Refactor runner and fix integration spec
This commit is contained in:
		
							parent
							
								
									96beff82b9
								
							
						
					
					
						commit
						cd35a6dcc6
					
				
					 9 changed files with 49 additions and 74 deletions
				
			
		
							
								
								
									
										1
									
								
								Gemfile
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								Gemfile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -6,6 +6,7 @@ gem 'immutable',           :git => 'https://github.com/dkubb/immutable.git', :br
 | 
			
		|||
gem 'descendants_tracker', :git => 'https://github.com/dkubb/descendants_tracker.git'
 | 
			
		||||
gem 'abstract_class',      :git => 'https://github.com/dkubb/abstract_class.git'
 | 
			
		||||
gem 'equalizer',           :git => 'https://github.com/dkubb/equalizer.git'
 | 
			
		||||
gem 'anima',               :git => 'https://github.com/mbj/anima.git'
 | 
			
		||||
gem 'to_source',           :git => 'https://github.com/mbj/to_source.git'
 | 
			
		||||
 | 
			
		||||
group :development do
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ require 'to_source'
 | 
			
		|||
require 'ice_nine'
 | 
			
		||||
require 'ice_nine/core_ext/object'
 | 
			
		||||
require 'backports'
 | 
			
		||||
require 'anima'
 | 
			
		||||
require 'diff/lcs'
 | 
			
		||||
require 'diff/lcs/hunk'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
module Mutant
 | 
			
		||||
  # Comandline adapter or mutant runner
 | 
			
		||||
  # Comandline parser
 | 
			
		||||
  class CLI
 | 
			
		||||
    include Immutable
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -16,17 +16,17 @@ module Mutant
 | 
			
		|||
    # @api private
 | 
			
		||||
    #
 | 
			
		||||
    def self.run(*arguments)
 | 
			
		||||
      error = Runner.run(new(*arguments).runner_options).fail?
 | 
			
		||||
      error = Runner.run(new(*arguments).attributes).fail?
 | 
			
		||||
      error ? 1 : 0
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Return options for runner
 | 
			
		||||
    # Return attributes
 | 
			
		||||
    #
 | 
			
		||||
    # @return [Hash]
 | 
			
		||||
    #
 | 
			
		||||
    # @api private
 | 
			
		||||
    #
 | 
			
		||||
    def runner_options
 | 
			
		||||
    def attributes
 | 
			
		||||
      { 
 | 
			
		||||
        :mutation_filter => mutation_filter,
 | 
			
		||||
        :matcher         => matcher,
 | 
			
		||||
| 
						 | 
				
			
			@ -34,12 +34,12 @@ module Mutant
 | 
			
		|||
        :killer          => Killer::Rspec::Forking
 | 
			
		||||
      }
 | 
			
		||||
    end
 | 
			
		||||
    memoize :runner_options
 | 
			
		||||
    memoize :attributes
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
    OPTIONS = {
 | 
			
		||||
      '--code' => [:add_filter, Mutation::Filter::Code].freeze
 | 
			
		||||
      '--code' => [:add_filter, Mutation::Filter::Code]
 | 
			
		||||
    }.deep_freeze
 | 
			
		||||
 | 
			
		||||
    OPTION_PATTERN = %r(\A-(?:-)?[a-z0-9]+\z).freeze
 | 
			
		||||
| 
						 | 
				
			
			@ -67,9 +67,7 @@ module Mutant
 | 
			
		|||
    def initialize(arguments)
 | 
			
		||||
      @filters, @matchers = [], []
 | 
			
		||||
 | 
			
		||||
      @arguments = arguments
 | 
			
		||||
 | 
			
		||||
      @index = 0
 | 
			
		||||
      @arguments, @index = arguments, 0
 | 
			
		||||
 | 
			
		||||
      while @index < @arguments.length
 | 
			
		||||
        dispatch
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,14 @@
 | 
			
		|||
module Mutant
 | 
			
		||||
  # Runner that allows to mutate an entire project
 | 
			
		||||
  class Runner
 | 
			
		||||
    include Immutable
 | 
			
		||||
    include Immutable, Anima
 | 
			
		||||
    extend MethodObject
 | 
			
		||||
 | 
			
		||||
    attribute :matcher
 | 
			
		||||
    attribute :killer
 | 
			
		||||
    attribute :reporter
 | 
			
		||||
    attribute :mutation_filter
 | 
			
		||||
 | 
			
		||||
    # Return killers with errors
 | 
			
		||||
    #
 | 
			
		||||
    # @return [Enumerable<Killer>]
 | 
			
		||||
| 
						 | 
				
			
			@ -28,42 +33,25 @@ module Mutant
 | 
			
		|||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
    # Return reporter
 | 
			
		||||
    # Initialize object
 | 
			
		||||
    #
 | 
			
		||||
    # @return [Reporter]
 | 
			
		||||
    #
 | 
			
		||||
    # @api private
 | 
			
		||||
    #
 | 
			
		||||
    def reporter; @reporter; end
 | 
			
		||||
 | 
			
		||||
    # Initialize runner object
 | 
			
		||||
    #
 | 
			
		||||
    # @param [Hash] options
 | 
			
		||||
    # @param [Hash] attributes
 | 
			
		||||
    #
 | 
			
		||||
    # @return [undefined]
 | 
			
		||||
    #
 | 
			
		||||
    # @api private
 | 
			
		||||
    #
 | 
			
		||||
    def initialize(options)
 | 
			
		||||
      @killer          = Helper.extract_option(options, :killer)
 | 
			
		||||
      @matcher         = Helper.extract_option(options, :matcher) 
 | 
			
		||||
      @reporter        = options.fetch(:reporter,        Reporter::Null)
 | 
			
		||||
      @mutation_filter = options.fetch(:mutation_filter, Mutation::Filter::ALL)
 | 
			
		||||
    def initialize(attributes)
 | 
			
		||||
      attributes[:reporter]        ||= Reporter::Null
 | 
			
		||||
      attributes[:mutation_filter] ||= Mutation::Filter::ALL
 | 
			
		||||
 | 
			
		||||
      super(attributes)
 | 
			
		||||
 | 
			
		||||
      @errors = []
 | 
			
		||||
 | 
			
		||||
      run
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Return subject enumerator
 | 
			
		||||
    #
 | 
			
		||||
    # @return [Enumerator<Subject>]
 | 
			
		||||
    #
 | 
			
		||||
    # @api private
 | 
			
		||||
    #
 | 
			
		||||
    def subjects
 | 
			
		||||
      @matcher.each
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Run mutation killers on subjects
 | 
			
		||||
    #
 | 
			
		||||
    # @return [undefined]
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +59,7 @@ module Mutant
 | 
			
		|||
    # @api private
 | 
			
		||||
    #
 | 
			
		||||
    def run
 | 
			
		||||
      subjects.each do |subject|
 | 
			
		||||
      matcher.each do |subject|
 | 
			
		||||
        reporter.subject(subject)
 | 
			
		||||
        run_subject(subject)
 | 
			
		||||
      end
 | 
			
		||||
| 
						 | 
				
			
			@ -111,13 +99,3 @@ module Mutant
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
    # Return candiate matcher enumerator
 | 
			
		||||
    #
 | 
			
		||||
    # @return [Enumerable<Class<Matcher>>]
 | 
			
		||||
    #
 | 
			
		||||
    # @api private
 | 
			
		||||
    #
 | 
			
		||||
    def candidate_matchers
 | 
			
		||||
      [Matcher::Method::Singleton, Matcher::Method::Instance].each
 | 
			
		||||
    end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,5 +23,6 @@ Gem::Specification.new do |gem|
 | 
			
		|||
  gem.add_runtime_dependency('immutable',           '~> 0.0.1')
 | 
			
		||||
  gem.add_runtime_dependency('equalizer',           '~> 0.0.1')
 | 
			
		||||
  gem.add_runtime_dependency('abstract_class',      '~> 0.0.1')
 | 
			
		||||
  gem.add_runtime_dependency('anima',               '~> 0.0.1')
 | 
			
		||||
  gem.add_runtime_dependency('diff-lcs',            '~> 1.1.3')
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,6 @@
 | 
			
		|||
require 'spec_helper'
 | 
			
		||||
 | 
			
		||||
describe Mutant, 'runner' do
 | 
			
		||||
  before do
 | 
			
		||||
    pending
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  around do |example|
 | 
			
		||||
    Dir.chdir(TestApp.root) do
 | 
			
		||||
      example.run
 | 
			
		||||
| 
						 | 
				
			
			@ -14,13 +10,13 @@ describe Mutant, 'runner' do
 | 
			
		|||
  it 'allows to run mutant over a project' do
 | 
			
		||||
    output = StringIO.new
 | 
			
		||||
    runner = Mutant::Runner.run(
 | 
			
		||||
      :pattern => /\ATestApp::/,
 | 
			
		||||
      :killer => Mutant::Killer::Rspec,
 | 
			
		||||
      :matcher => Mutant::Matcher::ObjectSpace.new(/\ATestApp::/),
 | 
			
		||||
      :reporter => Mutant::Reporter::CLI.new(output)
 | 
			
		||||
    )
 | 
			
		||||
    runner.fail?.should be(true)
 | 
			
		||||
    runner.errors.size.should be(22)
 | 
			
		||||
    output.rewind
 | 
			
		||||
    output.lines.grep(/Mutation/).size.should be(22)
 | 
			
		||||
    output.lines.grep(/Mutant alive:/).size.should be(22)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,8 +6,8 @@ shared_examples_for 'an invalid cli run' do
 | 
			
		|||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
describe Mutant::CLI, '#runner_options' do
 | 
			
		||||
  subject { object.runner_options }
 | 
			
		||||
describe Mutant::CLI, '#attributes' do
 | 
			
		||||
  subject { object.attributes }
 | 
			
		||||
 | 
			
		||||
  let(:object) { described_class.new(arguments) }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -5,22 +5,22 @@ describe Mutant::CLI, '.run' do
 | 
			
		|||
 | 
			
		||||
  let(:object)     { described_class                                       }
 | 
			
		||||
  let(:argv)       { mock('ARGV')                                          }
 | 
			
		||||
  let(:options)  { mock('Options')                                        }
 | 
			
		||||
  let(:attributes) { mock('Options')                                       }
 | 
			
		||||
  let(:runner)     { mock('Runner', :fail? => failure)                     }
 | 
			
		||||
  let(:instance) { mock(described_class.name, :runner_options => options) }
 | 
			
		||||
  let(:instance)   { mock(described_class.name, :attributes => attributes) }
 | 
			
		||||
 | 
			
		||||
  before do 
 | 
			
		||||
    described_class.stub(:new => instance)
 | 
			
		||||
    Mutant::Runner.stub(:run => runner)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  context 'when runner NOT fails' do
 | 
			
		||||
  context 'when runner does NOT fail' do
 | 
			
		||||
    let(:failure) { false }
 | 
			
		||||
 | 
			
		||||
    it { should be(0) }
 | 
			
		||||
 | 
			
		||||
    it 'should run with options' do
 | 
			
		||||
      Mutant::Runner.should_receive(:run).with(options).and_return(runner)
 | 
			
		||||
    it 'should run with attributes' do
 | 
			
		||||
      Mutant::Runner.should_receive(:run).with(attributes).and_return(runner)
 | 
			
		||||
      should be(0)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			@ -30,8 +30,8 @@ describe Mutant::CLI, '.run' do
 | 
			
		|||
 | 
			
		||||
    it { should be(1) }
 | 
			
		||||
 | 
			
		||||
    it 'should run with options' do
 | 
			
		||||
      Mutant::Runner.should_receive(:run).with(options).and_return(runner)
 | 
			
		||||
    it 'should run with attributes' do
 | 
			
		||||
      Mutant::Runner.should_receive(:run).with(attributes).and_return(runner)
 | 
			
		||||
      should be(1)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ describe Mutant::Matcher, '.from_string' do
 | 
			
		|||
    it_should_behave_like 'an idempotent method'
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  pending 'when more than one descendant handles input' do
 | 
			
		||||
  context 'when more than one descendant handles input' do
 | 
			
		||||
    let(:matcher_b) { mock('Matcher B') }
 | 
			
		||||
 | 
			
		||||
    before do
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue