mutant 0.3.0.beta14 → 0.3.0.beta15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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