| Name | Total Lines | Lines of Code | Total Coverage | Code Coverage |
|---|---|---|---|---|
| lib/buildr/java/tests.rb | 362 | 236 | 27.07%
|
24.15%
|
Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.
1 # Licensed to the Apache Software Foundation (ASF) under one or more |
2 # contributor license agreements. See the NOTICE file distributed with this |
3 # work for additional information regarding copyright ownership. The ASF |
4 # licenses this file to you under the Apache License, Version 2.0 (the |
5 # "License"); you may not use this file except in compliance with the License. |
6 # You may obtain a copy of the License at |
7 # |
8 # http://www.apache.org/licenses/LICENSE-2.0 |
9 # |
10 # Unless required by applicable law or agreed to in writing, software |
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
13 # License for the specific language governing permissions and limitations under |
14 # the License. |
15 |
16 |
17 require 'buildr/core/build' |
18 require 'buildr/core/compile' |
19 require 'buildr/java/ant' |
20 |
21 |
22 module Buildr |
23 |
24 class TestFramework::Java < TestFramework::Base |
25 |
26 class << self |
27 |
28 def applies_to?(project) #:nodoc: |
29 project.test.compile.language == :java || project.test.compile.language == :groovy |
30 end |
31 |
32 def dependencies |
33 unless @dependencies |
34 super |
35 # Add buildr utility classes (e.g. JavaTestFilter) |
36 @dependencies |= [ File.join(File.dirname(__FILE__)) ] |
37 end |
38 @dependencies |
39 end |
40 end |
41 |
42 private |
43 |
44 # Add buildr utilities (JavaTestFilter) to classpath |
45 Java.classpath << lambda { dependencies } |
46 |
47 # :call-seq: |
48 # filter_classes(dependencies, criteria) |
49 # |
50 # Return a list of classnames that match the given criteria. |
51 # The criteria parameter is a hash that must contain at least one of: |
52 # |
53 # * :class_names -- List of patterns to match against class name |
54 # * :interfaces -- List of java interfaces or java classes |
55 # * :class_annotations -- List of annotations on class level |
56 # * :method_annotations -- List of annotations on method level |
57 # * :fields -- List of java field names |
58 # |
59 def filter_classes(dependencies, criteria = {}) |
60 return [] unless task.compile.target |
61 target = task.compile.target.to_s |
62 candidates = Dir["#{target}/**/*.class"]. |
63 map { |file| Util.relative_path(file, target).ext('').gsub(File::SEPARATOR, '.') }. |
64 reject { |name| name =~ /\$./ } |
65 result = [] |
66 if criteria[:class_names] |
67 result.concat candidates.select { |name| criteria[:class_names].flatten.any? { |pat| pat === name } } |
68 end |
69 begin |
70 Java.load |
71 filter = Java.org.apache.buildr.JavaTestFilter.new(dependencies.to_java(Java.java.lang.String)) |
72 if criteria[:interfaces] |
73 filter.add_interfaces(criteria[:interfaces].to_java(Java.java.lang.String)) |
74 end |
75 if criteria[:class_annotations] |
76 filter.add_class_annotations(criteria[:class_annotations].to_java(Java.java.lang.String)) |
77 end |
78 if criteria[:method_annotations] |
79 filter.add_method_annotations(criteria[:method_annotations].to_java(Java.java.lang.String)) |
80 end |
81 if criteria[:fields] |
82 filter.add_fields(criteria[:fields].to_java(Java.java.lang.String)) |
83 end |
84 result.concat filter.filter(candidates.to_java(Java.java.lang.String)).map(&:to_s) |
85 rescue =>ex |
86 info "#{ex.class}: #{ex.message}" |
87 raise |
88 end |
89 end |
90 |
91 end |
92 |
93 |
94 # JMock is available when using JUnit and TestNG, JBehave. |
95 module JMock |
96 |
97 VERSION = '2.5.1' |
98 |
99 class << self |
100 def version |
101 Buildr.settings.build['jmock'] || VERSION |
102 end |
103 |
104 def dependencies |
105 two_or_later = version[0,1].to_i >= 2 |
106 group = two_or_later ? "org.jmock" : "jmock" |
107 |
108 @dependencies ||= ["#{group}:jmock:jar:#{version}"] |
109 if two_or_later |
110 @dependencies << "org.jmock:jmock-junit#{Buildr::JUnit.version.to_s[0,1]}:jar:#{version}" |
111 @dependencies << "org.hamcrest:hamcrest-core:jar:1.1" |
112 @dependencies << "org.hamcrest:hamcrest-library:jar:1.1" |
113 end |
114 @dependencies |
115 end |
116 |
117 private |
118 def const_missing(const) |
119 return super unless const == :REQUIRES # TODO: remove in 1.5 |
120 Buildr.application.deprecated "Please use JMock.dependencies/.version instead of JMock::REQUIRES/VERSION" |
121 dependencies |
122 end |
123 end |
124 end |
125 |
126 |
127 # JUnit test framework, the default test framework for Java tests. |
128 # |
129 # Support the following options: |
130 # * :fork -- If true/:once (default), fork for each test class. If :each, fork for each individual |
131 # test case. If false, run all tests in the same VM (fast, but dangerous). |
132 # * :clonevm -- If true clone the VM each time it is forked. |
133 # * :properties -- Hash of system properties available to the test case. |
134 # * :environment -- Hash of environment variables available to the test case. |
135 # * :java_args -- Arguments passed as is to the JVM. |
136 class JUnit < TestFramework::Java |
137 |
138 # Used by the junit:report task. Access through JUnit#report if you want to set various |
139 # options for that task, for example: |
140 # JUnit.report.frames = false |
141 class Report |
142 |
143 # Parameters passed to the Ant JUnitReport task. |
144 attr_reader :params |
145 # True (default) to produce a report using frames, false to produce a single-page report. |
146 attr_accessor :frames |
147 # Directory for the report style (defaults to using the internal style). |
148 attr_accessor :style_dir |
149 # Target directory for generated report. |
150 attr_accessor :target |
151 |
152 def initialize |
153 @params = {} |
154 @frames = true |
155 @target = 'reports/junit' |
156 end |
157 |
158 # :call-seq: |
159 # generate(projects, target?) |
160 # |
161 # Generates a JUnit report for these projects (must run JUnit tests first) into the |
162 # target directory. You can specify a target, or let it pick the default one from the |
163 # target attribute. |
164 def generate(projects, target = @target.to_s) |
165 html_in = File.join(target, 'html') |
166 rm_rf html_in ; mkpath html_in |
167 |
168 Buildr.ant('junit-report') do |ant| |
169 ant.taskdef :name=>'junitreport', :classname=>'org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator', |
170 :classpath=>Buildr.artifacts(JUnit.ant_taskdef).each(&:invoke).map(&:to_s).join(File::PATH_SEPARATOR) |
171 ant.junitreport :todir=>target do |
172 projects.select { |project| project.test.framework == :junit }. |
173 map { |project| project.test.report_to.to_s }.select { |path| File.exist?(path) }. |
174 each { |path| ant.fileset(:dir=>path) { ant.include :name=>'TEST-*.xml' } } |
175 options = { :format=>frames ? 'frames' : 'noframes' } |
176 options[:styledir] = style_dir if style_dir |
177 ant.report options.merge(:todir=>html_in) do |
178 params.each { |key, value| ant.param :name=>key, :expression=>value } |
179 end |
180 end |
181 end |
182 end |
183 |
184 end |
185 |
186 # JUnit version number. |
187 VERSION = '4.8.2' |
188 |
189 class << self |
190 # :call-seq: |
191 # report() |
192 # |
193 # Returns the Report object used by the junit:report task. You can use this object to set |
194 # various options that affect your report, for example: |
195 # JUnit.report.frames = false |
196 # JUnit.report.params['title'] = 'My App' |
197 def report |
198 @report ||= Report.new |
199 end |
200 |
201 def version |
202 Buildr.settings.build['junit'] || VERSION |
203 end |
204 |
205 def dependencies |
206 @dependencies ||= ["junit:junit:jar:#{version}"]+ JMock.dependencies |
207 end |
208 |
209 def ant_taskdef #:nodoc: |
210 "org.apache.ant:ant-junit:jar:#{Ant.version}" |
211 end |
212 |
213 private |
214 def const_missing(const) |
215 return super unless const == :REQUIRES # TODO: remove in 1.5 |
216 Buildr.application.deprecated "Please use JUnit.dependencies/.version instead of JUnit::REQUIRES/VERSION" |
217 dependencies |
218 end |
219 end |
220 |
221 def tests(dependencies) #:nodoc: |
222 if (self.class.version.to_s[0,1].to_i < 4) |
223 filter_classes(dependencies, :interfaces => %w{junit.framework.TestCase}) |
224 else |
225 filter_classes(dependencies, |
226 :interfaces => %w{junit.framework.TestCase}, |
227 :class_annotations => %w{org.junit.runner.RunWith}, |
228 :method_annotations => %w{org.junit.Test}) |
229 end |
230 |
231 end |
232 |
233 def run(tests, dependencies) #:nodoc: |
234 # Use Ant to execute the Junit tasks, gives us performance and reporting. |
235 Buildr.ant('junit') do |ant| |
236 case options[:fork] |
237 when false |
238 forking = {} |
239 when :each |
240 forking = { :fork=>true, :forkmode=>'perTest' } |
241 when true, :once |
242 forking = { :fork=>true, :forkmode=>'once' } |
243 else |
244 fail 'Option fork must be :once, :each or false.' |
245 end |
246 mkpath task.report_to.to_s |
247 |
248 taskdef = Buildr.artifact(JUnit.ant_taskdef) |
249 taskdef.invoke |
250 ant.taskdef :name=>'junit', :classname=>'org.apache.tools.ant.taskdefs.optional.junit.JUnitTask', :classpath=>taskdef.to_s |
251 |
252 ant.junit forking.merge(:clonevm=>options[:clonevm] || false, :dir=>task.send(:project).path_to) do |
253 ant.classpath :path=>dependencies.join(File::PATH_SEPARATOR) |
254 (options[:properties] || []).each { |key, value| ant.sysproperty :key=>key, :value=>value } |
255 (options[:environment] || []).each { |key, value| ant.env :key=>key, :value=>value } |
256 Array(options[:java_args]).each { |value| ant.jvmarg :value=>value } |
257 ant.formatter :type=>'plain' |
258 ant.formatter :type=>'plain', :usefile=>false # log test |
259 ant.formatter :type=>'xml' |
260 ant.batchtest :todir=>task.report_to.to_s, :failureproperty=>'failed' do |
261 ant.fileset :dir=>task.compile.target.to_s do |
262 tests.each { |test| ant.include :name=>File.join(*test.split('.')).ext('class') } |
263 end |
264 end |
265 end |
266 return tests unless ant.project.getProperty('failed') |
267 end |
268 # But Ant doesn't tell us what went kaput, so we'll have to parse the test files. |
269 tests.inject([]) do |passed, test| |
270 report_file = File.join(task.report_to.to_s, "TEST-#{test}.txt") |
271 if File.exist?(report_file) |
272 report = File.read(report_file) |
273 # The second line (if exists) is the status line and we scan it for its values. |
274 status = (report.split("\n")[1] || '').scan(/(run|failures|errors):\s*(\d+)/i). |
275 inject(Hash.new(0)) { |hash, pair| hash[pair[0].downcase.to_sym] = pair[1].to_i ; hash } |
276 passed << test if status[:failures] == 0 && status[:errors] == 0 |
277 end |
278 passed |
279 end |
280 end |
281 |
282 namespace 'junit' do |
283 desc "Generate JUnit tests report in #{report.target}" |
284 task('report') do |task| |
285 report.generate Project.projects |
286 info "Generated JUnit tests report in #{report.target}" |
287 end |
288 end |
289 |
290 task('clean') { rm_rf report.target.to_s } |
291 |
292 end |
293 |
294 |
295 # TestNG test framework. To use in your project: |
296 # test.using :testng |
297 # |
298 # Support the following options: |
299 # * :properties -- Hash of properties passed to the test suite. |
300 # * :java_args -- Arguments passed to the JVM. |
301 class TestNG < TestFramework::Java |
302 |
303 VERSION = '5.10' |
304 |
305 class << self |
306 def version |
307 Buildr.settings.build['testng'] || VERSION |
308 end |
309 |
310 def dependencies |
311 ["org.testng:testng:jar:jdk15:#{version}"]+ JMock.dependencies |
312 end |
313 |
314 private |
315 def const_missing(const) |
316 return super unless const == :REQUIRES # TODO: remove in 1.5 |
317 Buildr.application.deprecated "Please use TestNG.dependencies/.version instead of TestNG::REQUIRES/VERSION" |
318 dependencies |
319 end |
320 end |
321 |
322 def tests(dependencies) #:nodoc: |
323 filter_classes(dependencies, |
324 :class_annotations => %w{org.testng.annotations.Test}, |
325 :method_annotations => %w{org.testng.annotations.Test}) |
326 end |
327 |
328 def run(tests, dependencies) #:nodoc: |
329 cmd_args = ['-log', '2', '-sourcedir', task.compile.sources.join(';'), '-suitename', task.project.id ] |
330 cmd_args << '-d' << task.report_to.to_s |
331 # run all tests in the same suite |
332 cmd_args << '-testclass' << tests |
333 |
334 cmd_options = { :properties=>options[:properties], :java_args=>options[:java_args], |
335 :classpath=>dependencies, :name => "TestNG in #{task.send(:project).name}" } |
336 |
337 tmp = nil |
338 begin |
339 tmp = Tempfile.open("testNG") |
340 tmp.write cmd_args.join("\n") |
341 tmp.close |
342 Java::Commands.java ['org.testng.TestNG', "@#{tmp.path}"], cmd_options |
343 return tests |
344 rescue |
345 # testng-failed.xml contains the list of failed tests *only* |
346 report = File.read(File.join(task.report_to.to_s, 'testng-failed.xml')) |
347 failed = report.scan(/<class name="(.*?)">/im).flatten |
348 error "TestNG regexp returned unexpected failed tests #{failed.inspect}" unless (failed - tests).empty? |
349 # return the list of passed tests |
350 return tests - failed |
351 ensure |
352 tmp.close unless tmp.nil? |
353 end |
354 end |
355 |
356 end |
357 |
358 end # Buildr |
359 |
360 |
361 Buildr::TestFramework << Buildr::JUnit |
362 Buildr::TestFramework << Buildr::TestNG |
Generated on 2011-07-06 23:35:37 -0700 with rcov 0.9.8