C0 code coverage information
Generated on Wed Oct 07 08:34:03 -0700 2009 with rcov 0.8.2.1
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
30 end
31
32 end
33
34 private
35
36 # Add buildr utilities (JavaTestFilter) to classpath
37 Java.classpath << File.join(File.dirname(__FILE__))
38
39 # :call-seq:
40 # filter_classes(dependencies, criteria)
41 #
42 # Return a list of classnames that match the given criteria.
43 # The criteria parameter is a hash that must contain at least one of:
44 #
45 # * :class_names -- List of patterns to match against class name
46 # * :interfaces -- List of java interfaces or java classes
47 # * :class_annotations -- List of annotations on class level
48 # * :method_annotations -- List of annotations on method level
49 # * :fields -- List of java field names
50 #
51 def filter_classes(dependencies, criteria = {})
52 return [] unless task.compile.target
53 target = task.compile.target.to_s
54 candidates = Dir["#{target}/**/*.class"].
55 map { |file| Util.relative_path(file, target).ext('').gsub(File::SEPARATOR, '.') }.
56 reject { |name| name =~ /\$./ }
57 result = []
58 if criteria[:class_names]
59 result.concat candidates.select { |name| criteria[:class_names].flatten.any? { |pat| pat === name } }
60 end
61 begin
62 Java.load
63 filter = Java.org.apache.buildr.JavaTestFilter.new(dependencies.to_java(Java.java.lang.String))
64 if criteria[:interfaces]
65 filter.add_interfaces(criteria[:interfaces].to_java(Java.java.lang.String))
66 end
67 if criteria[:class_annotations]
68 filter.add_class_annotations(criteria[:class_annotations].to_java(Java.java.lang.String))
69 end
70 if criteria[:method_annotations]
71 filter.add_method_annotations(criteria[:method_annotations].to_java(Java.java.lang.String))
72 end
73 if criteria[:fields]
74 filter.add_fields(criteria[:fields].to_java(Java.java.lang.String))
75 end
76 result.concat filter.filter(candidates.to_java(Java.java.lang.String)).map(&:to_s)
77 rescue =>ex
78 info "#{ex.class}: #{ex.message}"
79 raise
80 end
81 end
82
83 end
84
85
86 # JMock is available when using JUnit and TestNG, JBehave.
87 module JMock
88
89 VERSION = '1.2.0'
90
91 class << self
92 def version
93 Buildr.settings.build['jmock'] || VERSION
94 end
95
96 def dependencies
97 @dependencies ||= ["jmock:jmock:jar:#{version}"]
98 end
99
100 private
101 def const_missing(const)
102 return super unless const == :REQUIRES # TODO: remove in 1.5
103 Buildr.application.deprecated "Please use JMock.dependencies/.version instead of JMock::REQUIRES/VERSION"
104 dependencies
105 end
106 end
107 end
108
109
110 # JUnit test framework, the default test framework for Java tests.
111 #
112 # Support the following options:
113 # * :fork -- If true/:once (default), fork for each test class. If :each, fork for each individual
114 # test case. If false, run all tests in the same VM (fast, but dangerous).
115 # * :clonevm -- If true clone the VM each time it is forked.
116 # * :properties -- Hash of system properties available to the test case.
117 # * :environment -- Hash of environment variables available to the test case.
118 # * :java_args -- Arguments passed as is to the JVM.
119 class JUnit < TestFramework::Java
120
121 # Used by the junit:report task. Access through JUnit#report if you want to set various
122 # options for that task, for example:
123 # JUnit.report.frames = false
124 class Report
125
126 # Parameters passed to the Ant JUnitReport task.
127 attr_reader :params
128 # True (default) to produce a report using frames, false to produce a single-page report.
129 attr_accessor :frames
130 # Directory for the report style (defaults to using the internal style).
131 attr_accessor :style_dir
132 # Target directory for generated report.
133 attr_accessor :target
134
135 def initialize
136 @params = {}
137 @frames = true
138 @target = 'reports/junit'
139 end
140
141 # :call-seq:
142 # generate(projects, target?)
143 #
144 # Generates a JUnit report for these projects (must run JUnit tests first) into the
145 # target directory. You can specify a target, or let it pick the default one from the
146 # target attribute.
147 def generate(projects, target = @target.to_s)
148 html_in = File.join(target, 'html')
149 rm_rf html_in ; mkpath html_in
150
151 Buildr.ant('junit-report') do |ant|
152 ant.taskdef :name=>'junitreport', :classname=>'org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator',
153 :classpath=>Buildr.artifacts(JUnit.ant_taskdef).each(&:invoke).map(&:to_s).join(File::PATH_SEPARATOR)
154 ant.junitreport :todir=>target do
155 projects.select { |project| project.test.framework == :junit }.
156 map { |project| project.test.report_to.to_s }.select { |path| File.exist?(path) }.
157 each { |path| ant.fileset(:dir=>path) { ant.include :name=>'TEST-*.xml' } }
158 options = { :format=>frames ? 'frames' : 'noframes' }
159 options[:styledir] = style_dir if style_dir
160 ant.report options.merge(:todir=>html_in) do
161 params.each { |key, value| ant.param :name=>key, :expression=>value }
162 end
163 end
164 end
165 end
166
167 end
168
169 # JUnit version number.
170 VERSION = '4.5'
171
172 class << self
173 # :call-seq:
174 # report()
175 #
176 # Returns the Report object used by the junit:report task. You can use this object to set
177 # various options that affect your report, for example:
178 # JUnit.report.frames = false
179 # JUnit.report.params['title'] = 'My App'
180 def report
181 @report ||= Report.new
182 end
183
184 def version
185 Buildr.settings.build['junit'] || VERSION
186 end
187
188 def dependencies
189 @dependencies ||= ["junit:junit:jar:#{version}"]+ JMock.dependencies
190 end
191
192 def ant_taskdef #:nodoc:
193 "org.apache.ant:ant-junit:jar:#{Ant.version}"
194 end
195
196 private
197 def const_missing(const)
198 return super unless const == :REQUIRES # TODO: remove in 1.5
199 Buildr.application.deprecated "Please use JUnit.dependencies/.version instead of JUnit::REQUIRES/VERSION"
200 dependencies
201 end
202 end
203
204 def tests(dependencies) #:nodoc:
205 filter_classes(dependencies,
206 :interfaces => %w{junit.framework.TestCase},
207 :class_annotations => %w{org.junit.runner.RunWith},
208 :method_annotations => %w{org.junit.Test})
209 end
210
211 def run(tests, dependencies) #:nodoc:
212 # Use Ant to execute the Junit tasks, gives us performance and reporting.
213 Buildr.ant('junit') do |ant|
214 case options[:fork]
215 when false
216 forking = {}
217 when :each
218 forking = { :fork=>true, :forkmode=>'perTest' }
219 when true, :once
220 forking = { :fork=>true, :forkmode=>'once' }
221 else
222 fail 'Option fork must be :once, :each or false.'
223 end
224 mkpath task.report_to.to_s
225
226 taskdef = Buildr.artifact(JUnit.ant_taskdef)
227 taskdef.invoke
228 ant.taskdef :name=>'junit', :classname=>'org.apache.tools.ant.taskdefs.optional.junit.JUnitTask', :classpath=>taskdef.to_s
229
230 ant.junit forking.merge(:clonevm=>options[:clonevm] || false, :dir=>task.send(:project).path_to) do
231 ant.classpath :path=>dependencies.join(File::PATH_SEPARATOR)
232 (options[:properties] || []).each { |key, value| ant.sysproperty :key=>key, :value=>value }
233 (options[:environment] || []).each { |key, value| ant.env :key=>key, :value=>value }
234 Array(options[:java_args]).each { |value| ant.jvmarg :value=>value }
235 ant.formatter :type=>'plain'
236 ant.formatter :type=>'plain', :usefile=>false # log test
237 ant.formatter :type=>'xml'
238 ant.batchtest :todir=>task.report_to.to_s, :failureproperty=>'failed' do
239 ant.fileset :dir=>task.compile.target.to_s do
240 tests.each { |test| ant.include :name=>File.join(*test.split('.')).ext('class') }
241 end
242 end
243 end
244 return tests unless ant.project.getProperty('failed')
245 end
246 # But Ant doesn't tell us what went kaput, so we'll have to parse the test files.
247 tests.inject([]) do |passed, test|
248 report_file = File.join(task.report_to.to_s, "TEST-#{test}.txt")
249 if File.exist?(report_file)
250 report = File.read(report_file)
251 # The second line (if exists) is the status line and we scan it for its values.
252 status = (report.split("\n")[1] || '').scan(/(run|failures|errors):\s*(\d+)/i).
253 inject(Hash.new(0)) { |hash, pair| hash[pair[0].downcase.to_sym] = pair[1].to_i ; hash }
254 passed << test if status[:failures] == 0 && status[:errors] == 0
255 end
256 passed
257 end
258 end
259
260 namespace 'junit' do
261 desc "Generate JUnit tests report in #{report.target}"
262 task('report') do |task|
263 report.generate Project.projects
264 info "Generated JUnit tests report in #{report.target}"
265 end
266 end
267
268 task('clean') { rm_rf report.target.to_s }
269
270 end
271
272
273 # TestNG test framework. To use in your project:
274 # test.using :testng
275 #
276 # Support the following options:
277 # * :properties -- Hash of properties passed to the test suite.
278 # * :java_args -- Arguments passed to the JVM.
279 class TestNG < TestFramework::Java
280
281 VERSION = '5.10'
282
283 class << self
284 def version
285 Buildr.settings.build['testng'] || VERSION
286 end
287
288 def dependencies
289 ["org.testng:testng:jar:jdk15:#{version}"]+ JMock.dependencies
290 end
291
292 private
293 def const_missing(const)
294 return super unless const == :REQUIRES # TODO: remove in 1.5
295 Buildr.application.deprecated "Please use TestNG.dependencies/.version instead of TestNG::REQUIRES/VERSION"
296 dependencies
297 end
298 end
299
300 def tests(dependencies) #:nodoc:
301 filter_classes(dependencies,
302 :class_annotations => %w{org.testng.annotations.Test},
303 :method_annotations => %w{org.testng.annotations.Test})
304 end
305
306 def run(tests, dependencies) #:nodoc:
307 cmd_args = [ 'org.testng.TestNG', '-log', '2', '-sourcedir', task.compile.sources.join(';'), '-suitename', task.project.id ]
308 cmd_args << '-d' << task.report_to.to_s
309 # run all tests in the same suite
310 cmd_args << '-testclass' << tests
311 cmd_options = { :properties=>options[:properties], :java_args=>options[:java_args],
312 :classpath=>dependencies, :name => "TestNG in #{task.send(:project).name}" }
313
314 begin
315 Java::Commands.java cmd_args, cmd_options
316 return tests
317 rescue
318 # testng-failed.xml contains the list of failed tests *only*
319 report = File.read(File.join(task.report_to.to_s, 'testng-failed.xml'))
320 failed = report.scan(/<class name="(.*?)">/im).flatten
321 error "TestNG regexp returned unexpected failed tests #{failed.inspect}" unless (failed - tests).empty?
322 # return the list of passed tests
323 return tests - failed
324 end
325 end
326
327 end
328
329 end # Buildr
330
331
332 Buildr::TestFramework << Buildr::JUnit
333 Buildr::TestFramework << Buildr::TestNG
Generated using the rcov code coverage analysis tool for Ruby
version 0.8.2.1.