Rename Runner to Killer
* Add working integration spec for rspec (mutant) killer.
This commit is contained in:
parent
c9219b1f1e
commit
23ee68ac1e
19 changed files with 183 additions and 102 deletions
|
@ -35,8 +35,8 @@ module Mutant
|
|||
end
|
||||
|
||||
require 'mutant/random'
|
||||
require 'mutant/runner'
|
||||
require 'mutant/runner/rspec'
|
||||
require 'mutant/killer'
|
||||
require 'mutant/killer/rspec'
|
||||
require 'mutant/mutator'
|
||||
require 'mutant/mutator/registry'
|
||||
require 'mutant/mutator/literal'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module Mutant
|
||||
# Abstract runner for tests
|
||||
class Runner
|
||||
# Abstract runner for mutant killers
|
||||
class Killer
|
||||
include Immutable, Abstract
|
||||
|
||||
# Run runner
|
96
lib/mutant/killer/rspec.rb
Normal file
96
lib/mutant/killer/rspec.rb
Normal file
|
@ -0,0 +1,96 @@
|
|||
module Mutant
|
||||
class Killer
|
||||
# Simple runner for rspec tests
|
||||
class Rspec < self
|
||||
|
||||
# Return error stream
|
||||
#
|
||||
# @return [StringIO]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
attr_reader :error_stream
|
||||
|
||||
# Return output stream
|
||||
#
|
||||
# @return [StringIO]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
attr_reader :output_stream
|
||||
|
||||
# Run block in clean rspec environment
|
||||
#
|
||||
# @return [self]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def self.nest
|
||||
original_world, original_configuration =
|
||||
::RSpec.instance_variable_get(:@world),
|
||||
::RSpec.instance_variable_get(:@configuration)
|
||||
|
||||
::RSpec.instance_variable_set(:@world,nil)
|
||||
::RSpec.instance_variable_set(:@configuration,nil)
|
||||
|
||||
yield
|
||||
|
||||
self
|
||||
ensure
|
||||
::RSpec.instance_variable_set(:@world,original_world)
|
||||
::RSpec.instance_variable_set(:@configuration,original_configuration)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Initialize rspec runner
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def initialize(*)
|
||||
@error_stream, @output_stream = StringIO.new, StringIO.new
|
||||
super
|
||||
end
|
||||
|
||||
# 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_arguments, error_stream, output_stream).zero?
|
||||
end
|
||||
|
||||
# Return command line arguments
|
||||
#
|
||||
# @return [Array]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def command_line_arguments
|
||||
%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
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,69 +0,0 @@
|
|||
module Mutant
|
||||
class Runner
|
||||
# Simple runner for rspec tests
|
||||
class Rspec < self
|
||||
|
||||
# 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
|
|
@ -59,6 +59,20 @@ module Mutant
|
|||
self
|
||||
end
|
||||
|
||||
# Insert AST node under context
|
||||
#
|
||||
# @param [Rubinius::AST::Node] node
|
||||
#
|
||||
# @return [self]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def insert(node)
|
||||
Loader.load(context.root(node))
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Initialize subject
|
||||
|
@ -76,19 +90,5 @@ module Mutant
|
|||
def initialize(context, node)
|
||||
@context, @node = context, node
|
||||
end
|
||||
|
||||
# Insert AST node under context
|
||||
#
|
||||
# @param [Rubinius::AST::Node] node
|
||||
#
|
||||
# @return [self]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def insert(node)
|
||||
Loader.load(context.root(node))
|
||||
|
||||
self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,11 +7,11 @@ class CodeLoadingSubject
|
|||
end
|
||||
|
||||
describe Mutant, 'code loading' do
|
||||
let(:context) { Mutant::Context::Constant.build(CodeLoadingSubject) }
|
||||
let(:node) { 'def foo; :bar; end'.to_ast }
|
||||
let(:root) { context.root(node) }
|
||||
|
||||
subject { Mutant::Loader.load(root) }
|
||||
let(:context) { Mutant::Context::Constant.build("/some/path",CodeLoadingSubject) }
|
||||
let(:node) { 'def foo; :bar; end'.to_ast }
|
||||
let(:root) { context.root(node) }
|
||||
|
||||
subject { Mutant::Loader.load(root) }
|
||||
|
||||
before { subject }
|
||||
|
||||
|
|
31
spec/integration/mutant/rspec_killer_spec.rb
Normal file
31
spec/integration/mutant/rspec_killer_spec.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant,'rspec integration' do
|
||||
around do |example|
|
||||
Dir.chdir(TestApp.root) do
|
||||
example.run
|
||||
end
|
||||
end
|
||||
|
||||
specify 'allows to run rspec with mutations' do
|
||||
|
||||
Mutant::Matcher::Method.parse('TestApp::Literal#string').each do |subject|
|
||||
subject.each do |mutation|
|
||||
Mutant::Killer::Rspec.nest do
|
||||
runner = Mutant::Killer::Rspec.run(subject,mutation)
|
||||
runner.killed?.should be(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Mutant::Matcher::Method.parse('TestApp::Literal#uncovered_string').each do |subject|
|
||||
subject.each do |mutation|
|
||||
Mutant::Killer::Rspec.nest do
|
||||
runner = Mutant::Killer::Rspec.run(subject,mutation)
|
||||
runner.killed?.should be(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -5,6 +5,9 @@ require 'rspec'
|
|||
# require spec support files and shared behavior
|
||||
Dir[File.expand_path('../{support,shared}/**/*.rb', __FILE__)].each { |f| require f }
|
||||
|
||||
$: << File.join(TestApp.root,'lib')
|
||||
require 'test_app'
|
||||
|
||||
require 'mutant'
|
||||
|
||||
RSpec.configure do |config|
|
||||
|
|
5
spec/support/test_app.rb
Normal file
5
spec/support/test_app.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
module TestApp
|
||||
def self.root
|
||||
File.expand_path('../../../test_app', __FILE__)
|
||||
end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Runner,'.run' do
|
||||
describe Mutant::Killer,'.run' do
|
||||
subject { class_under_test.run(mutation_subject,mutant) }
|
||||
|
||||
let(:mutation_subject) { mock('Subject', :insert => nil, :reset => nil) }
|
|
@ -1,6 +1,6 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Runner,'#killed?' do
|
||||
describe Mutant::Killer,'#killed?' do
|
||||
subject { object.killed? }
|
||||
|
||||
let(:object) { class_under_test.run(mutation_subject,mutant) }
|
|
@ -1,6 +1,6 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Runner,'#mutant' do
|
||||
describe Mutant::Killer,'#mutant' do
|
||||
subject { object.mutant }
|
||||
|
||||
let(:object) { class_under_test.run(mutation_subject, mutant) }
|
|
@ -1,10 +1,10 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Runner::Rspec, '.run' do
|
||||
describe Mutant::Killer::Rspec, '.run' do
|
||||
subject { object.run(context, mutant) }
|
||||
|
||||
let(:context) { mock('Context') }
|
||||
let(:mutant) { mock('Mutant') }
|
||||
let(:context) { mock('Context') }
|
||||
let(:mutant) { mock('Mutant') }
|
||||
|
||||
let(:object) { described_class }
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Runner::Rspec,'#error_stream' do
|
||||
describe Mutant::Killer::Rspec,'#error_stream' do
|
||||
subject { object.error_stream }
|
||||
|
||||
let(:object) { described_class.run(mutation_subject,mutant) }
|
|
@ -1,6 +1,6 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Runner::Rspec,'#output_stream' do
|
||||
describe Mutant::Killer::Rspec,'#output_stream' do
|
||||
subject { object.output_stream }
|
||||
|
||||
let(:object) { described_class.run(mutation_subject,mutant) }
|
|
@ -1,6 +1,6 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Runner,'#subject' do
|
||||
describe Mutant::Killer,'#subject' do
|
||||
subject { object.subject }
|
||||
|
||||
let(:object) { class_under_test.run(mutation_subject, mutant) }
|
|
@ -10,6 +10,10 @@ describe Mutant::Matcher::Method, '#each' do
|
|||
node
|
||||
end
|
||||
|
||||
define_method(:method) do
|
||||
TestApp::Literal.instance_method(:string)
|
||||
end
|
||||
|
||||
define_method(:constant) do
|
||||
::SampleSubjects::ExampleModule
|
||||
end
|
||||
|
|
|
@ -5,10 +5,22 @@ module TestApp
|
|||
true
|
||||
end
|
||||
|
||||
def self.freeze
|
||||
raise
|
||||
end
|
||||
|
||||
def string
|
||||
'string'
|
||||
end
|
||||
|
||||
def uncovered_string
|
||||
'string'
|
||||
end
|
||||
|
||||
def self.string
|
||||
'string'
|
||||
end
|
||||
|
||||
def symbol
|
||||
:symbol
|
||||
end
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# encoding: utf-8
|
||||
|
||||
require 'rspec'
|
||||
|
||||
require 'test_app'
|
||||
|
||||
# require spec support files and shared behavior
|
||||
|
|
Loading…
Reference in a new issue