class ChefSpec::Coverage

Constants

EXIT_FAILURE
EXIT_SUCCESS

Attributes

filters[R]

Public Class Methods

method_added(name) click to toggle source
# File lib/chefspec/coverage.rb, line 9
      def method_added(name)
        # Only delegate public methods
        if method_defined?(name)
          instance_eval <<-EOH, __FILE__, __LINE__ + 1
            def #{name}(*args, &block)
              instance.public_send(:#{name}, *args, &block)
            end
          EOH
        end
      end
new() click to toggle source

Create a new coverage object singleton.

# File lib/chefspec/coverage.rb, line 28
def initialize
  @collection = {}
  @filters    = {}
  @outputs    = []
  add_output do |report|

    erb = Erubis::Eruby.new(File.read(@template))
    puts erb.evaluate(report)
  rescue NameError => e
    raise Error::ErbTemplateParseError.new(original_error: e.message)

  end
  @template = ChefSpec.root.join("templates", "coverage", "human.erb")
end

Public Instance Methods

add(resource) click to toggle source

Add a resource to the resource collection. Only new resources are added and only resources that match the given filter are covered (which is * by default).

@param [Chef::Resource] resource

# File lib/chefspec/coverage.rb, line 116
def add(resource)
  if !exists?(resource) && !filtered?(resource)
    @collection[resource.to_s] = ResourceWrapper.new(resource)
  end
end
add_filter(filter = nil, &block) click to toggle source

Add a filter to the coverage analysis.

@param [Filter, String, Regexp] filter

the filter to add

@param [Proc] block

the block to use as a filter

@return [true]

# File lib/chefspec/coverage.rb, line 63
def add_filter(filter = nil, &block)
  id = "#{filter.inspect}/#{block.inspect}".hash

  @filters[id] = if filter.is_a?(Filter)
                   filter
                 elsif filter.is_a?(String)
                   StringFilter.new(filter)
                 elsif filter.is_a?(Regexp)
                   RegexpFilter.new(filter)
                 elsif block
                   BlockFilter.new(block)
                 else
                   raise ArgumentError, "Please specify either a string, " \
                     "filter, or block to filter source files with!"
                 end

  true
end
add_output(&block) click to toggle source

Add an output to send the coverage results to. @param [Proc] block

the block to use as the output

@return [true]

# File lib/chefspec/coverage.rb, line 89
def add_output(&block)
  @outputs << block
end
cover!(resource) click to toggle source

Called when a resource is matched to indicate it has been tested.

@param [Chef::Resource] resource

# File lib/chefspec/coverage.rb, line 127
def cover!(resource)
  wrapper = find(resource)
  wrapper.touch! if wrapper
end
filtered?(resource) click to toggle source

Called to check if a resource belongs to a cookbook from the specified directories.

@param [Chef::Resource] resource

# File lib/chefspec/coverage.rb, line 138
def filtered?(resource)
  filters.any? { |_, filter| filter.matches?(resource) }
end
report!() click to toggle source

Generate a coverage report. This report must be generated at_exit or else the entire resource collection may not be complete!

@example Generating a report

ChefSpec::Coverage.report!
# File lib/chefspec/coverage.rb, line 150
def report!
  # Borrowed from simplecov#41
  #
  # If an exception is thrown that isn't a "SystemExit", we need to capture
  # that error and re-raise.
  if $!
    exit_status = $!.is_a?(SystemExit) ? $!.status : EXIT_FAILURE
  else
    exit_status = EXIT_SUCCESS
  end

  report = {}.tap do |h|
    h[:total]     = @collection.size
    h[:touched]   = @collection.count { |_, resource| resource.touched? }
    h[:coverage]  = ((h[:touched] / h[:total].to_f) * 100).round(2)
  end

  report[:untouched_resources] = @collection.collect do |_, resource|
    resource unless resource.touched?
  end.compact
  report[:all_resources] = @collection.values

  @outputs.each do |block|
    instance_exec(report, &block)
  end

  # Ensure we exit correctly (#351)
  Kernel.exit(exit_status) if exit_status && exit_status > 0
end
set_template(file = "human.erb") click to toggle source

Change the template for reporting of converage analysis.

@param [string] path

The template file to use for the output of the report

@return [true]

# File lib/chefspec/coverage.rb, line 101
def set_template(file = "human.erb")
  @template = [
    ChefSpec.root.join("templates", "coverage", file),
    File.expand_path(file, Dir.pwd),
  ].find { |f| File.exist?(f) }
  raise Error::TemplateNotFound.new(path: file) unless @template
end
start!(&block) click to toggle source

Start the coverage reporting analysis. This method also adds the the at_exit handler for printing the coverage report.

# File lib/chefspec/coverage.rb, line 47
def start!(&block)
  warn("ChefSpec's coverage reporting is deprecated and will be removed in a future version")
  instance_eval(&block) if block
  at_exit { ChefSpec::Coverage.report! }
end

Private Instance Methods

exists?(resource) click to toggle source
# File lib/chefspec/coverage.rb, line 186
def exists?(resource)
  !find(resource).nil?
end
find(resource) click to toggle source
# File lib/chefspec/coverage.rb, line 182
def find(resource)
  @collection[resource.to_s]
end