diff --git a/lib/mutant.rb b/lib/mutant.rb index 1d791320..0358aad7 100644 --- a/lib/mutant.rb +++ b/lib/mutant.rb @@ -36,7 +36,7 @@ end require 'mutant/random' require 'mutant/runner' -#require 'mutant/runner/rspec' +require 'mutant/runner/rspec' require 'mutant/mutator' require 'mutant/mutator/registry' require 'mutant/mutator/literal' diff --git a/lib/mutant/runner/rspec.rb b/lib/mutant/runner/rspec.rb new file mode 100644 index 00000000..171a5d48 --- /dev/null +++ b/lib/mutant/runner/rspec.rb @@ -0,0 +1,69 @@ +module Mutant + class Runner + # Simple runner for rspec tests + class Rspec < Runner + + # Return error stream + # + # @return [StringIO] + # + # @api private + # + def error_stream + StringIO.new + end + + # Return output stream + # + # @return [StringIO] + # + # @api private + # + def output_stream + StringIO.new + end + + private + + # Run rspec test + # + # @return [true] + # returns true when test is NOT successful and the mutant was killed + # + # @return [false] + # returns false otherwise + # + # @api private + # + def run + !RSpec::Core::Runner.run(command_line,error_stream,output_stream).zero? + end + + # Return command line + # + # @return [Array] + # + # @api private + # + def command_line + %W( + --fail-fast + ) + Dir[filename_pattern] + end + + # Return rspec filename pattern + # + # @return [String] + # + # @api private + # + # TODO: Add an option or be clever and only run affected specs. + # + def filename_pattern + 'spec/unit/**/*_spec.rb' + end + + memoize :output_stream, :error_stream + end + end +end diff --git a/spec/unit/mutant/runner/rspec/class_methods/run_spec.rb b/spec/unit/mutant/runner/rspec/class_methods/run_spec.rb new file mode 100644 index 00000000..4481b8af --- /dev/null +++ b/spec/unit/mutant/runner/rspec/class_methods/run_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +describe Mutant::Runner::Rspec, '.run' do + subject { object.run(context, mutant) } + + let(:context) { mock('Context') } + let(:mutant) { mock('Mutant') } + + let(:object) { described_class } + + before do + context.stub(:insert => context) + context.stub(:reset => context) + RSpec::Core::Runner.stub(:run => exit_status) + end + + context 'when run exits zero' do + let(:exit_status) { 0 } + + its(:killed?) { should be(false) } + it { should be_a(described_class) } + end + + context 'when run exits nonzero' do + let(:exit_status) { 1 } + + its(:killed?) { should be(true) } + it { should be_a(described_class) } + end +end diff --git a/spec/unit/mutant/runner/rspec/error_stream_spec.rb b/spec/unit/mutant/runner/rspec/error_stream_spec.rb new file mode 100644 index 00000000..534f32b0 --- /dev/null +++ b/spec/unit/mutant/runner/rspec/error_stream_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +describe Mutant::Runner::Rspec,'#error_stream' do + subject { object.error_stream } + + let(:object) { described_class.run(mutation_subject,mutant) } + let(:mutation_subject) { mock('Subject', :insert => nil,:reset => nil) } + let(:mutant) { mock('Mutant') } + + before do + RSpec::Core::Runner.stub(:run => 1) + end + + it_should_behave_like 'an idempotent method' + + it { should be_kind_of(StringIO) } + + its(:read) { should eql('') } +end diff --git a/spec/unit/mutant/runner/rspec/output_stream_spec.rb b/spec/unit/mutant/runner/rspec/output_stream_spec.rb new file mode 100644 index 00000000..5ba9a7e9 --- /dev/null +++ b/spec/unit/mutant/runner/rspec/output_stream_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +describe Mutant::Runner::Rspec,'#output_stream' do + subject { object.output_stream } + + let(:object) { described_class.run(mutation_subject,mutant) } + let(:mutation_subject) { mock('Subject', :insert => nil,:reset => nil) } + let(:mutant) { mock('Mutant') } + + before do + RSpec::Core::Runner.stub(:run => 1) + end + + it_should_behave_like 'an idempotent method' + + it { should be_kind_of(StringIO) } + + its(:read) { should eql('') } +end