mutant 0.3.0.beta8 → 0.3.0.beta9

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: 360fa704d17fde6a8699cf73cb30cfb1fe421e05
4
- data.tar.gz: 9dbd9a5918ce529871b86fd5a80f1067f49da439
3
+ metadata.gz: 2680d48343b2c5b7122252e999dceca9fb51ff4a
4
+ data.tar.gz: 3fe806d025ebb900b98f863aff8e11b0dffa7fed
5
5
  SHA512:
6
- metadata.gz: b1139b749e2e1e7a94060d8638113373681e9fafc8707b7b24d919ca9f41ab72e9d82c29fe4d44d7a3a5af32e6c7f7d1210096e14fec0df2803060901aa67b63
7
- data.tar.gz: 40cfbe6e7022486af8d50ff8bbb943bc5946e0ed6402aa46a339a3fbd15f1317c760677365d8270b24c4744d96bbbc43a00fcb50d2083c2884fef5a22ba8a7f9
6
+ metadata.gz: e8a6cd662eb49939f08df67a418edd884c8b7318cc4b2b6ab1d630118ce7ec3f0448c508e65678b866379e5ba4b37f8ea46e2bc355e164affbd880b3aa33fcbb
7
+ data.tar.gz: d3bab712b12881bc4cf816dbedac61568f4d928e09f2c1cf9d2618ec2e908674fa5b8f5cdb453ec1d6da6abb8f1a77c7da58f5c96720808631b295c9a8c197c2
data/README.md CHANGED
@@ -42,6 +42,12 @@ Installation
42
42
 
43
43
  Install the gem `mutant` via your preferred method.
44
44
 
45
+ The 0.2 series is stable but has outdated dependencies. The 0.3 series is in beta phase currently.
46
+
47
+ ```ruby
48
+ gem install mutant -v0.3.0.beta8
49
+ ```
50
+
45
51
  Examples
46
52
  --------
47
53
 
@@ -50,13 +56,13 @@ CLI will be simplified in the next releases, but currently stick with this:
50
56
  ```
51
57
  cd virtus
52
58
  # Run mutant on virtus namespace (that uses the dm-2 style spec layout)
53
- mutant -I lib -r virtus --rspec-dm2 ::Virtus
59
+ mutant --rspec-dm2 '::Virtus*'
54
60
  # Run mutant on specific virtus class
55
- mutant -I lib -r virtus --rspec-dm2 ::Virtus::Attribute
61
+ mutant --rspec-dm2 ::Virtus::Attribute
56
62
  # Run mutant on specific virtus class method
57
- mutant -I lib -r virtus --rspec-dm2 ::Virtus::Attribute.build
63
+ mutant --rspec-dm2 ::Virtus::Attribute.build
58
64
  # Run mutant on specific virtus instance method
59
- mutant -I lib -r virtus --rspec-dm2 ::Virtus::Attribute#name
65
+ mutant --rspec-dm2 ::Virtus::Attribute#name
60
66
  ```
61
67
 
62
68
  Strategies
data/Rakefile CHANGED
@@ -1,10 +1,11 @@
1
1
  require 'devtools'
2
2
  Devtools.init_rake_tasks
3
3
 
4
+ Rake.application.load_imports
4
5
  task('metrics:mutant').clear
5
6
 
6
7
  namespace :metrics do
7
- task :mutant do
8
+ task :mutant => :coverage do
8
9
  $stderr.puts 'Mutant self mutation is disable till mutant is fast enough for travis'
9
10
  end
10
11
  end
data/config/flay.yml CHANGED
@@ -1,3 +1,3 @@
1
1
  ---
2
2
  threshold: 16
3
- total_score: 640
3
+ total_score: 674
data/config/reek.yml CHANGED
@@ -35,7 +35,8 @@ IrresponsibleModule:
35
35
  exclude: []
36
36
  LongParameterList:
37
37
  enabled: true
38
- exclude: []
38
+ exclude:
39
+ - Mutant::Matcher::Method::Instance#self.build?
39
40
  max_params: 2
40
41
  LongYieldList:
41
42
  enabled: true
data/lib/mutant.rb CHANGED
@@ -40,7 +40,7 @@ require 'mutant/mutator/util'
40
40
  require 'mutant/mutator/util/array'
41
41
  require 'mutant/mutator/util/symbol'
42
42
  require 'mutant/mutator/node'
43
- require 'mutant/mutator/node/noop'
43
+ require 'mutant/mutator/node/generic'
44
44
  require 'mutant/mutator/node/literal'
45
45
  require 'mutant/mutator/node/literal/boolean'
46
46
  require 'mutant/mutator/node/literal/range'
@@ -74,6 +74,8 @@ require 'mutant/context'
74
74
  require 'mutant/context/scope'
75
75
  require 'mutant/subject'
76
76
  require 'mutant/subject/method'
77
+ require 'mutant/subject/method/instance'
78
+ require 'mutant/subject/method/singleton'
77
79
  require 'mutant/matcher'
78
80
  require 'mutant/matcher/chain'
79
81
  require 'mutant/matcher/method'
@@ -24,10 +24,20 @@ module Mutant
24
24
  # @api private
25
25
  #
26
26
  def matcher
27
- methods_matcher.matcher.new(cache, scope, method)
27
+ methods_matcher.matcher.build(cache, scope, method)
28
28
  end
29
29
  memoize :matcher
30
30
 
31
+ # Return identification
32
+ #
33
+ # @return [String]
34
+ #
35
+ # @api private
36
+ #
37
+ def identification
38
+ match.to_s
39
+ end
40
+
31
41
  private
32
42
 
33
43
  # Return method
data/lib/mutant/differ.rb CHANGED
@@ -6,6 +6,10 @@ module Mutant
6
6
  # Return source diff
7
7
  #
8
8
  # @return [String]
9
+ # if there is a diff
10
+ #
11
+ # @return [nil]
12
+ # otherwise
9
13
  #
10
14
  # @api private
11
15
  #
@@ -18,7 +22,7 @@ module Mutant
18
22
  output = Diff::LCS::Hunk.new(old, new, diffs.first, max_length, 0).diff(:unified)
19
23
  output << "\n"
20
24
  else
21
- raise 'Mutation resulted in more than one diff, should not happen!'
25
+ abort 'Mutation resulted in more than one diff, should not happen! PLS report a bug!'
22
26
  end
23
27
  end
24
28
  memoize :diff
@@ -26,10 +30,15 @@ module Mutant
26
30
  # Return colorized source diff
27
31
  #
28
32
  # @return [String]
33
+ # if there is a diff
34
+ #
35
+ # @return [nil]
36
+ # otherwise
29
37
  #
30
38
  # @api private
31
39
  #
32
40
  def colorized_diff
41
+ return unless diff
33
42
  diff.lines.map do |line|
34
43
  self.class.colorize_line(line)
35
44
  end.join
@@ -82,7 +91,7 @@ module Mutant
82
91
  # @api private
83
92
  #
84
93
  def max_length
85
- old.length > new.length ? old.length : new.length
94
+ [old, new].map(&:length).max
86
95
  end
87
96
 
88
97
  # Return colorized diff line
@@ -32,7 +32,7 @@ module Mutant
32
32
  def run
33
33
  pid = fork do
34
34
  killer = @killer.new(strategy, mutation)
35
- exit(killer.success? ? CLI::EXIT_SUCCESS : CLI::EXIT_FAILURE)
35
+ exit(killer.killed? ? CLI::EXIT_SUCCESS : CLI::EXIT_FAILURE)
36
36
  end
37
37
 
38
38
  status = Process.wait2(pid).last
@@ -20,9 +20,9 @@ module Mutant
20
20
  # TODO: replace with real streams from configuration
21
21
  require 'stringio'
22
22
  null = StringIO.new
23
- args = command_line_arguments
23
+ argv = command_line_arguments
24
24
  begin
25
- !::RSpec::Core::Runner.run(args, null, null).zero?
25
+ !::RSpec::Core::Runner.run(argv, null, null).zero?
26
26
  rescue StandardError
27
27
  true
28
28
  end
@@ -11,18 +11,31 @@ module Mutant
11
11
  # @return [self]
12
12
  # if block given
13
13
  #
14
- # @return [Enumerator<Subject>]
14
+ # @return [Enumerable<Subject>]
15
15
  #
16
16
  # @api private
17
17
  #
18
18
  def self.each(cache, input, &block)
19
19
  return to_enum(__method__, cache, input) unless block_given?
20
20
 
21
- new(cache, input).each(&block)
21
+ build(cache, input).each(&block)
22
22
 
23
23
  self
24
24
  end
25
25
 
26
+ # Default matcher build implementation
27
+ #
28
+ # @param [Cache] cache
29
+ # @param [Object] input
30
+ #
31
+ # @return [undefined]
32
+ #
33
+ # @api private
34
+ #
35
+ def self.build(*arguments)
36
+ new(*arguments)
37
+ end
38
+
26
39
  # Enumerate subjects
27
40
  #
28
41
  # @api private
@@ -10,7 +10,7 @@ module Mutant
10
10
 
11
11
  # Enumerate matches
12
12
  #
13
- # @return [Enumerable]
13
+ # @return [Enumerable<Subject>]
14
14
  # returns enumerable when no block given
15
15
  #
16
16
  # @return [self]
@@ -22,7 +22,11 @@ module Mutant
22
22
  return to_enum unless block_given?
23
23
 
24
24
  unless skip?
25
- yield subject if subject
25
+ if subject
26
+ yield subject
27
+ else
28
+ $stderr.puts "Cannot find definition of: #{identification} in #{source_location.join(':')}"
29
+ end
26
30
  end
27
31
 
28
32
  self
@@ -5,6 +5,23 @@ module Mutant
5
5
  class Instance < self
6
6
  SUBJECT_CLASS = Subject::Method::Instance
7
7
 
8
+ # Dispatching builder, detects adamantium case
9
+ #
10
+ # @param [Cache] cache
11
+ # @param [Class, Module] scope
12
+ # @param [UnboundMethod] method
13
+ #
14
+ # @return [Matcher::Method::Instance]
15
+ #
16
+ # @api private
17
+ #
18
+ def self.build(cache, scope, method)
19
+ if scope.ancestors.include?(::Adamantium) and scope.memoized?(method.name)
20
+ return Memoized.new(cache, scope, method)
21
+ end
22
+ super
23
+ end
24
+
8
25
  # Return identification
9
26
  #
10
27
  # @return [String]
@@ -40,6 +57,23 @@ module Mutant
40
57
  node.children[NAME_INDEX] == method_name
41
58
  end
42
59
 
60
+ # Matcher for memoized instance methods
61
+ class Memoized < self
62
+
63
+ private
64
+
65
+ # Return source location
66
+ #
67
+ # @return [Array]
68
+ #
69
+ # @api private
70
+ #
71
+ def source_location
72
+ scope.original_instance_method(method.name).source_location
73
+ end
74
+
75
+ end # Memoized
76
+
43
77
  end # Instance
44
78
  end # Method
45
79
  end # Matcher
@@ -59,7 +59,7 @@ module Mutant
59
59
  # @api private
60
60
  #
61
61
  def emit_matches(method)
62
- matcher.new(cache, scope, method).each do |subject|
62
+ matcher.build(cache, scope, method).each do |subject|
63
63
  yield subject
64
64
  end
65
65
  end
@@ -3,6 +3,15 @@ module Mutant
3
3
  # Neutral mutation
4
4
  class Neutral < self
5
5
 
6
+ SYMBOL = 'neutral'
7
+
8
+ # Noop mutation, special case of neutral
9
+ class Noop < self
10
+
11
+ SYMBOL = 'noop'
12
+
13
+ end
14
+
6
15
  # Return identification
7
16
  #
8
17
  # @return [String]
@@ -10,7 +19,7 @@ module Mutant
10
19
  # @api private
11
20
  #
12
21
  def identification
13
- "noop:#{super}"
22
+ "#{self.class::SYMBOL}:#{super}"
14
23
  end
15
24
  memoize :identification
16
25
 
@@ -1,13 +1,12 @@
1
1
  module Mutant
2
2
  class Mutator
3
3
  class Node
4
- # Mutator that does not do mutations on ast
5
- class Noop < self
4
+ # Generic mutator
5
+ class Generic < self
6
6
 
7
- # Literal references to self do not need to be mutated?
8
7
  handle(:self)
9
8
 
10
- # These nodes still need a mutator, your contribution is that close!
9
+ # These nodes still need a dedicated mutator, your contribution is that close!
11
10
  handle(
12
11
  :zsuper, :not, :or, :and, :defined,
13
12
  :next, :break, :match, :gvar, :cvar, :ensure,
@@ -28,6 +27,9 @@ module Mutant
28
27
  # @api private
29
28
  #
30
29
  def dispatch
30
+ children.each_index do |index|
31
+ mutate_child(index) if children.at(index)
32
+ end
31
33
  end
32
34
 
33
35
  end # Noop
@@ -30,6 +30,16 @@ module Mutant
30
30
  REGISTRY.freeze
31
31
  end
32
32
 
33
+ # Build printer
34
+ #
35
+ # @return [Printer]
36
+ #
37
+ # @api private
38
+ #
39
+ def self.build(*args)
40
+ new(*args)
41
+ end
42
+
33
43
  # Run printer
34
44
  #
35
45
  # @return [self]
@@ -37,7 +47,7 @@ module Mutant
37
47
  # @api private
38
48
  #
39
49
  def self.run(*args)
40
- new(*args).run
50
+ build(*args).run
41
51
  self
42
52
  end
43
53
 
@@ -59,7 +69,6 @@ module Mutant
59
69
 
60
70
  private
61
71
 
62
-
63
72
  # Return status color
64
73
  #
65
74
  # @return [Color]
@@ -70,6 +79,18 @@ module Mutant
70
79
  success? ? Color::GREEN : Color::RED
71
80
  end
72
81
 
82
+ # Visit object
83
+ #
84
+ # @param [Object] object
85
+ #
86
+ # @return [undefined]
87
+ #
88
+ # @api private
89
+ #
90
+ def visit(object)
91
+ self.class.visit(object, output)
92
+ end
93
+
73
94
  # Print an info line to output
74
95
  #
75
96
  # @return [undefined]
@@ -5,6 +5,29 @@ module Mutant
5
5
  # Mutation printer
6
6
  class Mutation < self
7
7
 
8
+ handle(Runner::Mutation)
9
+
10
+ # Build printer
11
+ #
12
+ # @param [Runner::Mutation] runner
13
+ # @param [IO] output
14
+ #
15
+ # @return [Printer::Mutation]
16
+ #
17
+ # @api private
18
+ #
19
+ def self.build(runner, output)
20
+ mutation = runner.mutation
21
+ case mutation
22
+ when Mutant::Mutation::Neutral::Noop
23
+ Noop
24
+ when Mutant::Mutation::Evil, Mutant::Mutation::Neutral
25
+ Diff
26
+ else
27
+ raise "Unknown mutation: #{mutation}"
28
+ end.new(runner, output)
29
+ end
30
+
8
31
  # Run mutation printer
9
32
  #
10
33
  # @return [undefined]
@@ -13,7 +36,7 @@ module Mutant
13
36
  #
14
37
  def run
15
38
  status(mutation.identification)
16
- puts(colorized_diff)
39
+ puts(details)
17
40
  end
18
41
 
19
42
  private
@@ -28,25 +51,45 @@ module Mutant
28
51
  object.mutation
29
52
  end
30
53
 
31
- # Return colorized diff
32
- #
33
- # @param [Mutation] mutation
34
- #
35
- # @return [undefined]
36
- #
37
- # @api private
38
- #
39
- def colorized_diff
40
- original, current = mutation.original_source, mutation.source
41
- differ = Differ.build(original, current)
42
- diff = color? ? differ.colorized_diff : differ.diff
54
+ # Reporter for noop mutations
55
+ class Noop < self
56
+
57
+ MESSAGE =
58
+ "Parsed subject AST:\n" \
59
+ "%s\n" \
60
+ "Unparsed source:\n" \
61
+ "%s\n"
62
+
63
+ private
43
64
 
44
- if diff.empty?
45
- raise 'Unable to create a diff, so ast mutant or unparser does something strange!!'
65
+ # Return details
66
+ #
67
+ # @return [String]
68
+ #
69
+ # @api private
70
+ #
71
+ def details
72
+ sprintf(MESSAGE, mutation.subject.node.inspect, mutation.original_source)
46
73
  end
47
74
 
48
- diff
49
- end
75
+ end # Noop
76
+
77
+ # Reporter for neutral and evil mutations
78
+ class Diff < self
79
+
80
+ # Return diff
81
+ #
82
+ # @return [String]
83
+ #
84
+ # @api private
85
+ #
86
+ def details
87
+ original, current = mutation.original_source, mutation.source
88
+ differ = Differ.build(original, current)
89
+ color? ? differ.colorized_diff : differ.diff
90
+ end
91
+
92
+ end # Evil
50
93
 
51
94
  end # Mutantion
52
95
  end # Printer
@@ -133,7 +133,7 @@ module Mutant
133
133
  def run
134
134
  puts(subject.identification)
135
135
  object.failed_mutations.each do |mutation|
136
- Mutation.run(mutation, output)
136
+ visit(mutation)
137
137
  end
138
138
  print_stats
139
139
  end
@@ -15,8 +15,11 @@ module Mutant
15
15
  #
16
16
  def each
17
17
  return to_enum unless block_given?
18
- Mutator.each(node) do |mutant|
19
- yield Mutation::Evil.new(self, mutant)
18
+
19
+ yield noop_mutation
20
+
21
+ mutations.each do |mutation|
22
+ yield mutation
20
23
  end
21
24
 
22
25
  self
@@ -109,5 +112,15 @@ module Mutant
109
112
  abstract_method :subtype
110
113
  private :subtype
111
114
 
115
+ # Return neutral mutation
116
+ #
117
+ # @return [Mutation::Neutral]
118
+ #
119
+ # @api private
120
+ #
121
+ def noop_mutation
122
+ Mutation::Neutral::Noop.new(self, node)
123
+ end
124
+
112
125
  end # Subject
113
126
  end # Mutant
@@ -27,6 +27,18 @@ module Mutant
27
27
 
28
28
  private
29
29
 
30
+ # Return mutations
31
+ #
32
+ # @return [Enumerable<Mutation>]
33
+ #
34
+ # @api private
35
+ #
36
+ def mutations
37
+ Mutator.each(node).map do |mutant|
38
+ Mutation::Evil.new(self, mutant)
39
+ end
40
+ end
41
+
30
42
  # Return scope
31
43
  #
32
44
  # @return [Class, Module]
@@ -47,54 +59,6 @@ module Mutant
47
59
  "#{context.identification}#{self.class::SYMBOL}#{name}"
48
60
  end
49
61
 
50
- # Instance method subjects
51
- class Instance < self
52
-
53
- NAME_INDEX = 0
54
- SYMBOL = '#'.freeze
55
-
56
- # Test if method is public
57
- #
58
- # @return [true]
59
- # if method is public
60
- #
61
- # @return [false]
62
- # otherwise
63
- #
64
- # @api private
65
- #
66
- def public?
67
- scope.public_method_defined?(name)
68
- end
69
- memoize :public?
70
-
71
- private
72
-
73
- end # Instance
74
-
75
- # Singleton method subjects
76
- class Singleton < self
77
-
78
- NAME_INDEX = 1
79
- SYMBOL = '.'.freeze
80
-
81
- # Test if method is public
82
- #
83
- # @return [true]
84
- # if method is public
85
- #
86
- # @return [false]
87
- # otherwise
88
- #
89
- # @api private
90
- #
91
- def public?
92
- scope.singleton_class.public_method_defined?(name)
93
- end
94
- memoize :public?
95
-
96
- end # Singleton
97
-
98
62
  end # Method
99
63
  end # Subject
100
64
  end # Mutant
@@ -0,0 +1,60 @@
1
+ module Mutant
2
+ class Subject
3
+ class Method
4
+ # Instance method subjects
5
+ class Instance < self
6
+
7
+ NAME_INDEX = 0
8
+ SYMBOL = '#'.freeze
9
+
10
+ # Test if method is public
11
+ #
12
+ # @return [true]
13
+ # if method is public
14
+ #
15
+ # @return [false]
16
+ # otherwise
17
+ #
18
+ # @api private
19
+ #
20
+ def public?
21
+ scope.public_method_defined?(name)
22
+ end
23
+ memoize :public?
24
+
25
+ private
26
+
27
+ # Mutator for memoized instance methods
28
+ class Memoized < self
29
+
30
+ private
31
+
32
+ # Return mutations
33
+ #
34
+ # @return [Enumerable<Mutation>]
35
+ #
36
+ # @api private
37
+ #
38
+ def mutations
39
+ Mutator.each(node).map do |mutant|
40
+ Mutation::Evil.new(self, memoizer_node(mutant))
41
+ end
42
+ end
43
+
44
+ # Return memoizer node for mutant
45
+ #
46
+ # @param [Parser::AST::Node] mutant
47
+ #
48
+ # @return [Parser::AST::Node]
49
+ #
50
+ # @api private
51
+ #
52
+ def memoizer_node(mutant)
53
+ s(:begin, mutant, s(:send, nil, :memoize, s(:args, s(:sym, name))))
54
+ end
55
+
56
+ end # Memoized
57
+ end # Instance
58
+ end # Method
59
+ end # Subject
60
+ end # Mutant
@@ -0,0 +1,28 @@
1
+ module Mutant
2
+ class Subject
3
+ class Method
4
+ # Singleton method subjects
5
+ class Singleton < self
6
+
7
+ NAME_INDEX = 1
8
+ SYMBOL = '.'.freeze
9
+
10
+ # Test if method is public
11
+ #
12
+ # @return [true]
13
+ # if method is public
14
+ #
15
+ # @return [false]
16
+ # otherwise
17
+ #
18
+ # @api private
19
+ #
20
+ def public?
21
+ scope.singleton_class.public_method_defined?(name)
22
+ end
23
+ memoize :public?
24
+
25
+ end # Singleton
26
+ end # Method
27
+ end # Subject
28
+ end # Mutant
data/mutant.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |gem|
4
4
  gem.name = 'mutant'
5
- gem.version = '0.3.0.beta8'
5
+ gem.version = '0.3.0.beta9'
6
6
  gem.authors = [ 'Markus Schirp' ]
7
7
  gem.email = [ 'mbj@schirp-dso.com' ]
8
8
 
@@ -16,11 +16,11 @@ Gem::Specification.new do |gem|
16
16
  gem.extra_rdoc_files = %w[TODO LICENSE]
17
17
  gem.executables = [ 'mutant', 'zombie' ]
18
18
 
19
- gem.add_runtime_dependency('parser', '~> 2.0.beta10')
20
- gem.add_runtime_dependency('unparser', '~> 0.0.7')
19
+ gem.add_runtime_dependency('parser', '~> 2.0.pre1')
20
+ gem.add_runtime_dependency('unparser', '~> 0.0.8')
21
21
  gem.add_runtime_dependency('ice_nine', '~> 0.8.0')
22
22
  gem.add_runtime_dependency('descendants_tracker', '~> 0.0.1')
23
- gem.add_runtime_dependency('adamantium', '~> 0.0.8')
23
+ gem.add_runtime_dependency('adamantium', '~> 0.0.10')
24
24
  gem.add_runtime_dependency('equalizer', '~> 0.0.5')
25
25
  gem.add_runtime_dependency('inflecto', '~> 0.0.2')
26
26
  gem.add_runtime_dependency('anima', '~> 0.0.6')
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mutant::Matcher::Method::Instance, '.build' do
4
+ let(:object) { described_class }
5
+
6
+ subject { object.build(cache, scope, method) }
7
+
8
+ let(:cache) { mock }
9
+
10
+ let(:scope) do
11
+ Class.new do
12
+ include Adamantium
13
+
14
+ def foo
15
+ end
16
+ memoize :foo
17
+
18
+ def bar
19
+ end
20
+ end
21
+ end
22
+
23
+ let(:method) do
24
+ scope.instance_method(method_name)
25
+ end
26
+
27
+ context 'with adamantium infected scope' do
28
+ context 'with unmemoized method' do
29
+ let(:method_name) { :bar }
30
+
31
+ it { should eql(Mutant::Matcher::Method::Instance.new(cache, scope, method)) }
32
+ end
33
+
34
+ context 'with memoized method' do
35
+ let(:method_name) { :foo }
36
+
37
+ it { should eql(Mutant::Matcher::Method::Instance::Memoized.new(cache, scope, method)) }
38
+ end
39
+ end
40
+ end
@@ -4,35 +4,28 @@ describe Mutant::Subject, '#each' do
4
4
  subject { object.each { |item| yields << item } }
5
5
 
6
6
  let(:class_under_test) do
7
- Class.new(described_class)
7
+ mutations = [mutation_a, mutation_b]
8
+ Class.new(described_class) do
9
+ define_method(:mutations) { mutations }
10
+ end
8
11
  end
9
12
 
10
- let(:object) { class_under_test.new(context, ast) }
11
- let(:root) { mock('Root Node') }
12
- let(:ast) { mock('Node') }
13
- let(:context) { mock('Context', :root => root) }
14
- let(:mutant) { mock('Mutant') }
15
- let(:mutation) { mock('Mutation') }
16
- let(:yields) { [] }
17
-
18
- before do
19
- Mutant::Mutator.stub(:each).with(ast).and_yield(mutant).and_return(Mutant::Mutator)
20
- Mutant::Mutation.stub(:new => mutation)
21
- end
13
+ let(:object) { class_under_test.new(context, node) }
14
+ let(:yields) { [] }
15
+ let(:node) { mock('Node') }
16
+ let(:context) { mock('Context') }
17
+ let(:mutant) { mock('Mutant') }
18
+ let(:mutation_a) { mock('Mutation A') }
19
+ let(:mutation_b) { mock('Mutation B') }
22
20
 
23
21
  it_should_behave_like 'an #each method'
24
22
 
25
- it 'should initialize mutator with ast' do
26
- Mutant::Mutator.should_receive(:each).with(ast).and_yield(mutation).and_return(Mutant::Mutator)
27
- subject
28
- end
29
-
30
- it 'should yield mutations' do
31
- expect { subject }.to change { yields.dup }.from([]).to([mutation])
23
+ let(:neutral_mutation) do
24
+ Mutant::Mutation::Neutral.new(object, node)
32
25
  end
33
26
 
34
- it 'should initialize mutation' do
35
- Mutant::Mutation.should_receive(:new).with(object, mutant).and_return(mutation)
36
- subject
27
+ it 'yields mutations' do
28
+ expect { subject }.to change { yields.dup }.from([])
29
+ .to([neutral_mutation, mutation_a, mutation_b])
37
30
  end
38
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mutant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0.beta8
4
+ version: 0.3.0.beta9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Markus Schirp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-02 00:00:00.000000000 Z
11
+ date: 2013-07-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: 2.0.beta10
19
+ version: 2.0.pre1
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.beta10
26
+ version: 2.0.pre1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: unparser
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ~>
32
32
  - !ruby/object:Gem::Version
33
- version: 0.0.7
33
+ version: 0.0.8
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ~>
39
39
  - !ruby/object:Gem::Version
40
- version: 0.0.7
40
+ version: 0.0.8
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: ice_nine
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - ~>
74
74
  - !ruby/object:Gem::Version
75
- version: 0.0.8
75
+ version: 0.0.10
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ~>
81
81
  - !ruby/object:Gem::Version
82
- version: 0.0.8
82
+ version: 0.0.10
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: equalizer
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -224,6 +224,7 @@ files:
224
224
  - lib/mutant/mutator/node/block.rb
225
225
  - lib/mutant/mutator/node/case.rb
226
226
  - lib/mutant/mutator/node/define.rb
227
+ - lib/mutant/mutator/node/generic.rb
227
228
  - lib/mutant/mutator/node/if.rb
228
229
  - lib/mutant/mutator/node/literal.rb
229
230
  - lib/mutant/mutator/node/literal/array.rb
@@ -238,7 +239,6 @@ files:
238
239
  - lib/mutant/mutator/node/literal/string.rb
239
240
  - lib/mutant/mutator/node/literal/symbol.rb
240
241
  - lib/mutant/mutator/node/mlhs.rb
241
- - lib/mutant/mutator/node/noop.rb
242
242
  - lib/mutant/mutator/node/return.rb
243
243
  - lib/mutant/mutator/node/send.rb
244
244
  - lib/mutant/mutator/node/send/binary.rb
@@ -273,6 +273,8 @@ files:
273
273
  - lib/mutant/strategy/static.rb
274
274
  - lib/mutant/subject.rb
275
275
  - lib/mutant/subject/method.rb
276
+ - lib/mutant/subject/method/instance.rb
277
+ - lib/mutant/subject/method/singleton.rb
276
278
  - lib/mutant/support/method_object.rb
277
279
  - lib/mutant/zombifier.rb
278
280
  - mutant.gemspec
@@ -303,6 +305,7 @@ files:
303
305
  - spec/unit/mutant/matcher/chain/each_spec.rb
304
306
  - spec/unit/mutant/matcher/chain/matchers_spec.rb
305
307
  - spec/unit/mutant/matcher/each_spec.rb
308
+ - spec/unit/mutant/matcher/method/instance/class_methods/build_spec.rb
306
309
  - spec/unit/mutant/matcher/method/instance/each_spec.rb
307
310
  - spec/unit/mutant/matcher/method/singleton/each_spec.rb
308
311
  - spec/unit/mutant/matcher/methods/instance/each_spec.rb
@@ -328,7 +331,6 @@ files:
328
331
  - spec/unit/mutant/mutator/node/literal/regex_spec.rb
329
332
  - spec/unit/mutant/mutator/node/literal/string_spec.rb
330
333
  - spec/unit/mutant/mutator/node/literal/symbol_spec.rb
331
- - spec/unit/mutant/mutator/node/noop/mutation_spec.rb
332
334
  - spec/unit/mutant/mutator/node/return/mutation_spec.rb
333
335
  - spec/unit/mutant/mutator/node/send/mutation_spec.rb
334
336
  - spec/unit/mutant/mutator/node/super/mutation_spec.rb
@@ -378,7 +380,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
378
380
  version: 1.3.1
379
381
  requirements: []
380
382
  rubyforge_project:
381
- rubygems_version: 2.0.3
383
+ rubygems_version: 2.0.2
382
384
  signing_key:
383
385
  specification_version: 4
384
386
  summary: Mutation testing tool for ruby under MRI and Rubinius
@@ -410,6 +412,7 @@ test_files:
410
412
  - spec/unit/mutant/matcher/chain/each_spec.rb
411
413
  - spec/unit/mutant/matcher/chain/matchers_spec.rb
412
414
  - spec/unit/mutant/matcher/each_spec.rb
415
+ - spec/unit/mutant/matcher/method/instance/class_methods/build_spec.rb
413
416
  - spec/unit/mutant/matcher/method/instance/each_spec.rb
414
417
  - spec/unit/mutant/matcher/method/singleton/each_spec.rb
415
418
  - spec/unit/mutant/matcher/methods/instance/each_spec.rb
@@ -435,7 +438,6 @@ test_files:
435
438
  - spec/unit/mutant/mutator/node/literal/regex_spec.rb
436
439
  - spec/unit/mutant/mutator/node/literal/string_spec.rb
437
440
  - spec/unit/mutant/mutator/node/literal/symbol_spec.rb
438
- - spec/unit/mutant/mutator/node/noop/mutation_spec.rb
439
441
  - spec/unit/mutant/mutator/node/return/mutation_spec.rb
440
442
  - spec/unit/mutant/mutator/node/send/mutation_spec.rb
441
443
  - spec/unit/mutant/mutator/node/super/mutation_spec.rb
@@ -1,13 +0,0 @@
1
- require 'spec_helper'
2
-
3
- # FIXME: This spec needs to be structured better!
4
- describe Mutant::Mutator::Node::Noop, 'send' do
5
-
6
- let(:source) { 'alias foo bar' }
7
-
8
- let(:mutations) do
9
- mutations = []
10
- end
11
-
12
- it_should_behave_like 'a mutator'
13
- end