atpsoft/dohtest

View on GitHub
lib/dohtest/group_runner.rb

Summary

Maintainability
A
2 hrs
Test Coverage
require 'dohtest/test_group'
require 'dohtest/configure'

module DohTest

class GroupRunner
  def initialize(group_class, output, config = nil)
    @group_class,@output = group_class,output
    @config = config || DohTest.config
    @group_name = @group_class.to_s
    @before_all_failed = false
    @error_count = @tests_ran = @tests_skipped = @assertions_failed = @assertions_passed = 0
    @test_name = 'no_test_name_set_yet'
    @max_errors = 0
    @max_failures = 0
    @has_brink = false
  end

  def run
    @output.group_begin(@group_name)
    if create_group
      run_before_all
      run_tests unless @before_all_failed
      run_after_all
    end
    @output.group_end(@group_name, @tests_ran, @tests_skipped, @assertions_passed, @assertions_failed)
    past_brink?
  end

  def create_group
    @group = @group_class.new
  rescue => error
    caught_error(error, 'initialize')
    false
  else
    @group.runner = self
    true
  end

  def run_before_all
    @group.before_all if @group.respond_to?(:before_all)
    @config[:pre_group_callback].each do |callback|
      if (!callback.call(@group))
        @error_count += 1
        @output.callback_failed(callback.inspect)
      end
    end
  rescue => error
    @before_all_failed = true
    caught_error(error, 'before_all')
  end

  def run_after_all
    @group.after_all if @group.respond_to?(:after_all)
    @config[:post_group_callback].each do |callback|
      if (!callback.call(total_problems))
        @error_count += 1
        @output.callback_failed(callback.inspect)
      end
    end
  rescue => error
    caught_error(error, 'after_all')
  end

  def find_before_each_method
    has_before_each = @group.respond_to?(:before_each)
    has_setup = @group.respond_to?(:setup)
    if has_before_each && has_setup
      raise ":before_each and :setup both defined; please pick one"
    elsif has_before_each
      @before_each_method = :before_each
    elsif has_setup
      @before_each_method = :setup
    else
      @before_each_method = nil
    end
  end

  def find_after_each_method
    has_after_each = @group.respond_to?(:after_each)
    has_teardown = @group.respond_to?(:teardown)
    if has_after_each && has_teardown
      raise ":after_each and :teardown both defined; please pick one"
    elsif has_after_each
      @after_each_method = :after_each
    elsif has_teardown
      @after_each_method = :teardown
    else
      @after_each_method = nil
    end
  end

  def run_before_each
    @config[:pre_each_callback].each do |callback|
      if !callback.call
        @error_count += 1
        @output.callback_failed(callback.inspect)
      end
    end
    @group.send(@before_each_method) if @before_each_method
  rescue => error
    @before_each_failed = true
    caught_error(error)
  end

  def run_after_each
    @group.send(@after_each_method) if @after_each_method
    @config[:post_each_callback].each do |callback|
      if !callback.call
        @error_count += 1
        @output.callback_failed(callback.inspect)
      end
    end
  rescue => error
    caught_error(error)
  end

  def run_test_method
    @group.send(@test_name)
  rescue DohTest::Failure => failure
    @assertions_failed += 1
    @output.assertion_failed(@group_name, @test_name, failure, @config[:dynamic_seed])
  rescue => error
    caught_error(error)
  end

  def setup_brink
    @max_errors = @config[:max_errors].to_i
    @max_failures = @config[:max_failures].to_i

    @has_brink = (@max_errors > 0) || (@max_failures > 0)
  end

  def past_brink?
    ((@max_errors > 0) && (@error_count >= @max_errors)) ||
    ((@max_failures > 0) && (@assertions_failed >= @max_failures))
  end

  def generate_new_seed
    if @config[:dynamic_seed]
      @config[:dynamic_seed] = rand(100000000000)
      srand(@config[:dynamic_seed])
    else
      @config[:dynamic_seed] = @config[:seed]
    end
  end

  def run_tests
    determine_test_methods
    find_before_each_method
    find_after_each_method
    setup_brink

    @test_methods.each do |method_name|
      break if @has_brink && past_brink?
      generate_new_seed
      @test_name = method_name
      @before_each_failed = false
      @output.test_begin(@group_name, @test_name)
      run_before_each
      run_test_method unless @before_each_failed
      run_after_each
      @tests_ran += 1
      @output.test_end(@group_name, @test_name)
    end
  end

  def determine_test_methods
    @test_methods = @group_class.public_instance_methods.grep(/^test/)
    return unless @config.key?(:grep)
    original_test_count = @test_methods.size
    grep_filter = Regexp.new(@config[:grep])
    @test_methods.select! { |method| method.to_s =~ grep_filter }
    @tests_skipped = original_test_count - @test_methods.size
  end

  def assertion_passed
    @assertions_passed += 1
    @output.assertion_passed(@group_name, @test_name)
  end

  def caught_error(error, test_name = nil)
    @error_count += 1
    @output.test_error(@group_name, test_name || @test_name, error, @config[:dynamic_seed])
  end

  def total_problems
    @error_count + @assertions_failed
  end
end

end