mutant 0.8.0 → 0.8.1
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 +4 -4
- data/Changelog.md +7 -0
- data/config/flay.yml +1 -1
- data/config/reek.yml +1 -0
- data/lib/mutant.rb +10 -3
- data/lib/mutant/actor.rb +2 -5
- data/lib/mutant/actor/env.rb +1 -3
- data/lib/mutant/actor/mailbox.rb +2 -4
- data/lib/mutant/actor/receiver.rb +0 -2
- data/lib/mutant/actor/sender.rb +0 -1
- data/lib/mutant/ast.rb +22 -28
- data/lib/mutant/ast/meta.rb +8 -88
- data/lib/mutant/ast/named_children.rb +1 -8
- data/lib/mutant/ast/sexp.rb +0 -2
- data/lib/mutant/cache.rb +1 -3
- data/lib/mutant/cli.rb +9 -19
- data/lib/mutant/color.rb +0 -3
- data/lib/mutant/config.rb +6 -2
- data/lib/mutant/context.rb +2 -4
- data/lib/mutant/context/scope.rb +10 -16
- data/lib/mutant/delegator.rb +0 -3
- data/lib/mutant/diff.rb +8 -17
- data/lib/mutant/env.rb +3 -5
- data/lib/mutant/env/bootstrap.rb +32 -39
- data/lib/mutant/expression.rb +14 -132
- data/lib/mutant/expression/method.rb +25 -42
- data/lib/mutant/expression/methods.rb +17 -29
- data/lib/mutant/expression/namespace.rb +33 -28
- data/lib/mutant/expression/parser.rb +71 -0
- data/lib/mutant/integration.rb +17 -16
- data/lib/mutant/isolation.rb +14 -14
- data/lib/mutant/loader.rb +2 -4
- data/lib/mutant/matcher.rb +1 -11
- data/lib/mutant/matcher/chain.rb +0 -1
- data/lib/mutant/matcher/compiler.rb +19 -52
- data/lib/mutant/matcher/config.rb +65 -5
- data/lib/mutant/matcher/filter.rb +11 -1
- data/lib/mutant/matcher/method.rb +11 -21
- data/lib/mutant/matcher/method/instance.rb +2 -16
- data/lib/mutant/matcher/method/singleton.rb +3 -20
- data/lib/mutant/matcher/methods.rb +11 -21
- data/lib/mutant/matcher/namespace.rb +0 -4
- data/lib/mutant/matcher/null.rb +0 -1
- data/lib/mutant/matcher/scope.rb +0 -12
- data/lib/mutant/meta.rb +0 -1
- data/lib/mutant/meta/example.rb +12 -26
- data/lib/mutant/meta/example/dsl.rb +1 -8
- data/lib/mutant/mutation.rb +6 -14
- data/lib/mutant/mutator.rb +2 -14
- data/lib/mutant/mutator/node.rb +6 -33
- data/lib/mutant/mutator/node/and_asgn.rb +0 -1
- data/lib/mutant/mutator/node/argument.rb +0 -5
- data/lib/mutant/mutator/node/arguments.rb +1 -7
- data/lib/mutant/mutator/node/begin.rb +0 -2
- data/lib/mutant/mutator/node/binary.rb +0 -3
- data/lib/mutant/mutator/node/block.rb +0 -2
- data/lib/mutant/mutator/node/break.rb +0 -1
- data/lib/mutant/mutator/node/case.rb +0 -3
- data/lib/mutant/mutator/node/conditional_loop.rb +0 -1
- data/lib/mutant/mutator/node/const.rb +0 -1
- data/lib/mutant/mutator/node/define.rb +0 -1
- data/lib/mutant/mutator/node/defined.rb +0 -1
- data/lib/mutant/mutator/node/dstr.rb +0 -1
- data/lib/mutant/mutator/node/dsym.rb +0 -1
- data/lib/mutant/mutator/node/generic.rb +0 -1
- data/lib/mutant/mutator/node/if.rb +0 -4
- data/lib/mutant/mutator/node/kwbegin.rb +0 -1
- data/lib/mutant/mutator/node/literal/array.rb +0 -2
- data/lib/mutant/mutator/node/literal/boolean.rb +0 -1
- data/lib/mutant/mutator/node/literal/fixnum.rb +2 -5
- data/lib/mutant/mutator/node/literal/float.rb +1 -4
- data/lib/mutant/mutator/node/literal/hash.rb +0 -3
- data/lib/mutant/mutator/node/literal/nil.rb +0 -1
- data/lib/mutant/mutator/node/literal/range.rb +1 -5
- data/lib/mutant/mutator/node/literal/regex.rb +1 -3
- data/lib/mutant/mutator/node/literal/string.rb +0 -1
- data/lib/mutant/mutator/node/literal/symbol.rb +0 -1
- data/lib/mutant/mutator/node/masgn.rb +0 -1
- data/lib/mutant/mutator/node/match_current_line.rb +0 -1
- data/lib/mutant/mutator/node/mlhs.rb +0 -1
- data/lib/mutant/mutator/node/named_value/access.rb +0 -1
- data/lib/mutant/mutator/node/named_value/constant_assignment.rb +0 -2
- data/lib/mutant/mutator/node/named_value/variable_assignment.rb +0 -2
- data/lib/mutant/mutator/node/next.rb +0 -1
- data/lib/mutant/mutator/node/noop.rb +0 -1
- data/lib/mutant/mutator/node/nthref.rb +0 -1
- data/lib/mutant/mutator/node/op_asgn.rb +0 -1
- data/lib/mutant/mutator/node/or_asgn.rb +1 -2
- data/lib/mutant/mutator/node/resbody.rb +0 -2
- data/lib/mutant/mutator/node/rescue.rb +1 -6
- data/lib/mutant/mutator/node/return.rb +0 -1
- data/lib/mutant/mutator/node/send.rb +16 -17
- data/lib/mutant/mutator/node/send/attribute_assignment.rb +0 -3
- data/lib/mutant/mutator/node/send/binary.rb +0 -1
- data/lib/mutant/mutator/node/send/index.rb +0 -3
- data/lib/mutant/mutator/node/splat.rb +0 -1
- data/lib/mutant/mutator/node/super.rb +0 -1
- data/lib/mutant/mutator/node/when.rb +2 -7
- data/lib/mutant/mutator/node/yield.rb +0 -1
- data/lib/mutant/mutator/node/zsuper.rb +0 -1
- data/lib/mutant/mutator/registry.rb +1 -4
- data/lib/mutant/mutator/util.rb +0 -2
- data/lib/mutant/mutator/util/array.rb +0 -3
- data/lib/mutant/mutator/util/symbol.rb +0 -1
- data/lib/mutant/parallel.rb +3 -9
- data/lib/mutant/parallel/master.rb +7 -17
- data/lib/mutant/parallel/source.rb +2 -7
- data/lib/mutant/parallel/worker.rb +1 -5
- data/lib/mutant/reporter.rb +0 -4
- data/lib/mutant/reporter/cli.rb +1 -8
- data/lib/mutant/reporter/cli/format.rb +7 -18
- data/lib/mutant/reporter/cli/printer.rb +2 -12
- data/lib/mutant/reporter/cli/printer/config.rb +1 -4
- data/lib/mutant/reporter/cli/printer/env_progress.rb +3 -7
- data/lib/mutant/reporter/cli/printer/env_result.rb +0 -1
- data/lib/mutant/reporter/cli/printer/mutation_progress_result.rb +0 -2
- data/lib/mutant/reporter/cli/printer/mutation_result.rb +3 -11
- data/lib/mutant/reporter/cli/printer/status.rb +1 -4
- data/lib/mutant/reporter/cli/printer/status_progressive.rb +1 -3
- data/lib/mutant/reporter/cli/printer/subject_progress.rb +0 -5
- data/lib/mutant/reporter/cli/printer/subject_result.rb +0 -1
- data/lib/mutant/reporter/cli/printer/test_result.rb +0 -1
- data/lib/mutant/reporter/cli/tput.rb +4 -1
- data/lib/mutant/reporter/trace.rb +2 -4
- data/lib/mutant/repository.rb +88 -0
- data/lib/mutant/require_highjack.rb +0 -1
- data/lib/mutant/result.rb +25 -48
- data/lib/mutant/runner.rb +7 -16
- data/lib/mutant/runner/sink.rb +3 -11
- data/lib/mutant/selector.rb +1 -2
- data/lib/mutant/selector/expression.rb +1 -2
- data/lib/mutant/subject.rb +10 -21
- data/lib/mutant/subject/method.rb +11 -12
- data/lib/mutant/subject/method/instance.rb +1 -5
- data/lib/mutant/subject/method/singleton.rb +1 -3
- data/lib/mutant/test.rb +1 -2
- data/lib/mutant/version.rb +2 -2
- data/lib/mutant/warning_filter.rb +2 -7
- data/lib/mutant/zombifier.rb +6 -10
- data/meta/send.rb +8 -0
- data/spec/spec_helper.rb +5 -1
- data/spec/support/corpus.rb +5 -9
- data/spec/support/rb_bug.rb +0 -1
- data/spec/support/rspec.rb +0 -1
- data/spec/support/ruby_vm.rb +0 -2
- data/spec/unit/mutant/ast/meta/send_spec.rb +42 -0
- data/spec/unit/mutant/ast/named_children_spec.rb +51 -0
- data/spec/unit/mutant/ast/sexp_spec.rb +36 -0
- data/spec/unit/mutant/ast_spec.rb +8 -0
- data/spec/unit/mutant/cli_spec.rb +34 -19
- data/spec/unit/mutant/context/scope_spec.rb +11 -0
- data/spec/unit/mutant/env/boostrap_spec.rb +5 -2
- data/spec/unit/mutant/env_spec.rb +14 -15
- data/spec/unit/mutant/expression/method_spec.rb +10 -14
- data/spec/unit/mutant/expression/methods_spec.rb +24 -11
- data/spec/unit/mutant/expression/namespace/flat_spec.rb +5 -6
- data/spec/unit/mutant/expression/namespace/recursive_spec.rb +16 -10
- data/spec/unit/mutant/expression/parser_spec.rb +67 -0
- data/spec/unit/mutant/expression_spec.rb +24 -57
- data/spec/unit/mutant/integration/rspec_spec.rb +7 -7
- data/spec/unit/mutant/integration_spec.rb +2 -2
- data/spec/unit/mutant/isolation_spec.rb +31 -29
- data/spec/unit/mutant/matcher/compiler/subject_prefix_spec.rb +2 -2
- data/spec/unit/mutant/matcher/compiler_spec.rb +27 -58
- data/spec/unit/mutant/matcher/config_spec.rb +45 -0
- data/spec/unit/mutant/matcher/filter_spec.rb +12 -5
- data/spec/unit/mutant/matcher/method/instance_spec.rb +0 -1
- data/spec/unit/mutant/matcher/method/singleton_spec.rb +0 -1
- data/spec/unit/mutant/matcher/namespace_spec.rb +4 -4
- data/spec/unit/mutant/parallel/worker_spec.rb +1 -1
- data/spec/unit/mutant/reporter/cli/printer/config_spec.rb +4 -4
- data/spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb +7 -7
- data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +2 -2
- data/spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb +2 -2
- data/spec/unit/mutant/reporter/cli/printer/status_spec.rb +12 -12
- data/spec/unit/mutant/reporter/cli/printer/subject_progress_spec.rb +1 -1
- data/spec/unit/mutant/reporter/cli_spec.rb +9 -10
- data/spec/unit/mutant/repository/diff_spec.rb +80 -0
- data/spec/unit/mutant/repository/subject_filter_spec.rb +28 -0
- data/spec/unit/mutant/result/env_spec.rb +1 -1
- data/spec/unit/mutant/runner_spec.rb +0 -1
- data/spec/unit/mutant/selector/expression_spec.rb +14 -14
- data/spec/unit/mutant/subject/method/instance_spec.rb +2 -2
- data/spec/unit/mutant/subject/method/singleton_spec.rb +2 -2
- data/spec/unit/mutant/subject_spec.rb +5 -2
- metadata +20 -3
- data/spec/support/mutation_verifier.rb +0 -96
data/lib/mutant/version.rb
CHANGED
@@ -12,28 +12,25 @@ module Mutant
|
|
12
12
|
# @return [undefined]
|
13
13
|
#
|
14
14
|
# @api private
|
15
|
-
#
|
16
15
|
def initialize(target)
|
17
16
|
@target = target
|
18
17
|
@warnings = []
|
19
18
|
end
|
20
19
|
|
21
|
-
#
|
20
|
+
# Warnings captured by filter
|
22
21
|
#
|
23
22
|
# @return [Array<String>]
|
24
23
|
#
|
25
24
|
# @api private
|
26
|
-
#
|
27
25
|
attr_reader :warnings
|
28
26
|
|
29
|
-
#
|
27
|
+
# Target stream to capture warnings on
|
30
28
|
#
|
31
29
|
# @return [#write] target
|
32
30
|
#
|
33
31
|
# @return [undefined]
|
34
32
|
#
|
35
33
|
# @api private
|
36
|
-
#
|
37
34
|
attr_reader :target
|
38
35
|
protected :target
|
39
36
|
|
@@ -44,7 +41,6 @@ module Mutant
|
|
44
41
|
# @return [self]
|
45
42
|
#
|
46
43
|
# @api private
|
47
|
-
#
|
48
44
|
def write(message)
|
49
45
|
if WARNING_PATTERN =~ message
|
50
46
|
warnings << message
|
@@ -60,7 +56,6 @@ module Mutant
|
|
60
56
|
# @return [Array<String>]
|
61
57
|
#
|
62
58
|
# @api private
|
63
|
-
#
|
64
59
|
def self.use
|
65
60
|
original = $stderr
|
66
61
|
$stderr = filter = new(original)
|
data/lib/mutant/zombifier.rb
CHANGED
@@ -22,13 +22,17 @@ module Mutant
|
|
22
22
|
# @return [undefined]
|
23
23
|
#
|
24
24
|
# @api private
|
25
|
-
#
|
26
25
|
def initialize(*)
|
27
26
|
super
|
28
27
|
@includes = %r{\A#{Regexp.union(includes)}(?:/.*)?\z}
|
29
28
|
@zombified = Set.new
|
30
29
|
end
|
31
30
|
|
31
|
+
# Call zombifier
|
32
|
+
#
|
33
|
+
# @return [self]
|
34
|
+
#
|
35
|
+
# @api private
|
32
36
|
def self.call(*args)
|
33
37
|
new(*args).__send__(:call)
|
34
38
|
self
|
@@ -41,7 +45,6 @@ module Mutant
|
|
41
45
|
# @return [undefined]
|
42
46
|
#
|
43
47
|
# @api private
|
44
|
-
#
|
45
48
|
def call
|
46
49
|
@original = require_highjack.call(method(:require))
|
47
50
|
require(root_require)
|
@@ -52,7 +55,6 @@ module Mutant
|
|
52
55
|
# @param [String]
|
53
56
|
#
|
54
57
|
# @api private
|
55
|
-
#
|
56
58
|
def include?(logical_name)
|
57
59
|
!@zombified.include?(logical_name) && @includes =~ logical_name
|
58
60
|
end
|
@@ -64,7 +66,6 @@ module Mutant
|
|
64
66
|
# @return [undefined]
|
65
67
|
#
|
66
68
|
# @api private
|
67
|
-
#
|
68
69
|
def require(logical_name)
|
69
70
|
logical_name = logical_name.to_s
|
70
71
|
@original.call(logical_name)
|
@@ -83,7 +84,6 @@ module Mutant
|
|
83
84
|
# otherwise
|
84
85
|
#
|
85
86
|
# @api private
|
86
|
-
#
|
87
87
|
def find(logical_name)
|
88
88
|
file_name = "#{logical_name}.rb"
|
89
89
|
|
@@ -104,9 +104,6 @@ module Mutant
|
|
104
104
|
# @return [undefined]
|
105
105
|
#
|
106
106
|
# @api private
|
107
|
-
#
|
108
|
-
# rubocop:disable Lint/Eval
|
109
|
-
#
|
110
107
|
def zombify(source_path)
|
111
108
|
kernel.eval(
|
112
109
|
Unparser.unparse(namespaced_node(source_path)),
|
@@ -115,14 +112,13 @@ module Mutant
|
|
115
112
|
)
|
116
113
|
end
|
117
114
|
|
118
|
-
#
|
115
|
+
# Namespaced root node
|
119
116
|
#
|
120
117
|
# @param [Symbol] namespace
|
121
118
|
#
|
122
119
|
# @return [Parser::AST::Node]
|
123
120
|
#
|
124
121
|
# @api private
|
125
|
-
#
|
126
122
|
def namespaced_node(source_path)
|
127
123
|
s(:module, s(:const, nil, namespace), Parser::CurrentRuby.parse(source_path.read))
|
128
124
|
end
|
data/meta/send.rb
CHANGED
@@ -367,6 +367,8 @@ Mutant::Meta::Example.add do
|
|
367
367
|
mutation '1'
|
368
368
|
mutation 'foo'
|
369
369
|
mutation 'foo[]'
|
370
|
+
mutation 'foo.at(1)'
|
371
|
+
mutation 'foo.fetch(1)'
|
370
372
|
mutation 'self[1]'
|
371
373
|
mutation 'foo[0]'
|
372
374
|
mutation 'foo[2]'
|
@@ -380,6 +382,8 @@ Mutant::Meta::Example.add do
|
|
380
382
|
|
381
383
|
singleton_mutations
|
382
384
|
mutation 'self.foo'
|
385
|
+
mutation 'self.foo.at()'
|
386
|
+
mutation 'self.foo.fetch()'
|
383
387
|
mutation 'self[]'
|
384
388
|
mutation 'foo[]'
|
385
389
|
end
|
@@ -391,6 +395,8 @@ Mutant::Meta::Example.add do
|
|
391
395
|
mutation 'self[self]'
|
392
396
|
mutation 'self[nil]'
|
393
397
|
mutation 'self[]'
|
398
|
+
mutation 'self.at(foo)'
|
399
|
+
mutation 'self.fetch(foo)'
|
394
400
|
mutation 'foo'
|
395
401
|
end
|
396
402
|
|
@@ -400,6 +406,8 @@ Mutant::Meta::Example.add do
|
|
400
406
|
singleton_mutations
|
401
407
|
mutation 'foo'
|
402
408
|
mutation 'foo[]'
|
409
|
+
mutation 'foo.at(*bar)'
|
410
|
+
mutation 'foo.fetch(*bar)'
|
403
411
|
mutation 'foo[nil]'
|
404
412
|
mutation 'foo[self]'
|
405
413
|
mutation 'foo[bar]'
|
data/spec/spec_helper.rb
CHANGED
@@ -35,7 +35,7 @@ require 'test_app'
|
|
35
35
|
module Fixtures
|
36
36
|
TEST_CONFIG = Mutant::Config::DEFAULT.update(reporter: Mutant::Reporter::Trace.new)
|
37
37
|
TEST_CACHE = Mutant::Cache.new
|
38
|
-
TEST_ENV = Mutant::Env::Bootstrap.
|
38
|
+
TEST_ENV = Mutant::Env::Bootstrap.(TEST_CONFIG, TEST_CACHE)
|
39
39
|
end # Fixtures
|
40
40
|
|
41
41
|
module ParserHelper
|
@@ -46,6 +46,10 @@ module ParserHelper
|
|
46
46
|
def parse(string)
|
47
47
|
Unparser::Preprocessor.run(Parser::CurrentRuby.parse(string))
|
48
48
|
end
|
49
|
+
|
50
|
+
def parse_expression(string)
|
51
|
+
Mutant::Config::DEFAULT.expression_parser.(string)
|
52
|
+
end
|
49
53
|
end
|
50
54
|
|
51
55
|
module MessageHelper
|
data/spec/support/corpus.rb
CHANGED
@@ -31,6 +31,7 @@ module MutantSpec
|
|
31
31
|
#
|
32
32
|
# @raise [Exception]
|
33
33
|
#
|
34
|
+
# @api private
|
34
35
|
def verify_mutation_coverage
|
35
36
|
checkout
|
36
37
|
Dir.chdir(repo_path) do
|
@@ -60,6 +61,7 @@ module MutantSpec
|
|
60
61
|
#
|
61
62
|
# rubocop:disable AbcSize
|
62
63
|
#
|
64
|
+
# @api private
|
63
65
|
def verify_mutation_generation
|
64
66
|
checkout
|
65
67
|
start = Time.now
|
@@ -99,7 +101,6 @@ module MutantSpec
|
|
99
101
|
# @return [self]
|
100
102
|
#
|
101
103
|
# @api private
|
102
|
-
#
|
103
104
|
def checkout
|
104
105
|
return self if noinstall?
|
105
106
|
TMP.mkdir unless TMP.directory?
|
@@ -126,7 +127,6 @@ module MutantSpec
|
|
126
127
|
# @return [undefined]
|
127
128
|
#
|
128
129
|
# @api private
|
129
|
-
#
|
130
130
|
def install_mutant
|
131
131
|
return if noinstall?
|
132
132
|
relative = ROOT.relative_path_from(repo_path)
|
@@ -142,12 +142,11 @@ module MutantSpec
|
|
142
142
|
# Not in the docs. Number from chatting with their support.
|
143
143
|
CIRCLE_CI_CONTAINER_PROCESSES = 2
|
144
144
|
|
145
|
-
#
|
145
|
+
# Number of parallel processes to use
|
146
146
|
#
|
147
147
|
# @return [Fixnum]
|
148
148
|
#
|
149
149
|
# @api private
|
150
|
-
#
|
151
150
|
def parallel_processes
|
152
151
|
if ENV['CI']
|
153
152
|
Mutant::Config::DEFAULT.jobs
|
@@ -156,12 +155,11 @@ module MutantSpec
|
|
156
155
|
end
|
157
156
|
end
|
158
157
|
|
159
|
-
#
|
158
|
+
# Repository path
|
160
159
|
#
|
161
160
|
# @return [Pathname]
|
162
161
|
#
|
163
162
|
# @api private
|
164
|
-
#
|
165
163
|
def repo_path
|
166
164
|
TMP.join(name)
|
167
165
|
end
|
@@ -171,7 +169,6 @@ module MutantSpec
|
|
171
169
|
# @return [Boolean]
|
172
170
|
#
|
173
171
|
# @api private
|
174
|
-
#
|
175
172
|
def noinstall?
|
176
173
|
ENV.key?('NOINSTALL')
|
177
174
|
end
|
@@ -208,13 +205,12 @@ module MutantSpec
|
|
208
205
|
# @param [Array<String>] arguments
|
209
206
|
#
|
210
207
|
# @api private
|
211
|
-
#
|
212
208
|
def system(arguments)
|
213
209
|
return if Kernel.system(*arguments)
|
214
210
|
if block_given?
|
215
211
|
yield
|
216
212
|
else
|
217
|
-
fail
|
213
|
+
fail "System command failed!: #{arguments.join(' ')}"
|
218
214
|
end
|
219
215
|
end
|
220
216
|
|
data/spec/support/rb_bug.rb
CHANGED
data/spec/support/rspec.rb
CHANGED
data/spec/support/ruby_vm.rb
CHANGED
@@ -2,8 +2,6 @@ module MutantSpec
|
|
2
2
|
# Not a real VM, just kidding. It connects the require / eval triggers
|
3
3
|
# require semantics Zombifier relies on in a way we can avoid having to
|
4
4
|
# mock around everywhere to test every detail.
|
5
|
-
#
|
6
|
-
# rubocop:disable LineLength
|
7
5
|
class RubyVM
|
8
6
|
include Concord.new(:expected_events)
|
9
7
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
RSpec.describe Mutant::AST::Meta::Send do
|
2
|
+
let(:object) { described_class.new(node) }
|
3
|
+
|
4
|
+
def parse(source)
|
5
|
+
Parser::CurrentRuby.parse(source)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:method_call) { parse('foo.bar(baz)') }
|
9
|
+
let(:attribute_read) { parse('foo.bar') }
|
10
|
+
let(:index_assignment) { parse('foo[0] = bar') }
|
11
|
+
let(:attribute_assignment) { parse('foo.bar = baz') }
|
12
|
+
let(:binary_method_operator) { parse('foo == bar') }
|
13
|
+
|
14
|
+
class Expectation
|
15
|
+
include Adamantium, Anima.new(:name, :assignment, :attribute_assignment, :index_assignment, :binary_method_operator)
|
16
|
+
|
17
|
+
ALL = [
|
18
|
+
[:method_call, false, false, false, false],
|
19
|
+
[:attribute_read, false, false, false, false],
|
20
|
+
[:index_assignment, true, false, true, false],
|
21
|
+
[:attribute_assignment, true, true, false, false],
|
22
|
+
[:binary_method_operator, false, false, false, true]
|
23
|
+
].map do |values|
|
24
|
+
new(Hash[anima.attribute_names.zip(values)])
|
25
|
+
end.freeze
|
26
|
+
end
|
27
|
+
|
28
|
+
# Rspec should have a build in for this kind of "n-dimensional assertion with context"
|
29
|
+
(Expectation.anima.attribute_names - %i[name]).each do |name|
|
30
|
+
describe "##{name}?" do
|
31
|
+
subject { object.public_send(:"#{name}?") }
|
32
|
+
|
33
|
+
Expectation::ALL.each do |expectation|
|
34
|
+
context "on #{expectation.name}" do
|
35
|
+
let(:node) { public_send(expectation.name) }
|
36
|
+
|
37
|
+
it { should be(expectation.public_send(name)) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
RSpec.describe Mutant::AST::NamedChildren do
|
2
|
+
describe '.included' do
|
3
|
+
let(:klass) do
|
4
|
+
Class.new do
|
5
|
+
include Mutant::AST::NamedChildren, Concord.new(:node)
|
6
|
+
|
7
|
+
children :foo, :bar
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:instance) { klass.new(node) }
|
12
|
+
|
13
|
+
let(:node_foo) { s(:foo) }
|
14
|
+
let(:node_bar) { s(:bar) }
|
15
|
+
let(:node_baz) { s(:baz) }
|
16
|
+
|
17
|
+
let(:node) { s(:node, node_foo, node_bar, node_baz) }
|
18
|
+
|
19
|
+
describe 'generated methods' do
|
20
|
+
describe '#remaining_children' do
|
21
|
+
it 'returns remaining unnamed children' do
|
22
|
+
expect(instance.remaining_children).to eql([node_baz])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#remaining_children_indices' do
|
27
|
+
it 'returns remaining unnamed children indices' do
|
28
|
+
expect(instance.remaining_children_indices).to eql([2])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#remaining_children_with_index' do
|
33
|
+
it 'returns remaining unnamed children indices' do
|
34
|
+
expect(instance.remaining_children_with_index).to eql([[node_baz, 2]])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#foo' do
|
39
|
+
it 'returns named child foo' do
|
40
|
+
expect(instance.foo).to be(node_foo)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#bar' do
|
45
|
+
it 'returns named child bar' do
|
46
|
+
expect(instance.bar).to be(node_bar)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
RSpec.describe Mutant::AST::Sexp do
|
2
|
+
let(:object) do
|
3
|
+
Class.new do
|
4
|
+
include Mutant::AST::Sexp
|
5
|
+
|
6
|
+
public :n_not
|
7
|
+
public :s
|
8
|
+
end.new
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#n_not' do
|
12
|
+
subject { object.n_not(node) }
|
13
|
+
|
14
|
+
let(:node) { s(:true) }
|
15
|
+
|
16
|
+
it 'returns negated ast' do
|
17
|
+
expect(subject).to eql(s(:send, s(:true), :!))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#s' do
|
22
|
+
subject { object.s(*arguments) }
|
23
|
+
|
24
|
+
context 'with single argument' do
|
25
|
+
let(:arguments) { %i[foo] }
|
26
|
+
|
27
|
+
it { should eql(Parser::AST::Node.new(:foo)) }
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'with single multiple arguments' do
|
31
|
+
let(:arguments) { %i[foo bar baz] }
|
32
|
+
|
33
|
+
it { should eql(Parser::AST::Node.new(:foo, %i[bar baz])) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -19,6 +19,14 @@ RSpec.describe Mutant::AST do
|
|
19
19
|
it { should eql([]) }
|
20
20
|
end
|
21
21
|
|
22
|
+
context 'when called without block' do
|
23
|
+
let(:block) { nil }
|
24
|
+
|
25
|
+
it 'raises error' do
|
26
|
+
expect { subject }.to raise_error(ArgumentError, 'block expected')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
22
30
|
context 'when one node matches' do
|
23
31
|
let(:block) { ->(node) { node.equal?(child_a) } }
|
24
32
|
|
@@ -1,20 +1,20 @@
|
|
1
|
-
RSpec.shared_examples_for 'an invalid cli run' do
|
2
|
-
it 'raises error' do
|
3
|
-
expect do
|
4
|
-
subject
|
5
|
-
end.to raise_error(Mutant::CLI::Error, expected_message)
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
RSpec.shared_examples_for 'a cli parser' do
|
10
|
-
it { expect(subject.config.integration).to eql(expected_integration) }
|
11
|
-
it { expect(subject.config.reporter).to eql(expected_reporter) }
|
12
|
-
it { expect(subject.config.matcher).to eql(expected_matcher_config) }
|
13
|
-
end
|
14
|
-
|
15
1
|
RSpec.describe Mutant::CLI do
|
16
2
|
let(:object) { described_class }
|
17
3
|
|
4
|
+
shared_examples_for 'an invalid cli run' do
|
5
|
+
it 'raises error' do
|
6
|
+
expect do
|
7
|
+
subject
|
8
|
+
end.to raise_error(Mutant::CLI::Error, expected_message)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
shared_examples_for 'a cli parser' do
|
13
|
+
it { expect(subject.config.integration).to eql(expected_integration) }
|
14
|
+
it { expect(subject.config.reporter).to eql(expected_reporter) }
|
15
|
+
it { expect(subject.config.matcher).to eql(expected_matcher_config) }
|
16
|
+
end
|
17
|
+
|
18
18
|
describe '.run' do
|
19
19
|
subject { object.run(arguments) }
|
20
20
|
|
@@ -67,13 +67,13 @@ RSpec.describe Mutant::CLI do
|
|
67
67
|
|
68
68
|
# Defaults
|
69
69
|
let(:expected_filter) { Morpher.evaluator(s(:true)) }
|
70
|
-
let(:expected_integration) { Mutant::Integration::Null
|
70
|
+
let(:expected_integration) { Mutant::Integration::Null }
|
71
71
|
let(:expected_reporter) { Mutant::Config::DEFAULT.reporter }
|
72
72
|
let(:expected_matcher_config) { default_matcher_config }
|
73
73
|
|
74
74
|
let(:default_matcher_config) do
|
75
75
|
Mutant::Matcher::Config::DEFAULT
|
76
|
-
.update(match_expressions: expressions.map(&
|
76
|
+
.update(match_expressions: expressions.map(&method(:parse_expression)))
|
77
77
|
end
|
78
78
|
|
79
79
|
let(:flags) { [] }
|
@@ -127,7 +127,8 @@ Environment:
|
|
127
127
|
Options:
|
128
128
|
--expected-coverage COVERAGE Fail unless COVERAGE is not reached exactly, parsed via Rational()
|
129
129
|
--use INTEGRATION Use INTEGRATION to kill mutations
|
130
|
-
--ignore-subject
|
130
|
+
--ignore-subject EXPRESSION Ignore subjects that match EXPRESSION as prefix
|
131
|
+
--since REVISION Only select subjects touched since REVISION
|
131
132
|
--fail-fast Fail fast
|
132
133
|
--version Print mutants version
|
133
134
|
-d, --debug Enable debugging output
|
@@ -152,7 +153,7 @@ Options:
|
|
152
153
|
|
153
154
|
it_should_behave_like 'a cli parser'
|
154
155
|
|
155
|
-
let(:expected_integration) { Mutant::Integration::Rspec
|
156
|
+
let(:expected_integration) { Mutant::Integration::Rspec }
|
156
157
|
end
|
157
158
|
|
158
159
|
context 'when integration does NOT exist' do
|
@@ -230,11 +231,25 @@ Options:
|
|
230
231
|
end
|
231
232
|
end
|
232
233
|
|
234
|
+
context 'with --since flag' do
|
235
|
+
let(:flags) { %w[--since master] }
|
236
|
+
|
237
|
+
let(:expected_matcher_config) do
|
238
|
+
default_matcher_config.update(
|
239
|
+
subject_filters: [
|
240
|
+
Mutant::Repository::SubjectFilter.new(Mutant::Repository::Diff.new('HEAD', 'master'))
|
241
|
+
]
|
242
|
+
)
|
243
|
+
end
|
244
|
+
|
245
|
+
it_should_behave_like 'a cli parser'
|
246
|
+
end
|
247
|
+
|
233
248
|
context 'with subject-ignore flag' do
|
234
249
|
let(:flags) { %w[--ignore-subject Foo::Bar] }
|
235
250
|
|
236
251
|
let(:expected_matcher_config) do
|
237
|
-
default_matcher_config.update(
|
252
|
+
default_matcher_config.update(ignore_expressions: [parse_expression('Foo::Bar')])
|
238
253
|
end
|
239
254
|
|
240
255
|
it_should_behave_like 'a cli parser'
|