mutant 0.3.0.beta8 → 0.3.0.beta9

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: 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