mutant 0.3.0.beta14 → 0.3.0.beta15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c1b02e2a004b27eb4c96785f88d431d6f352ad5b
4
- data.tar.gz: 12d62f0e44af09e2711244278c8cdfe67e512fa6
3
+ metadata.gz: 1042e4c0fc2031a03918edcdfdfa7dfcdac388e7
4
+ data.tar.gz: b4f7f5d0b9d8e4ac9d59a147e8b25860d173145f
5
5
  SHA512:
6
- metadata.gz: f2cb7ddcbee74e216a95bed6f22fe576fadbe0230d06e08b8bd15ee933338029c0351dc9833925fb2cabb203d31b88d4b147ba98f584f1e04db75f7c3d8bca9d
7
- data.tar.gz: 750a4ea68ad7d76e8b8f0d6a5825c9c16a703324c20c1e5bfcd46fea48a8620134b4d31cdf3cbcf02e1db5bc0f68957d6b23964f55647f3927dedd203edd0cb3
6
+ metadata.gz: 85fadf546e6df77875b1d36ce8c9010037a1ed94571ec3e48b92ac73c89729d62321910872046295cbdf757ca715b88f1bf0b714ed0e9f5d443705664dc8454f
7
+ data.tar.gz: af84ddf9ba4c27c335b7c58c48a35e899bc568871ab53141db7f175ed99cdb3383c4307ee9b257fc5ef61ec15307dbfcb9ab981c5b65fcb1c489e6ffd4fc3097
data/Gemfile.devtools CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  group :development do
4
4
  gem 'rake', '~> 10.1.0'
5
- gem 'rspec', '~> 2.13.0'
5
+ gem 'rspec', '~> 2.14.1'
6
6
  gem 'yard', '~> 0.8.6.2'
7
7
  end
8
8
 
@@ -14,7 +14,7 @@ group :guard do
14
14
  gem 'guard', '~> 1.8.1'
15
15
  gem 'guard-bundler', '~> 1.0.0'
16
16
  gem 'guard-rspec', '~> 3.0.2'
17
- gem 'guard-rubocop', '~> 0.2.0'
17
+ # gem 'guard-rubocop', '~> 0.2.0'
18
18
 
19
19
  # file system change event handling
20
20
  gem 'listen', '~> 1.2.2'
@@ -30,13 +30,17 @@ end
30
30
 
31
31
  group :metrics do
32
32
  gem 'coveralls', '~> 0.6.7'
33
- gem 'flay', '~> 2.3.0'
34
- gem 'flog', '~> 4.1.0'
33
+ gem 'flay', '~> 2.3.1'
34
+ gem 'flog', '~> 4.1.1'
35
35
  gem 'reek', '~> 1.3.1', :git => 'https://github.com/troessner/reek.git'
36
- gem 'rubocop', '~> 0.9.1'
36
+ # gem 'rubocop', '~> 0.9.1'
37
37
  gem 'simplecov', '~> 0.7.1'
38
38
  gem 'yardstick', '~> 0.9.6'
39
39
 
40
+ platforms :ruby_19, :ruby_20 do
41
+ gem 'yard-spellcheck', '~> 0.1.5'
42
+ end
43
+
40
44
  platforms :ruby_19 do
41
45
  gem 'json', '~> 1.8.0'
42
46
  end
@@ -0,0 +1,31 @@
1
+ AllCops:
2
+ Includes:
3
+ - '../**/*.rake'
4
+ Excludes:
5
+ - '../vendor/**'
6
+
7
+ # Avoid parameter lists longer than five parameters.
8
+ ParameterLists:
9
+ Max: 3
10
+ CountKeywordArgs: true
11
+
12
+ # Avoid more than `Max` levels of nesting.
13
+ BlockNesting:
14
+ Max: 3
15
+
16
+ # Align with the style guide.
17
+ CollectionMethods:
18
+ PreferredMethods:
19
+ collect: 'map'
20
+ inject: 'reduce'
21
+ find: 'detect'
22
+ find_all: 'select'
23
+
24
+ # Do not force public/protected/private keyword to be indented at the same
25
+ # level as the def keyword. My personal preference is to outdent these keywords
26
+ # because I think when scanning code it makes it easier to identify the
27
+ # sections of code and visually separate them. When the keyword is at the same
28
+ # level I think it sort of blends in with the def keywords and makes it harder
29
+ # to scan the code and see where the sections are.
30
+ AccessControl:
31
+ Enabled: false
data/lib/mutant/cli.rb CHANGED
@@ -56,12 +56,13 @@ module Mutant
56
56
  #
57
57
  def config
58
58
  Config.new(
59
- :cache => @cache,
60
- :debug => debug?,
61
- :matcher => matcher,
62
- :filter => filter,
63
- :strategy => strategy,
64
- :reporter => reporter
59
+ :cache => @cache,
60
+ :debug => debug?,
61
+ :matcher => matcher,
62
+ :filter => filter,
63
+ :fail_fast => !!@fail_fast,
64
+ :strategy => strategy,
65
+ :reporter => reporter
65
66
  )
66
67
  end
67
68
  memoize :config
@@ -151,6 +152,16 @@ module Mutant
151
152
  @filters << klass.new(filter)
152
153
  end
153
154
 
155
+ # Set fail fast
156
+ #
157
+ # @api private
158
+ #
159
+ # @return [undefined]
160
+ #
161
+ def set_fail_fast
162
+ @fail_fast = true
163
+ end
164
+
154
165
  # Set debug mode
155
166
  #
156
167
  # @api private
@@ -252,6 +263,8 @@ module Mutant
252
263
 
253
264
  opts.on('--code FILTER', 'Adds a code filter') do |filter|
254
265
  add_filter Mutation::Filter::Code, filter
266
+ end.on('--fail-fast', 'Fail fast') do
267
+ set_fail_fast
255
268
  end.on('-d','--debug', 'Enable debugging output') do
256
269
  set_debug
257
270
  end.on_tail('-h', '--help', 'Show this message') do
data/lib/mutant/config.rb CHANGED
@@ -2,7 +2,7 @@ module Mutant
2
2
  # The configuration of a mutator run
3
3
  class Config
4
4
  include Adamantium::Flat, Anima.new(
5
- :cache, :debug, :strategy, :matcher, :filter, :reporter
5
+ :cache, :debug, :strategy, :matcher, :filter, :reporter, :fail_fast
6
6
  )
7
7
 
8
8
  # Enumerate subjects
data/lib/mutant/runner.rb CHANGED
@@ -1,8 +1,57 @@
1
1
  module Mutant
2
2
  # Runner baseclass
3
3
  class Runner
4
- include Adamantium::Flat, AbstractType, Equalizer.new(:config)
5
- extend MethodObject
4
+ include Adamantium::Flat, AbstractType
5
+
6
+ REGISTRY = {}
7
+
8
+ # Register handler
9
+ #
10
+ # @param [Class] klass
11
+ #
12
+ # @return [undefined]
13
+ #
14
+ # @api private
15
+ #
16
+ def self.register(klass)
17
+ REGISTRY[klass]=self
18
+ end
19
+ private_class_method :register
20
+
21
+ # Lookup runner
22
+ #
23
+ # @param [Class] klass
24
+ #
25
+ # @return [undefined]
26
+ #
27
+ # @api private
28
+ #
29
+ def self.lookup(klass)
30
+ current = klass
31
+ while current
32
+ handler = REGISTRY.fetch(current) do
33
+ current = current.superclass; nil
34
+ end
35
+ return handler if handler
36
+ end
37
+
38
+ raise ArgumentError, "No handler for: #{klass}"
39
+ end
40
+ private_class_method :lookup
41
+
42
+ # Run runner for object
43
+ #
44
+ # @param [Config] config
45
+ # @param [Object] object
46
+ #
47
+ # @return [Runner]
48
+ #
49
+ # @api private
50
+ #
51
+ def self.run(config, object)
52
+ handler = lookup(object.class)
53
+ handler.new(config, object)
54
+ end
6
55
 
7
56
  # Return config
8
57
  #
@@ -27,6 +76,18 @@ module Mutant
27
76
  @end = Time.now
28
77
  end
29
78
 
79
+ # Test if runner should stop
80
+ #
81
+ # @return [true]
82
+ # if runner should stop
83
+ #
84
+ # @return [false]
85
+ # otherwise
86
+ #
87
+ def stop?
88
+ !!@stop
89
+ end
90
+
30
91
  # Return runtime
31
92
  #
32
93
  # @return [Float]
@@ -34,22 +95,17 @@ module Mutant
34
95
  # @api private
35
96
  #
36
97
  def runtime
37
- @end - @start
98
+ (@end || Time.now) - @start
38
99
  end
39
- memoize :runtime
40
100
 
41
- # Test if runner failed
42
- #
43
- # @return [true]
44
- # if failed
101
+ # Return reporter
45
102
  #
46
- # @return [false]
47
- # otherwise
103
+ # @return [Reporter]
48
104
  #
49
105
  # @api private
50
106
  #
51
- def failed?
52
- !success?
107
+ def reporter
108
+ config.reporter
53
109
  end
54
110
 
55
111
  # Test if runner is successful
@@ -64,16 +120,6 @@ module Mutant
64
120
  #
65
121
  abstract_method :success?
66
122
 
67
- # Return reporter
68
- #
69
- # @return [Reporter]
70
- #
71
- # @api private
72
- #
73
- def reporter
74
- config.reporter
75
- end
76
-
77
123
  private
78
124
 
79
125
  # Perform operation
@@ -96,5 +142,36 @@ module Mutant
96
142
  reporter.report(object)
97
143
  end
98
144
 
145
+ # Perform dispatch
146
+ #
147
+ # @return [Enumerable<Runner>]
148
+ #
149
+ # @api private
150
+ #
151
+ def dispatch(input)
152
+ collection = []
153
+ input.each do |object|
154
+ runner = visit(object)
155
+ collection << runner
156
+ if runner.stop?
157
+ @stop = true
158
+ break
159
+ end
160
+ end
161
+ collection
162
+ end
163
+
164
+ # Visit object
165
+ #
166
+ # @param [Object] object
167
+ #
168
+ # @return [undefined]
169
+ #
170
+ # @api private
171
+ #
172
+ def visit(object)
173
+ Runner.run(config, object)
174
+ end
175
+
99
176
  end # Runner
100
177
  end # Mutant
@@ -3,6 +3,22 @@ module Mutant
3
3
  # Runner for object config
4
4
  class Config < self
5
5
 
6
+ register Mutant::Config
7
+
8
+ # Run runner for object
9
+ #
10
+ # @param [Config] config
11
+ # @param [Object] object
12
+ #
13
+ # @return [Runner]
14
+ #
15
+ # @api private
16
+ #
17
+ def self.run(config)
18
+ handler = lookup(config.class)
19
+ handler.new(config)
20
+ end
21
+
6
22
  # Return subject runners
7
23
  #
8
24
  # @return [Enumerable<Runner::Subject>]
@@ -18,7 +34,7 @@ module Mutant
18
34
  # @api private
19
35
  #
20
36
  def failed_subjects
21
- subjects.select(&:failed?)
37
+ subjects.reject(&:success?)
22
38
  end
23
39
  memoize :failed_subjects
24
40
 
@@ -58,9 +74,7 @@ module Mutant
58
74
  def run_subjects
59
75
  strategy = self.strategy
60
76
  strategy.setup
61
- @subjects = config.subjects.map do |subject|
62
- Subject.run(config, subject)
63
- end
77
+ @subjects = dispatch(config.subjects)
64
78
  strategy.teardown
65
79
  end
66
80
 
@@ -4,6 +4,8 @@ module Mutant
4
4
  class Mutation < self
5
5
  include Concord::Public.new(:config, :mutation)
6
6
 
7
+ register Mutant::Mutation
8
+
7
9
  # Return killer instance
8
10
  #
9
11
  # @return [Killer]
@@ -50,7 +52,8 @@ module Mutant
50
52
  #
51
53
  def run
52
54
  @killer = config.strategy.kill(mutation)
53
- report(@killer)
55
+ report(killer)
56
+ @stop = config.fail_fast && !killer.success?
54
57
  end
55
58
 
56
59
  end # Mutation
@@ -4,13 +4,7 @@ module Mutant
4
4
  class Subject < self
5
5
  include Concord::Public.new(:config, :subject)
6
6
 
7
- # Return subject
8
- #
9
- # @return [Subject]
10
- #
11
- # @api private
12
- #
13
- attr_reader :subject
7
+ register Mutant::Subject
14
8
 
15
9
  # Initialize object
16
10
  #
@@ -41,7 +35,7 @@ module Mutant
41
35
  # @api private
42
36
  #
43
37
  def failed_mutations
44
- mutations.select(&:failed?)
38
+ mutations.reject(&:success?)
45
39
  end
46
40
  memoize :failed_mutations
47
41
 
@@ -70,9 +64,7 @@ module Mutant
70
64
  def run
71
65
  subject = self.subject
72
66
  report(subject)
73
- @mutations = subject.map do |mutation|
74
- Mutation.run(config, mutation)
75
- end
67
+ @mutations = dispatch(subject.mutations)
76
68
  report(self)
77
69
  end
78
70
 
@@ -3,38 +3,18 @@ module Mutant
3
3
  class Subject
4
4
  include AbstractType, Adamantium::Flat, Enumerable, Concord::Public.new(:context, :node)
5
5
 
6
- # Enumerate possible mutations
6
+ # Return mutations
7
7
  #
8
- # @return [self]
9
- # returns self if block given
10
- #
11
- # @return [Enumerator<Mutation>]
12
- # returns eumerator if no block given
13
- #
14
- # @api private
15
- #
16
- def each
17
- return to_enum unless block_given?
18
-
19
- yield noop_mutation
20
-
21
- mutations.each do |mutation|
22
- yield mutation
23
- end
24
-
25
- self
26
- end
27
-
28
- # Return noop mutation
29
- #
30
- # @return [Mutation::Noop]
8
+ # @return [Enumerable<Mutation>]
31
9
  #
32
10
  # @api private
33
11
  #
34
- def noop
35
- Mutation::Neutral.new(self, node)
12
+ def mutations
13
+ mutations = []
14
+ generate_mutations(mutations)
15
+ mutations
36
16
  end
37
- memoize :noop
17
+ memoize :mutations
38
18
 
39
19
  # Return source path
40
20
  #
@@ -122,5 +102,15 @@ module Mutant
122
102
  Mutation::Neutral::Noop.new(self, node)
123
103
  end
124
104
 
105
+ # Generate mutations
106
+ #
107
+ # @param [#<<] emitter
108
+ #
109
+ # @return [undefined]
110
+ #
111
+ # @api private
112
+ #
113
+ abstract_method :generate_mutations
114
+
125
115
  end # Subject
126
116
  end # Mutant
@@ -29,13 +29,16 @@ module Mutant
29
29
 
30
30
  # Return mutations
31
31
  #
32
- # @return [Enumerable<Mutation>]
32
+ # @param [#<<] emitter
33
+ #
34
+ # @return [undefined]
33
35
  #
34
36
  # @api private
35
37
  #
36
- def mutations
37
- Mutator.each(node).map do |mutant|
38
- Mutation::Evil.new(self, mutant)
38
+ def generate_mutations(emitter)
39
+ emitter << noop_mutation
40
+ Mutator.each(node) do |mutant|
41
+ emitter << Mutation::Evil.new(self, mutant)
39
42
  end
40
43
  end
41
44
 
data/mutant.gemspec CHANGED
@@ -2,13 +2,14 @@
2
2
 
3
3
  Gem::Specification.new do |gem|
4
4
  gem.name = 'mutant'
5
- gem.version = '0.3.0.beta14'
5
+ gem.version = '0.3.0.beta15'
6
6
  gem.authors = [ 'Markus Schirp' ]
7
7
  gem.email = [ 'mbj@schirp-dso.com' ]
8
8
 
9
9
  gem.description = 'Mutation testing for ruby'
10
10
  gem.summary = 'Mutation testing tool for ruby under MRI and Rubinius'
11
11
  gem.homepage = 'https://github.com/mbj/mutant'
12
+ gem.license = 'MIT'
12
13
 
13
14
  gem.require_paths = [ 'lib' ]
14
15
  gem.files = `git ls-files`.split("\n")
@@ -16,7 +17,7 @@ Gem::Specification.new do |gem|
16
17
  gem.extra_rdoc_files = %w[TODO LICENSE]
17
18
  gem.executables = [ 'mutant', 'zombie' ]
18
19
 
19
- gem.add_runtime_dependency('parser', '~> 2.0.pre2')
20
+ gem.add_runtime_dependency('parser', '~> 2.0.0.pre2')
20
21
  gem.add_runtime_dependency('unparser', '~> 0.0.8')
21
22
  gem.add_runtime_dependency('ice_nine', '~> 0.8.0')
22
23
  gem.add_runtime_dependency('descendants_tracker', '~> 0.0.1')
@@ -25,5 +26,5 @@ Gem::Specification.new do |gem|
25
26
  gem.add_runtime_dependency('inflecto', '~> 0.0.2')
26
27
  gem.add_runtime_dependency('anima', '~> 0.0.6')
27
28
  gem.add_runtime_dependency('concord', '~> 0.1.1')
28
- gem.add_runtime_dependency('rspec', '~> 2.13.0')
29
+ gem.add_runtime_dependency('rspec', '~> 2.14.1')
29
30
  end
data/spec/spec_helper.rb CHANGED
@@ -24,4 +24,7 @@ RSpec.configure do |config|
24
24
  config.include(CompressHelper)
25
25
  config.include(ParserHelper)
26
26
  config.include(Mutant::NodeHelpers)
27
+ config.mock_with :rspec do |config|
28
+ config.syntax = [:expect, :should]
29
+ end
27
30
  end
@@ -8,31 +8,41 @@ describe Mutant::Runner::Config, '#subjects' do
8
8
  let(:config) do
9
9
  double(
10
10
  'Config',
11
- :subjects => [mutation_subject],
11
+ :class => Mutant::Config,
12
+ :subjects => [subject_a, subject_b],
12
13
  :strategy => strategy,
13
14
  :reporter => reporter
14
15
  )
15
16
  end
16
17
 
17
- let(:reporter) { double('Reporter') }
18
- let(:strategy) { double('Strategy') }
19
- let(:mutation_subject) { double('Mutation subject') }
20
- let(:subject_runner) { double('Subject runner') }
21
-
22
- class DummySubjectRunner
23
- include Concord::Public.new(:config, :mutation)
24
-
25
- def self.run(*args); new(*args); end
26
- end
18
+ let(:reporter) { double('Reporter') }
19
+ let(:strategy) { double('Strategy') }
20
+ let(:subject_a) { double('Subject A') }
21
+ let(:subject_b) { double('Subject B') }
22
+ let(:runner_a) { double('Runner A', :stop? => stop_a) }
23
+ let(:runner_b) { double('Runner B', :stop? => stop_b) }
27
24
 
28
25
  before do
29
26
  strategy.stub(:setup)
30
27
  strategy.stub(:teardown)
31
28
  reporter.stub(:report => reporter)
32
- stub_const('Mutant::Runner::Subject', DummySubjectRunner)
29
+ Mutant::Runner.stub(:run).with(config, subject_a).and_return(runner_a)
30
+ Mutant::Runner.stub(:run).with(config, subject_b).and_return(runner_b)
33
31
  end
34
32
 
35
- it { should eql([DummySubjectRunner.new(config, mutation_subject)]) }
33
+ context 'without earily stop' do
34
+ let(:stop_a) { false }
35
+ let(:stop_b) { false }
36
+ it { should eql([runner_a, runner_b]) }
37
+ it_should_behave_like 'an idempotent method'
38
+ end
39
+
40
+
41
+ context 'with earily stop' do
42
+ let(:stop_a) { true }
43
+ let(:stop_b) { false }
44
+ it { should eql([runner_a]) }
45
+ it_should_behave_like 'an idempotent method'
46
+ end
36
47
 
37
- it_should_behave_like 'an idempotent method'
38
48
  end
@@ -3,50 +3,45 @@ require 'spec_helper'
3
3
  describe Mutant::Runner::Config, '#success?' do
4
4
  subject { object.success? }
5
5
 
6
- let(:object) { described_class.run(config) }
6
+ let(:object) { described_class.new(config) }
7
7
 
8
8
  let(:config) do
9
9
  double(
10
10
  'Config',
11
11
  :reporter => reporter,
12
12
  :strategy => strategy,
13
- :subjects => subjects
13
+ :subjects => [subject_a, subject_b]
14
14
  )
15
15
  end
16
16
 
17
- let(:reporter) { double('Reporter') }
18
- let(:strategy) { double('Strategy') }
19
- let(:subjects) { [subject_a, subject_b] }
20
- let(:subject_a) { double('Subject A', :fails? => false) }
21
- let(:subject_b) { double('Subject B', :fails? => false) }
22
-
23
- class DummySubjectRunner
24
- include Concord::Public.new(:config, :subject)
25
-
26
- def self.run(*args)
27
- new(*args)
28
- end
29
-
30
- def failed?
31
- @subject.fails?
32
- end
33
- end
17
+ let(:reporter) { double('Reporter') }
18
+ let(:strategy) { double('Strategy') }
19
+ let(:subject_a) { double('Subject A') }
20
+ let(:subject_b) { double('Subject B') }
21
+ let(:runner_a) { double('Runner A', :stop? => stop_a, :success? => success_a) }
22
+ let(:runner_b) { double('Runner B', :stop? => stop_b, :success? => success_b) }
34
23
 
35
24
  before do
36
- stub_const('Mutant::Runner::Subject', DummySubjectRunner)
37
25
  reporter.stub(:report => reporter)
38
26
  strategy.stub(:setup)
39
27
  strategy.stub(:teardown)
28
+ Mutant::Runner.stub(:run).with(config, subject_a).and_return(runner_a)
29
+ Mutant::Runner.stub(:run).with(config, subject_b).and_return(runner_b)
40
30
  end
41
31
 
42
32
  context 'without failed subjects' do
33
+ let(:stop_a) { false }
34
+ let(:stop_b) { false }
35
+ let(:success_a) { true }
36
+ let(:success_b) { true }
43
37
  it { should be(true) }
44
38
  end
45
39
 
46
40
  context 'with failing subjects' do
47
- before do
48
- subject_a.stub(:fails? => true)
49
- end
41
+ let(:stop_a) { false }
42
+ let(:stop_b) { false }
43
+ let(:success_a) { false }
44
+ let(:success_b) { true }
50
45
 
51
46
  it { should be(false) }
52
47
  end
@@ -6,15 +6,18 @@ describe Mutant::Runner::Mutation, '#killer' do
6
6
  let(:config) do
7
7
  double(
8
8
  'Config',
9
- :reporter => reporter,
10
- :strategy => strategy
9
+ :fail_fast => fail_fast,
10
+ :reporter => reporter,
11
+ :strategy => strategy
11
12
  )
12
13
  end
13
14
 
14
- let(:reporter) { double('Reporter') }
15
- let(:mutation) { double('Mutation') }
16
- let(:strategy) { double('Strategy') }
17
- let(:killer) { double('Killer') }
15
+ let(:reporter) { double('Reporter') }
16
+ let(:mutation) { double('Mutation', :class => Mutant::Mutation) }
17
+ let(:strategy) { double('Strategy') }
18
+ let(:killer) { double('Killer', :success? => success) }
19
+ let(:fail_fast) { false }
20
+ let(:success) { false }
18
21
 
19
22
  subject { object.killer }
20
23
 
@@ -3,47 +3,49 @@ require 'spec_helper'
3
3
  describe Mutant::Runner::Subject, '#success?' do
4
4
  subject { object.success? }
5
5
 
6
- let(:object) { described_class.run(config, mutation_subject) }
6
+ let(:object) { described_class.new(config, mutation_subject) }
7
+
8
+ let(:mutation_subject) {
9
+ double(
10
+ 'Subject',
11
+ :class => Mutant::Subject,
12
+ :mutations => [mutation_a, mutation_b]
13
+ )
14
+ }
7
15
 
8
16
  let(:reporter) { double('Reporter') }
9
- let(:mutation_subject) { double('Subject', :map => mutations) }
10
17
  let(:config) { double('Config', :reporter => reporter) }
11
- let(:mutation_a) { double('Mutation A', :failed? => false) }
12
- let(:mutation_b) { double('Mutation B', :failed? => false) }
13
- let(:mutations) { [mutation_a, mutation_b] }
18
+ let(:mutation_a) { double('Mutation A') }
19
+ let(:mutation_b) { double('Mutation B') }
20
+
21
+ let(:runner_a) { double('Runner A', :success? => success_a, :stop? => stop_a) }
22
+ let(:runner_b) { double('Runner B', :success? => success_b, :stop? => stop_b) }
14
23
 
15
24
  before do
16
25
  reporter.stub(:report => reporter)
26
+ Mutant::Runner.stub(:run).with(config, mutation_a).and_return(runner_a)
27
+ Mutant::Runner.stub(:run).with(config, mutation_b).and_return(runner_b)
17
28
  end
18
29
 
19
- class DummyMutationRunner
20
- include Concord::Public.new(:config, :mutation)
30
+ context 'with failing mutations' do
31
+ let(:stop_a) { false }
32
+ let(:stop_b) { false }
33
+ let(:success_a) { false }
34
+ let(:success_b) { true }
21
35
 
22
- def self.run(*args)
23
- new(*args)
24
- end
36
+ it { should be(false) }
25
37
 
26
- def failed?
27
- @mutation.failed?
28
- end
38
+ it_should_behave_like 'an idempotent method'
29
39
  end
30
40
 
31
- before do
32
- stub_const('Mutant::Runner::Mutation', DummyMutationRunner)
33
- end
41
+ context 'without failing mutations' do
42
+ let(:stop_a) { false }
43
+ let(:stop_b) { false }
44
+ let(:success_a) { true }
45
+ let(:success_b) { true }
34
46
 
35
- context 'without evil failed mutations' do
36
47
  it { should be(true) }
37
- end
38
-
39
- context 'with failing noop mutation' do
40
- end
41
48
 
42
- context 'with failing evil mutations' do
43
- before do
44
- mutation_a.stub(:failed? => true)
45
- end
46
-
47
- it { should be(false) }
49
+ it_should_behave_like 'an idempotent method'
48
50
  end
49
51
  end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Subject, '#mutations' do
4
+ subject { object.mutations }
5
+
6
+ let(:class_under_test) do
7
+ mutation_a, mutation_b = self.mutation_a, self.mutation_b
8
+ Class.new(described_class) do
9
+ define_method(:generate_mutations) do |emitter|
10
+ emitter << mutation_a
11
+ emitter << mutation_b
12
+ end
13
+ end
14
+ end
15
+
16
+ let(:object) { class_under_test.new(context, node) }
17
+ let(:node) { double('Node') }
18
+ let(:context) { double('Context') }
19
+ let(:mutation_a) { double('Mutation A') }
20
+ let(:mutation_b) { double('Mutation B') }
21
+
22
+ it { should eql([mutation_a, mutation_b]) }
23
+ end
@@ -3,7 +3,7 @@ shared_examples_for 'a method filter parse result' do
3
3
  expected_class.stub(:new => response)
4
4
  end
5
5
 
6
- let(:response) { mock('Response') }
6
+ let(:response) { double('Response') }
7
7
 
8
8
  it { should be(response) }
9
9
 
@@ -8,10 +8,9 @@ shared_examples_for 'a method match' do
8
8
  let(:method_arity) { values.fetch(:method_arity) }
9
9
  let(:scope) { values.fetch(:scope) }
10
10
  let(:node_class) { values.fetch(:node_class) }
11
-
12
- let(:node) { mutation_subject.node }
13
- let(:context) { mutation_subject.context }
14
- let(:mutation_subject) { subject.first }
11
+ let(:node) { mutation_subject.node }
12
+ let(:context) { mutation_subject.context }
13
+ let(:mutation_subject) { subject.first }
15
14
 
16
15
  it 'should return one subject' do
17
16
  subject.size.should be(1)
@@ -1,11 +1,11 @@
1
1
  shared_examples_for 'a mutator' do
2
2
  subject { object.each(node) { |item| yields << item } }
3
3
 
4
- let(:yields) { [] }
5
- let(:object) { described_class }
4
+ let(:yields) { [] }
5
+ let(:object) { described_class }
6
6
 
7
7
  unless instance_methods.map(&:to_s).include?('node')
8
- let(:node) { source.to_ast }
8
+ let(:node) { source.to_ast }
9
9
  end
10
10
 
11
11
  it_should_behave_like 'a command method'
@@ -1,9 +1,9 @@
1
1
  # encoding: utf-8
2
- require 'test_app'
3
- require 'rspec'
4
2
 
5
- $: << File.join(File.dirname(__FILE__), 'lib')
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '../lib')
6
4
 
5
+ require 'test_app'
6
+ require 'rspec'
7
7
 
8
8
  # require spec support files and shared behavior
9
9
  Dir[File.expand_path('../{support,shared}/**/*.rb', __FILE__)].each { |f| require f }
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe TestApp::Literal,'#string' do
4
- subject { object.command(mock) }
3
+ describe TestApp::Literal, '#string' do
4
+ subject { object.command(double) }
5
5
 
6
6
  let(:object) { described_class.new }
7
7
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mutant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0.beta14
4
+ version: 0.3.0.beta15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Markus Schirp
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: 2.0.pre2
19
+ version: 2.0.0.pre2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
- version: 2.0.pre2
26
+ version: 2.0.0.pre2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: unparser
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - ~>
144
144
  - !ruby/object:Gem::Version
145
- version: 2.13.0
145
+ version: 2.14.1
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - ~>
151
151
  - !ruby/object:Gem::Version
152
- version: 2.13.0
152
+ version: 2.14.1
153
153
  description: Mutation testing for ruby
154
154
  email:
155
155
  - mbj@schirp-dso.com
@@ -180,6 +180,7 @@ files:
180
180
  - config/flog.yml
181
181
  - config/mutant.yml
182
182
  - config/reek.yml
183
+ - config/rubocop.yml
183
184
  - config/yardstick.yml
184
185
  - lib/mutant.rb
185
186
  - lib/mutant/cache.rb
@@ -340,14 +341,13 @@ files:
340
341
  - spec/unit/mutant/mutator/self_spec.rb
341
342
  - spec/unit/mutant/runner/config/subjects_spec.rb
342
343
  - spec/unit/mutant/runner/config/success_predicate_spec.rb
343
- - spec/unit/mutant/runner/failed_predicte_spec.rb
344
344
  - spec/unit/mutant/runner/mutation/killer_spec.rb
345
345
  - spec/unit/mutant/runner/subject/success_predicate_spec.rb
346
346
  - spec/unit/mutant/strategy/method_expansion/class_methods/run_spec.rb
347
347
  - spec/unit/mutant/strategy/rspec/dm2/lookup/method/instance/spec_files_spec.rb
348
348
  - spec/unit/mutant/strategy/rspec/dm2/lookup/method/singleton/spec_files_spec.rb
349
349
  - spec/unit/mutant/subject/context_spec.rb
350
- - spec/unit/mutant/subject/each_spec.rb
350
+ - spec/unit/mutant/subject/mutations_spec.rb
351
351
  - spec/unit/mutant/subject/node_spec.rb
352
352
  - test_app/.rspec
353
353
  - test_app/lib/test_app.rb
@@ -364,7 +364,8 @@ files:
364
364
  - test_app/spec/unit/test_app/literal/command_spec.rb
365
365
  - test_app/spec/unit/test_app/literal/string_spec.rb
366
366
  homepage: https://github.com/mbj/mutant
367
- licenses: []
367
+ licenses:
368
+ - MIT
368
369
  metadata: {}
369
370
  post_install_message:
370
371
  rdoc_options: []
@@ -447,13 +448,12 @@ test_files:
447
448
  - spec/unit/mutant/mutator/self_spec.rb
448
449
  - spec/unit/mutant/runner/config/subjects_spec.rb
449
450
  - spec/unit/mutant/runner/config/success_predicate_spec.rb
450
- - spec/unit/mutant/runner/failed_predicte_spec.rb
451
451
  - spec/unit/mutant/runner/mutation/killer_spec.rb
452
452
  - spec/unit/mutant/runner/subject/success_predicate_spec.rb
453
453
  - spec/unit/mutant/strategy/method_expansion/class_methods/run_spec.rb
454
454
  - spec/unit/mutant/strategy/rspec/dm2/lookup/method/instance/spec_files_spec.rb
455
455
  - spec/unit/mutant/strategy/rspec/dm2/lookup/method/singleton/spec_files_spec.rb
456
456
  - spec/unit/mutant/subject/context_spec.rb
457
- - spec/unit/mutant/subject/each_spec.rb
457
+ - spec/unit/mutant/subject/mutations_spec.rb
458
458
  - spec/unit/mutant/subject/node_spec.rb
459
459
  has_rdoc:
@@ -1,33 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Mutant::Runner, '#failed?' do
4
- subject { object.failed? }
5
-
6
- let(:object) { class_under_test.run(config) }
7
-
8
- let(:config) { double('Config') }
9
- let(:class_under_test) do
10
- success = self.success
11
-
12
- Class.new(described_class) do
13
- define_method :success? do
14
- success
15
- end
16
-
17
- define_method :run do
18
- end
19
- end
20
- end
21
-
22
- context 'when runner is successful' do
23
- let(:success) { true }
24
-
25
- it { should be(false) }
26
- end
27
-
28
- context 'when runner is NOT successful' do
29
- let(:success) { false }
30
-
31
- it { should be(true) }
32
- end
33
- end
@@ -1,31 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Mutant::Subject, '#each' do
4
- subject { object.each { |item| yields << item } }
5
-
6
- let(:class_under_test) do
7
- mutations = [mutation_a, mutation_b]
8
- Class.new(described_class) do
9
- define_method(:mutations) { mutations }
10
- end
11
- end
12
-
13
- let(:object) { class_under_test.new(context, node) }
14
- let(:yields) { [] }
15
- let(:node) { double('Node') }
16
- let(:context) { double('Context') }
17
- let(:mutant) { double('Mutant') }
18
- let(:mutation_a) { double('Mutation A') }
19
- let(:mutation_b) { double('Mutation B') }
20
-
21
- it_should_behave_like 'an #each method'
22
-
23
- let(:neutral_mutation) do
24
- Mutant::Mutation::Neutral.new(object, node)
25
- end
26
-
27
- it 'yields mutations' do
28
- expect { subject }.to change { yields.dup }.from([])
29
- .to([neutral_mutation, mutation_a, mutation_b])
30
- end
31
- end