C0 code coverage information

Generated on Wed Oct 07 08:33:56 -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.
Name Total lines Lines of code Total coverage Code coverage
lib/buildr/core/checks.rb 254 110
96.1%  
90.9%  
  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/project'
 18 autoload :Spec, 'spec'
 19 
 20 
 21 module Buildr
 22   # Methods added to Project to allow checking the build.
 23   module Checks
 24 
 25     module Matchers #:nodoc:
 26 
 27       class << self
 28 
 29         # Define matchers that operate by calling a method on the tested object.
 30         # For example:
 31         #   foo.should contain(bar)
 32         # calls:
 33         #   foo.contain(bar)
 34         def match_using(*names)
 35           names.each do |name|
 36             matcher = Class.new do
 37               # Initialize with expected arguments (i.e. contain(bar) initializes with bar).
 38               define_method(:initialize) { |*args| @expects = args }
 39               # Matches against actual value (i.e. foo.should exist called with foo).
 40               define_method(:matches?) do |actual|
 41                 @actual = actual
 42                 return actual.send("#{name}?", *@expects) if actual.respond_to?("#{name}?")
 43                 return actual.send(name, *@expects) if actual.respond_to?(name)
 44                 raise "You can't check #{actual}, it doesn't respond to #{name}."
 45               end
 46               # Some matchers have arguments, others don't, treat appropriately.
 47               define_method :failure_message do
 48                 args = " " + @expects.map{ |arg| "'#{arg}'" }.join(", ") unless @expects.empty?
 49                 "Expected #{@actual} to #{name}#{args}"
 50               end
 51               define_method :negative_failure_message do
 52                 args = " " + @expects.map{ |arg| "'#{arg}'" }.join(", ") unless @expects.empty?
 53                 "Expected #{@actual} to not #{name}#{args}"
 54               end
 55             end
 56             # Define method to create matcher.
 57             define_method(name) { |*args| matcher.new(*args) }
 58           end
 59         end
 60 
 61       end
 62 
 63       # Define delegate matchers for exist and contain methods.
 64       match_using :exist, :contain
 65 
 66     end
 67 
 68 
 69     # An expectation has subject, description and block. The expectation is validated by running the block,
 70     # and can access the subject from the method #it. The description is used for reporting.
 71     #
 72     # The expectation is run by calling #run_against. You can share expectations by running them against
 73     # different projects (or any other context for that matter).
 74     #
 75     # If the subject is missing, it is set to the argument of #run_against, typically the project itself.
 76     # If the description is missing, it is set from the project. If the block is missing, the default behavior
 77     # prints "Pending" followed by the description. You can use this to write place holders and fill them later.
 78     class Expectation
 79 
 80       attr_reader :description, :subject, :block
 81 
 82       # :call-seq:
 83       #   initialize(subject, description?) { .... }
 84       #   initialize(description?) { .... }
 85       #
 86       # First argument is subject (returned from it method), second argument is description. If you omit the
 87       # description, it will be set from the subject. If you omit the subject, it will be set from the object
 88       # passed to run_against.
 89       def initialize(*args, &block)
 90         @description = args.pop if String === args.last
 91         @subject = args.shift
 92         raise ArgumentError, "Expecting subject followed by description, and either one is optional. Not quite sure what to do with this list of arguments." unless args.empty?
 93         @block = block || lambda { info "Pending: #{description}" }
 94       end
 95 
 96       # :call-seq:
 97       #   run_against(context)
 98       #
 99       # Runs this expectation against the context object. The context object is different from the subject,
100       # but used as the subject if no subject specified (i.e. returned from the it method).
101       #
102       # This method creates a new context object modeled after the context argument, but a separate object
103       # used strictly for running this expectation, and used only once. The context object will pass methods
104       # to the context argument, so you can call any method, e.g. package(:jar).
105       #
106       # It also adds all matchers defined in Buildr and RSpec, and two additional methods:
107       # * it() -- Returns the subject.
108       # * description() -- Returns the description.
109       def run_against(context)
110         subject = @subject || context
111         description = @description ? "#{subject} #{@description}" : subject.to_s
112         # Define anonymous class and load it with:
113         # - All instance methods defined in context, so we can pass method calls to the context.
114         # - it() method to return subject, description() method to return description.
115         # - All matchers defined by Buildr and RSpec.
116         klass = Class.new
117         klass.instance_eval do
118           context.class.instance_methods.each do |method|
119             define_method(method) { |*args| context.send(method, *args) } unless instance_methods.include?(method)
120           end
121           define_method(:it) { subject }
122           define_method(:description) { description }
123           include Spec::Matchers
124           include Matchers
125         end
126 
127         # Run the expectation. We only print the expectation name when tracing (to know they all ran),
128         # or when we get a failure.
129         begin
130           trace description
131           klass.new.instance_eval &@block
132         rescue Exception=>error
133           raise error.exception("#{description}\n#{error}").tap { |wrapped| wrapped.set_backtrace(error.backtrace) }
134         end
135       end
136 
137     end
138 
139 
140     include Extension
141 
142     before_define do |project|
143       # The check task can do any sort of interesting things, but the most important is running expectations.
144       project.task("check") do |task|
145         project.expectations.inject(true) do |passed, expect|
146           begin
147             expect.run_against project
148             passed
149           rescue Exception=>ex
150             if verbose
151               error ex.backtrace.select { |line| line =~ /#{Buildr.application.buildfile}/ }.join("\n")
152               error ex
153             end
154             false
155           end
156         end or fail "Checks failed for project #{project.name} (see errors above)."
157       end
158       project.task("package").enhance do |task|
159         # Run all actions before checks.
160         task.enhance { project.task("check").invoke }
161       end
162     end
163 
164 
165     # :call-seq:
166     #    check(description) { ... }
167     #    check(subject, description) { ... }
168     #
169     # Adds an expectation. The expectation is run against the project by the check task, executed after packaging.
170     # You can access any package created by the project.
171     #
172     # An expectation is written using a subject, description and block to validate the expectation. For example:
173     #
174     # For example:
175     #   check package(:jar), "should exist" do
176     #     it.should exist
177     #   end
178     #   check package(:jar), "should contain a manifest" do
179     #     it.should contain("META-INF/MANIFEST.MF")
180     #   end
181     #   check package(:jar).path("com/acme"), "should contain classes" do
182     #     it.should_not be_empty
183     #   end
184     #   check package(:jar).entry("META-INF/MANIFEST"), "should be a recent license" do
185     #     it.should contain(/Copyright (C) 2007/)
186     #   end
187     #
188     # If you omit the subject, the project is used as the subject. If you omit the description, the subject is
189     # used as description.
190     #
191     # During development you can write placeholder expectations by omitting the block. This will simply report
192     # the expectation as pending.
193     def check(*args, &block)
194       expectations << Checks::Expectation.new(*args, &block)
195     end
196 
197     # :call-seq:
198     #   expectations() => Expectation*
199     #
200     # Returns a list of expectations (see #check).
201     def expectations()
202       @expectations ||= []
203     end
204 
205   end
206 
207 end
208 
209 
210 module Rake #:nodoc:
211   class FileTask
212 
213     # :call-seq:
214     #   exist?() => boolean
215     #
216     # Returns true if this file exists.
217     def exist?()
218       File.exist?(name)
219     end
220 
221     # :call-seq:
222     #   empty?() => boolean
223     #
224     # Returns true if file/directory is empty.
225     def empty?()
226       File.directory?(name) ? Dir.glob("#{name}/*").empty? : File.read(name).empty?
227     end
228 
229     # :call-seq:
230     #   contain?(pattern*) => boolean
231     #   contain?(file*) => boolean
232     #
233     # For a file, returns true if the file content matches against all the arguments. An argument may be
234     # a string or regular expression.
235     #
236     # For a directory, return true if the directory contains the specified files. You can use relative
237     # file names and glob patterns (using *, **, etc).
238     def contain?(*patterns)
239       if File.directory?(name)
240         patterns.map { |pattern| "#{name}/#{pattern}" }.all? { |pattern| !Dir[pattern].empty? }
241       else
242         contents = File.read(name)
243         patterns.map { |pattern| Regexp === pattern ? pattern : Regexp.new(Regexp.escape(pattern.to_s)) }.
244           all? { |pattern| contents =~ pattern }
245       end
246     end
247 
248   end
249 end
250 
251 
252 class Buildr::Project
253   include Buildr::Checks
254 end

Generated using the rcov code coverage analysis tool for Ruby version 0.8.2.1.

Valid XHTML 1.0! Valid CSS!