mutant 0.2.20 → 0.3.0.beta2
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 +7 -0
- data/.travis.yml +10 -11
- data/Changelog.md +93 -38
- data/Gemfile +3 -1
- data/Gemfile.devtools +16 -20
- data/Guardfile +1 -1
- data/README.md +36 -16
- data/Rakefile +21 -2
- data/TODO +11 -7
- data/bin/mutant +4 -0
- data/bin/zombie +4 -0
- data/config/devtools.yml +2 -0
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/{site.reek → reek.yml} +94 -70
- data/lib/mutant/cli/classifier/method.rb +100 -0
- data/lib/mutant/cli/classifier/namespace.rb +47 -0
- data/lib/mutant/cli/classifier/scope.rb +35 -0
- data/lib/mutant/cli/classifier.rb +141 -0
- data/lib/mutant/cli.rb +115 -162
- data/lib/mutant/color.rb +2 -2
- data/lib/mutant/config.rb +27 -0
- data/lib/mutant/constants.rb +32 -17
- data/lib/mutant/context/scope.rb +33 -51
- data/lib/mutant/context.rb +8 -19
- data/lib/mutant/differ.rb +5 -5
- data/lib/mutant/helper.rb +2 -17
- data/lib/mutant/killer/forked.rb +44 -0
- data/lib/mutant/killer/forking.rb +3 -57
- data/lib/mutant/killer/rspec.rb +16 -20
- data/lib/mutant/killer/static.rb +6 -7
- data/lib/mutant/killer.rb +48 -74
- data/lib/mutant/loader.rb +6 -6
- data/lib/mutant/matcher/chain.rb +4 -25
- data/lib/mutant/matcher/method/instance.rb +14 -24
- data/lib/mutant/matcher/method/singleton.rb +35 -46
- data/lib/mutant/matcher/method.rb +95 -83
- data/lib/mutant/matcher/{scope_methods.rb → methods.rb} +53 -76
- data/lib/mutant/matcher/namespace.rb +71 -0
- data/lib/mutant/matcher/scope.rb +34 -0
- data/lib/mutant/matcher.rb +24 -34
- data/lib/mutant/mutation/evil.rb +35 -0
- data/lib/mutant/mutation/filter/code.rb +7 -28
- data/lib/mutant/mutation/filter/regexp.rb +6 -18
- data/lib/mutant/mutation/filter/whitelist.rb +5 -4
- data/lib/mutant/mutation/filter.rb +10 -9
- data/lib/mutant/mutation/neutral.rb +35 -0
- data/lib/mutant/mutation.rb +21 -61
- data/lib/mutant/mutator/node/argument.rb +88 -0
- data/lib/mutant/mutator/node/arguments.rb +52 -0
- data/lib/mutant/mutator/node/assignment.rb +34 -38
- data/lib/mutant/mutator/node/begin.rb +33 -0
- data/lib/mutant/mutator/node/block.rb +14 -14
- data/lib/mutant/mutator/node/case.rb +59 -0
- data/lib/mutant/mutator/node/define.rb +26 -22
- data/lib/mutant/mutator/node/if.rb +31 -71
- data/lib/mutant/mutator/node/literal/array.rb +25 -9
- data/lib/mutant/mutator/node/literal/boolean.rb +13 -30
- data/lib/mutant/mutator/node/literal/dynamic.rb +6 -5
- data/lib/mutant/mutator/node/literal/fixnum.rb +18 -7
- data/lib/mutant/mutator/node/literal/float.rb +15 -8
- data/lib/mutant/mutator/node/literal/hash.rb +33 -52
- data/lib/mutant/mutator/node/literal/nil.rb +8 -7
- data/lib/mutant/mutator/node/literal/range.rb +25 -50
- data/lib/mutant/mutator/node/literal/regex.rb +15 -23
- data/lib/mutant/mutator/node/literal/string.rb +7 -6
- data/lib/mutant/mutator/node/literal/symbol.rb +7 -6
- data/lib/mutant/mutator/node/literal.rb +4 -46
- data/lib/mutant/mutator/node/mlhs.rb +27 -0
- data/lib/mutant/mutator/node/noop.rb +18 -43
- data/lib/mutant/mutator/node/return.rb +8 -8
- data/lib/mutant/mutator/node/send/binary.rb +31 -0
- data/lib/mutant/mutator/node/send.rb +106 -72
- data/lib/mutant/mutator/node/super.rb +15 -20
- data/lib/mutant/mutator/node/when.rb +32 -7
- data/lib/mutant/mutator/node/while.rb +9 -7
- data/lib/mutant/mutator/node.rb +116 -66
- data/lib/mutant/mutator/registry.rb +14 -11
- data/lib/mutant/mutator/util/array.rb +9 -9
- data/lib/mutant/mutator/util/symbol.rb +6 -20
- data/lib/mutant/mutator/util.rb +6 -3
- data/lib/mutant/mutator.rb +12 -28
- data/lib/mutant/node_helpers.rb +28 -0
- data/lib/mutant/random.rb +3 -2
- data/lib/mutant/reporter/cli/printer/config.rb +174 -0
- data/lib/mutant/reporter/cli/printer/killer.rb +42 -0
- data/lib/mutant/reporter/cli/printer/mutation.rb +55 -0
- data/lib/mutant/reporter/cli/printer/subject.rb +147 -0
- data/lib/mutant/reporter/cli/printer.rb +165 -0
- data/lib/mutant/reporter/cli.rb +9 -277
- data/lib/mutant/reporter/null.rb +6 -30
- data/lib/mutant/reporter.rb +6 -73
- data/lib/mutant/runner/config.rb +82 -0
- data/lib/mutant/runner/mutation.rb +58 -0
- data/lib/mutant/runner/subject.rb +81 -0
- data/lib/mutant/runner.rb +42 -92
- data/lib/mutant/singleton_methods.rb +2 -2
- data/lib/mutant/strategy/method_expansion.rb +51 -0
- data/lib/mutant/strategy/rspec/dm2/lookup/method.rb +142 -0
- data/lib/mutant/strategy/rspec/dm2/lookup.rb +61 -0
- data/lib/mutant/strategy/rspec/dm2.rb +22 -0
- data/lib/mutant/strategy/rspec.rb +20 -22
- data/lib/mutant/strategy/static.rb +18 -0
- data/lib/mutant/strategy.rb +15 -50
- data/lib/mutant/subject/method.rb +100 -0
- data/lib/mutant/subject.rb +18 -49
- data/lib/mutant/support/method_object.rb +4 -2
- data/lib/mutant.rb +40 -35
- data/mutant.gemspec +9 -8
- data/spec/integration/mutant/rspec_killer_spec.rb +3 -3
- data/spec/integration/mutant/test_mutator_handles_types_spec.rb +9 -0
- data/spec/integration/mutant/zombie_spec.rb +1 -1
- data/spec/shared/method_matcher_behavior.rb +35 -0
- data/spec/shared/mutator_behavior.rb +63 -32
- data/spec/spec_helper.rb +13 -3
- data/spec/support/ice_nine_config.rb +8 -0
- data/spec/support/rspec.rb +1 -1
- data/spec/support/zombie.rb +1 -1
- data/spec/unit/mutant/cli/class_methods/new_spec.rb +42 -28
- data/spec/unit/mutant/cli/class_methods/run_spec.rb +15 -13
- data/spec/unit/mutant/cli/classifier/class_methods/build_spec.rb +44 -0
- data/spec/unit/mutant/context/scope/root_spec.rb +4 -4
- data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +6 -5
- data/spec/unit/mutant/killer/success_predicate_spec.rb +28 -0
- data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +1 -1
- data/spec/unit/mutant/matcher/chain/each_spec.rb +1 -1
- data/spec/unit/mutant/matcher/chain/matchers_spec.rb +1 -1
- data/spec/unit/mutant/matcher/method/instance/each_spec.rb +112 -0
- data/spec/unit/mutant/matcher/method/singleton/each_spec.rb +93 -0
- data/spec/unit/mutant/matcher/methods/instance/each_spec.rb +59 -0
- data/spec/unit/mutant/matcher/methods/singleton/each_spec.rb +53 -0
- data/spec/unit/mutant/matcher/namespace/each_spec.rb +37 -0
- data/spec/unit/mutant/mutator/node/begin/mutation_spec.rb +33 -0
- data/spec/unit/mutant/mutator/node/block/mutation_spec.rb +42 -14
- data/spec/unit/mutant/mutator/node/case/mutation_spec.rb +319 -0
- data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +31 -27
- data/spec/unit/mutant/mutator/node/if/mutation_spec.rb +75 -0
- data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +1 -1
- data/spec/unit/mutant/mutator/node/literal/hash_spec.rb +2 -2
- data/spec/unit/mutant/mutator/node/literal/nil_spec.rb +1 -3
- data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +1 -9
- data/spec/unit/mutant/mutator/node/return/mutation_spec.rb +6 -2
- data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +111 -108
- data/spec/unit/mutant/mutator/node/super/mutation_spec.rb +0 -33
- data/spec/unit/mutant/mutator/node/while/mutation_spec.rb +2 -2
- data/spec/unit/mutant/runner/config/subjects_spec.rb +38 -0
- data/spec/unit/mutant/runner/config/success_predicate_spec.rb +53 -0
- data/spec/unit/mutant/runner/failed_predicte_spec.rb +33 -0
- data/spec/unit/mutant/runner/mutation/killer_spec.rb +39 -0
- data/spec/unit/mutant/runner/subject/success_predicate_spec.rb +49 -0
- data/spec/unit/mutant/strategy/method_expansion/class_methods/run_spec.rb +49 -0
- data/spec/unit/mutant/strategy/rspec/dm2/lookup/method/instance/spec_files_spec.rb +52 -0
- data/spec/unit/mutant/strategy/rspec/dm2/lookup/method/singleton/spec_files_spec.rb +42 -0
- data/spec/unit/mutant/subject/context_spec.rb +6 -3
- data/spec/unit/mutant/subject/each_spec.rb +11 -8
- data/spec/unit/mutant/subject/node_spec.rb +6 -2
- data/test_app/spec/shared/method_filter_parse_behavior.rb +0 -2
- data/test_app/spec/shared/method_match_behavior.rb +1 -1
- data/test_app/spec/spec_helper.rb +4 -2
- metadata +101 -109
- data/config/roodi.yml +0 -26
- data/lib/mutant/matcher/method/classifier.rb +0 -141
- data/lib/mutant/matcher/object_space.rb +0 -114
- data/lib/mutant/mutator/node/actual_arguments.rb +0 -25
- data/lib/mutant/mutator/node/default_arguments.rb +0 -25
- data/lib/mutant/mutator/node/formal_arguments_19/default_mutations.rb +0 -33
- data/lib/mutant/mutator/node/formal_arguments_19/pattern_argument_expansion.rb +0 -35
- data/lib/mutant/mutator/node/formal_arguments_19/require_defaults.rb +0 -37
- data/lib/mutant/mutator/node/formal_arguments_19.rb +0 -41
- data/lib/mutant/mutator/node/iter_19.rb +0 -27
- data/lib/mutant/mutator/node/literal/empty_array.rb +0 -26
- data/lib/mutant/mutator/node/pattern_arguments.rb +0 -41
- data/lib/mutant/mutator/node/pattern_variable.rb +0 -23
- data/lib/mutant/mutator/node/receiver_case.rb +0 -122
- data/lib/mutant/mutator/node/send/binary_operator_method.rb +0 -61
- data/lib/mutant/mutator/node/send/with_arguments.rb +0 -81
- data/lib/mutant/reporter/stats.rb +0 -120
- data/lib/mutant/strategy/rspec/example_lookup.rb +0 -163
- data/spec/integration/mutant/method_matching_spec.rb +0 -269
- data/spec/shared/method_match_behavior.rb +0 -39
- data/spec/unit/mutant/killer/fail_ques_spec.rb +0 -39
- data/spec/unit/mutant/matcher/class_methods/from_string_spec.rb +0 -49
- data/spec/unit/mutant/matcher/class_methods/parse_spec.rb +0 -12
- data/spec/unit/mutant/matcher/method/class_methods/parse_spec.rb +0 -21
- data/spec/unit/mutant/matcher/method/classifier/class_methods/run_spec.rb +0 -52
- data/spec/unit/mutant/matcher/object_space/class_methods/parse_spec.rb +0 -24
- data/spec/unit/mutant/matcher/object_space/each_spec.rb +0 -31
- data/spec/unit/mutant/mutator/node/if_statement/mutation_spec.rb +0 -60
- data/spec/unit/mutant/mutator/node/receiver_case/mutation_spec.rb +0 -27
- data/spec/unit/mutant/strategy/rspec/example_lookup/spec_file_spec.rb +0 -236
- data/spec/unit/mutant/subject/class_methods/new_spec.rb +0 -13
- data/tasks/metrics/ci.rake +0 -7
- data/tasks/metrics/flay.rake +0 -41
- data/tasks/metrics/flog.rake +0 -43
- data/tasks/metrics/heckle.rake +0 -216
- data/tasks/metrics/metric_fu.rake +0 -31
- data/tasks/metrics/reek.rake +0 -15
- data/tasks/metrics/roodi.rake +0 -15
- data/tasks/metrics/yardstick.rake +0 -23
- data/tasks/spec.rake +0 -45
- data/tasks/yard.rake +0 -9
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Subject
|
|
3
|
+
# Abstract base class for method subjects
|
|
4
|
+
class Method < self
|
|
5
|
+
|
|
6
|
+
# Test if method is public
|
|
7
|
+
#
|
|
8
|
+
# @return [true]
|
|
9
|
+
# if method is public
|
|
10
|
+
#
|
|
11
|
+
# @return [false]
|
|
12
|
+
# otherwise
|
|
13
|
+
#
|
|
14
|
+
# @api private
|
|
15
|
+
#
|
|
16
|
+
abstract_method :public?
|
|
17
|
+
|
|
18
|
+
# Return method name
|
|
19
|
+
#
|
|
20
|
+
# @return [Symbol]
|
|
21
|
+
#
|
|
22
|
+
# @api private
|
|
23
|
+
#
|
|
24
|
+
def name
|
|
25
|
+
node.children[self.class::NAME_INDEX]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
# Return scope
|
|
31
|
+
#
|
|
32
|
+
# @return [Class, Module]
|
|
33
|
+
#
|
|
34
|
+
# @api private
|
|
35
|
+
#
|
|
36
|
+
def scope
|
|
37
|
+
context.scope
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Return subtype identifier
|
|
41
|
+
#
|
|
42
|
+
# @return [String]
|
|
43
|
+
#
|
|
44
|
+
# @api private
|
|
45
|
+
#
|
|
46
|
+
def subtype
|
|
47
|
+
"#{context.identification}#{self.class::SYMBOL}#{name}"
|
|
48
|
+
end
|
|
49
|
+
|
|
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
|
+
end # Method
|
|
99
|
+
end # Subject
|
|
100
|
+
end # Mutant
|
data/lib/mutant/subject.rb
CHANGED
|
@@ -1,31 +1,7 @@
|
|
|
1
1
|
module Mutant
|
|
2
2
|
# Subject of a mutation
|
|
3
3
|
class Subject
|
|
4
|
-
include Adamantium::Flat, Enumerable,
|
|
5
|
-
|
|
6
|
-
# Return context
|
|
7
|
-
#
|
|
8
|
-
# @return [Context]
|
|
9
|
-
#
|
|
10
|
-
# @api private
|
|
11
|
-
#
|
|
12
|
-
attr_reader :context
|
|
13
|
-
|
|
14
|
-
# Return matcher
|
|
15
|
-
#
|
|
16
|
-
# @return [Matcher]
|
|
17
|
-
#
|
|
18
|
-
# @api private
|
|
19
|
-
#
|
|
20
|
-
attr_reader :matcher
|
|
21
|
-
|
|
22
|
-
# Return AST node
|
|
23
|
-
#
|
|
24
|
-
# @return [Rubinius::AST::Node]
|
|
25
|
-
#
|
|
26
|
-
# @api private
|
|
27
|
-
#
|
|
28
|
-
attr_reader :node
|
|
4
|
+
include AbstractType, Adamantium::Flat, Enumerable, Concord::Public.new(:context, :node)
|
|
29
5
|
|
|
30
6
|
# Enumerate possible mutations
|
|
31
7
|
#
|
|
@@ -40,7 +16,7 @@ module Mutant
|
|
|
40
16
|
def each
|
|
41
17
|
return to_enum unless block_given?
|
|
42
18
|
Mutator.each(node) do |mutant|
|
|
43
|
-
yield Mutation.new(self, mutant)
|
|
19
|
+
yield Mutation::Evil.new(self, mutant)
|
|
44
20
|
end
|
|
45
21
|
|
|
46
22
|
self
|
|
@@ -53,7 +29,7 @@ module Mutant
|
|
|
53
29
|
# @api private
|
|
54
30
|
#
|
|
55
31
|
def noop
|
|
56
|
-
Mutation::
|
|
32
|
+
Mutation::Neutral.new(self, node)
|
|
57
33
|
end
|
|
58
34
|
memoize :noop
|
|
59
35
|
|
|
@@ -74,36 +50,36 @@ module Mutant
|
|
|
74
50
|
# @api private
|
|
75
51
|
#
|
|
76
52
|
def source_line
|
|
77
|
-
node.line
|
|
53
|
+
node.location.expression.line
|
|
78
54
|
end
|
|
79
55
|
|
|
80
|
-
# Return subject
|
|
56
|
+
# Return subject identification
|
|
81
57
|
#
|
|
82
58
|
# @return [String]
|
|
83
59
|
#
|
|
84
60
|
# @api private
|
|
85
61
|
#
|
|
86
62
|
def identification
|
|
87
|
-
"#{
|
|
63
|
+
"#{subtype}:#{source_path}:#{source_line}"
|
|
88
64
|
end
|
|
89
65
|
memoize :identification
|
|
90
66
|
|
|
91
67
|
# Return source representation of ast
|
|
92
68
|
#
|
|
93
|
-
# @return [
|
|
69
|
+
# @return [String]
|
|
94
70
|
#
|
|
95
71
|
# @api private
|
|
96
|
-
#
|
|
72
|
+
#
|
|
97
73
|
def source
|
|
98
|
-
|
|
74
|
+
Unparser.unparse(node)
|
|
99
75
|
end
|
|
100
76
|
memoize :source
|
|
101
77
|
|
|
102
78
|
# Return root AST for node
|
|
103
79
|
#
|
|
104
|
-
# @param [
|
|
80
|
+
# @param [Parser::AST::Node] node
|
|
105
81
|
#
|
|
106
|
-
# @return [
|
|
82
|
+
# @return [Parser::AST::Node]
|
|
107
83
|
#
|
|
108
84
|
# @api private
|
|
109
85
|
#
|
|
@@ -113,7 +89,7 @@ module Mutant
|
|
|
113
89
|
|
|
114
90
|
# Return root AST node for original AST ndoe
|
|
115
91
|
#
|
|
116
|
-
# @return [
|
|
92
|
+
# @return [Parser::AST::Node]
|
|
117
93
|
#
|
|
118
94
|
# @api private
|
|
119
95
|
#
|
|
@@ -124,21 +100,14 @@ module Mutant
|
|
|
124
100
|
|
|
125
101
|
private
|
|
126
102
|
|
|
127
|
-
#
|
|
128
|
-
#
|
|
129
|
-
# @param [Matcher] matcher
|
|
130
|
-
# the context of mutations
|
|
131
|
-
#
|
|
132
|
-
# @param [Rubinius::AST::Node] node
|
|
133
|
-
# the node to be mutated
|
|
103
|
+
# Return subtype identifier
|
|
134
104
|
#
|
|
135
|
-
# @return [
|
|
105
|
+
# @return [String]
|
|
136
106
|
#
|
|
137
107
|
# @api private
|
|
138
108
|
#
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
end
|
|
109
|
+
abstract_method :subtype
|
|
110
|
+
private :subtype
|
|
142
111
|
|
|
143
|
-
end
|
|
144
|
-
end
|
|
112
|
+
end # Subject
|
|
113
|
+
end # Mutant
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
module Mutant
|
|
2
2
|
# A mixing to create method object semantics
|
|
3
3
|
module MethodObject
|
|
4
|
+
|
|
4
5
|
# Hook called when descendant is extended
|
|
5
6
|
#
|
|
6
7
|
# @param [Module|Class] descendant
|
|
@@ -27,5 +28,6 @@ module Mutant
|
|
|
27
28
|
def run(*args)
|
|
28
29
|
new(*args)
|
|
29
30
|
end
|
|
30
|
-
|
|
31
|
-
end
|
|
31
|
+
|
|
32
|
+
end # MethodObject
|
|
33
|
+
end # Mutant
|
data/lib/mutant.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'benchmark'
|
|
2
2
|
require 'set'
|
|
3
3
|
require 'adamantium'
|
|
4
4
|
require 'ice_nine'
|
|
@@ -8,29 +8,21 @@ require 'securerandom'
|
|
|
8
8
|
require 'equalizer'
|
|
9
9
|
require 'digest/sha1'
|
|
10
10
|
require 'inflecto'
|
|
11
|
-
require '
|
|
11
|
+
require 'parser'
|
|
12
|
+
require 'parser/current'
|
|
13
|
+
require 'unparser'
|
|
12
14
|
require 'ice_nine'
|
|
13
15
|
require 'diff/lcs'
|
|
14
16
|
require 'diff/lcs/hunk'
|
|
15
17
|
require 'rspec'
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class IceNine::Freezer
|
|
19
|
-
# Rubinius namsepace
|
|
20
|
-
class Rubinius
|
|
21
|
-
# AST namespace
|
|
22
|
-
class AST < IceNine::Freezer::Object
|
|
23
|
-
# Node configuration
|
|
24
|
-
class Node < IceNine::Freezer::Object
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
18
|
+
require 'anima'
|
|
19
|
+
require 'concord'
|
|
29
20
|
|
|
30
21
|
# Library namespace
|
|
31
22
|
module Mutant
|
|
32
23
|
end
|
|
33
24
|
|
|
25
|
+
require 'mutant/node_helpers'
|
|
34
26
|
require 'mutant/singleton_methods'
|
|
35
27
|
require 'mutant/constants'
|
|
36
28
|
require 'mutant/support/method_object'
|
|
@@ -38,6 +30,8 @@ require 'mutant/helper'
|
|
|
38
30
|
require 'mutant/random'
|
|
39
31
|
require 'mutant/mutator'
|
|
40
32
|
require 'mutant/mutation'
|
|
33
|
+
require 'mutant/mutation/evil'
|
|
34
|
+
require 'mutant/mutation/neutral'
|
|
41
35
|
require 'mutant/mutation/filter'
|
|
42
36
|
require 'mutant/mutation/filter/code'
|
|
43
37
|
require 'mutant/mutation/filter/whitelist'
|
|
@@ -55,55 +49,66 @@ require 'mutant/mutator/node/literal/string'
|
|
|
55
49
|
require 'mutant/mutator/node/literal/fixnum'
|
|
56
50
|
require 'mutant/mutator/node/literal/float'
|
|
57
51
|
require 'mutant/mutator/node/literal/array'
|
|
58
|
-
require 'mutant/mutator/node/literal/empty_array'
|
|
59
52
|
require 'mutant/mutator/node/literal/hash'
|
|
60
53
|
require 'mutant/mutator/node/literal/regex'
|
|
61
54
|
require 'mutant/mutator/node/literal/nil'
|
|
62
|
-
require 'mutant/mutator/node/
|
|
55
|
+
require 'mutant/mutator/node/assignment'
|
|
56
|
+
require 'mutant/mutator/node/argument'
|
|
57
|
+
require 'mutant/mutator/node/arguments'
|
|
58
|
+
require 'mutant/mutator/node/begin'
|
|
63
59
|
require 'mutant/mutator/node/while'
|
|
64
60
|
require 'mutant/mutator/node/super'
|
|
65
61
|
require 'mutant/mutator/node/send'
|
|
66
|
-
require 'mutant/mutator/node/send/
|
|
67
|
-
require 'mutant/mutator/node/send/binary_operator_method'
|
|
62
|
+
require 'mutant/mutator/node/send/binary'
|
|
68
63
|
require 'mutant/mutator/node/when'
|
|
69
64
|
require 'mutant/mutator/node/assignment'
|
|
70
65
|
require 'mutant/mutator/node/define'
|
|
71
|
-
require 'mutant/mutator/node/
|
|
72
|
-
require 'mutant/mutator/node/formal_arguments_19/default_mutations'
|
|
73
|
-
require 'mutant/mutator/node/formal_arguments_19/require_defaults'
|
|
74
|
-
require 'mutant/mutator/node/formal_arguments_19/pattern_argument_expansion'
|
|
75
|
-
require 'mutant/mutator/node/actual_arguments'
|
|
76
|
-
require 'mutant/mutator/node/pattern_arguments'
|
|
77
|
-
require 'mutant/mutator/node/pattern_variable'
|
|
78
|
-
require 'mutant/mutator/node/default_arguments'
|
|
66
|
+
require 'mutant/mutator/node/mlhs'
|
|
79
67
|
require 'mutant/mutator/node/return'
|
|
80
|
-
require 'mutant/mutator/node/
|
|
68
|
+
require 'mutant/mutator/node/block'
|
|
81
69
|
require 'mutant/mutator/node/if'
|
|
82
|
-
require 'mutant/mutator/node/
|
|
83
|
-
require 'mutant/
|
|
70
|
+
require 'mutant/mutator/node/case'
|
|
71
|
+
require 'mutant/config'
|
|
72
|
+
require 'mutant/loader'
|
|
84
73
|
require 'mutant/context'
|
|
85
74
|
require 'mutant/context/scope'
|
|
86
75
|
require 'mutant/subject'
|
|
76
|
+
require 'mutant/subject/method'
|
|
87
77
|
require 'mutant/matcher'
|
|
88
78
|
require 'mutant/matcher/chain'
|
|
89
|
-
require 'mutant/matcher/object_space'
|
|
90
79
|
require 'mutant/matcher/method'
|
|
91
80
|
require 'mutant/matcher/method/singleton'
|
|
92
81
|
require 'mutant/matcher/method/instance'
|
|
93
|
-
require 'mutant/matcher/
|
|
94
|
-
require 'mutant/matcher/
|
|
82
|
+
require 'mutant/matcher/methods'
|
|
83
|
+
require 'mutant/matcher/namespace'
|
|
84
|
+
require 'mutant/matcher/scope'
|
|
95
85
|
require 'mutant/killer'
|
|
96
86
|
require 'mutant/killer/static'
|
|
97
87
|
require 'mutant/killer/rspec'
|
|
98
88
|
require 'mutant/killer/forking'
|
|
89
|
+
require 'mutant/killer/forked'
|
|
99
90
|
require 'mutant/strategy'
|
|
91
|
+
require 'mutant/strategy/static'
|
|
92
|
+
require 'mutant/strategy/method_expansion'
|
|
100
93
|
require 'mutant/strategy/rspec'
|
|
101
|
-
require 'mutant/strategy/rspec/
|
|
94
|
+
require 'mutant/strategy/rspec/dm2'
|
|
95
|
+
require 'mutant/strategy/rspec/dm2/lookup'
|
|
96
|
+
require 'mutant/strategy/rspec/dm2/lookup/method'
|
|
102
97
|
require 'mutant/runner'
|
|
98
|
+
require 'mutant/runner/config'
|
|
99
|
+
require 'mutant/runner/subject'
|
|
100
|
+
require 'mutant/runner/mutation'
|
|
103
101
|
require 'mutant/cli'
|
|
102
|
+
require 'mutant/cli/classifier'
|
|
103
|
+
require 'mutant/cli/classifier/namespace'
|
|
104
|
+
require 'mutant/cli/classifier/method'
|
|
104
105
|
require 'mutant/color'
|
|
105
106
|
require 'mutant/differ'
|
|
106
107
|
require 'mutant/reporter'
|
|
107
|
-
require 'mutant/reporter/stats'
|
|
108
108
|
require 'mutant/reporter/null'
|
|
109
109
|
require 'mutant/reporter/cli'
|
|
110
|
+
require 'mutant/reporter/cli/printer'
|
|
111
|
+
require 'mutant/reporter/cli/printer/config'
|
|
112
|
+
require 'mutant/reporter/cli/printer/subject'
|
|
113
|
+
require 'mutant/reporter/cli/printer/killer'
|
|
114
|
+
require 'mutant/reporter/cli/printer/mutation'
|
data/mutant.gemspec
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |gem|
|
|
4
4
|
gem.name = 'mutant'
|
|
5
|
-
gem.version = '0.
|
|
5
|
+
gem.version = '0.3.0.beta2'
|
|
6
6
|
gem.authors = [ 'Markus Schirp' ]
|
|
7
|
-
gem.email = [ 'mbj@
|
|
7
|
+
gem.email = [ 'mbj@schirp-dso.com' ]
|
|
8
|
+
|
|
8
9
|
gem.description = 'Mutation testing for ruby'
|
|
9
10
|
gem.summary = 'Mutation testing tool for ruby under MRI and Rubinius'
|
|
10
11
|
gem.homepage = 'https://github.com/mbj/mutant'
|
|
@@ -15,14 +16,14 @@ Gem::Specification.new do |gem|
|
|
|
15
16
|
gem.extra_rdoc_files = %w[TODO LICENSE]
|
|
16
17
|
gem.executables = [ 'mutant' ]
|
|
17
18
|
|
|
18
|
-
gem.add_runtime_dependency('
|
|
19
|
-
gem.add_runtime_dependency('
|
|
20
|
-
gem.add_runtime_dependency('ice_nine', '~> 0.
|
|
19
|
+
gem.add_runtime_dependency('parser', '~> 2.0.beta7')
|
|
20
|
+
gem.add_runtime_dependency('unparser', '~> 0.0.4')
|
|
21
|
+
gem.add_runtime_dependency('ice_nine', '~> 0.8.0')
|
|
21
22
|
gem.add_runtime_dependency('descendants_tracker', '~> 0.0.1')
|
|
22
|
-
gem.add_runtime_dependency('adamantium', '~> 0.0.
|
|
23
|
+
gem.add_runtime_dependency('adamantium', '~> 0.0.8')
|
|
23
24
|
gem.add_runtime_dependency('equalizer', '~> 0.0.5')
|
|
24
25
|
gem.add_runtime_dependency('inflecto', '~> 0.0.2')
|
|
25
|
-
gem.add_runtime_dependency('
|
|
26
|
-
gem.add_runtime_dependency('
|
|
26
|
+
gem.add_runtime_dependency('anima', '~> 0.0.6')
|
|
27
|
+
gem.add_runtime_dependency('concord', '~> 0.1.1')
|
|
27
28
|
gem.add_runtime_dependency('rspec', '~> 2.13.0')
|
|
28
29
|
end
|
|
@@ -11,14 +11,14 @@ describe Mutant,'rspec integration' do
|
|
|
11
11
|
let(:strategy) { Mutant::Strategy::Rspec::DM2 }
|
|
12
12
|
|
|
13
13
|
specify 'allows to kill mutations' do
|
|
14
|
-
Kernel.system(
|
|
14
|
+
Kernel.system('bundle exec mutant --rspec-dm2 ::TestApp::Literal#string').should be(true)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
specify 'fails to kill mutations when they are not covered' do
|
|
18
|
-
Kernel.system(
|
|
18
|
+
Kernel.system('bundle exec mutant --rspec-dm2 ::TestApp::Literal#uncovered_string').should be(false)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
specify 'fails when some mutations when are not covered' do
|
|
22
|
-
Kernel.system(
|
|
22
|
+
Kernel.system('bundle exec mutant --rspec-dm2 ::TestApp::Literal').should be(false)
|
|
23
23
|
end
|
|
24
24
|
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
shared_examples_for 'a method matcher' do
|
|
2
|
+
before do
|
|
3
|
+
subject
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
let(:node) { mutation_subject.node }
|
|
7
|
+
let(:context) { mutation_subject.context }
|
|
8
|
+
let(:mutation_subject) { yields.first }
|
|
9
|
+
|
|
10
|
+
it 'should return one subject' do
|
|
11
|
+
yields.size.should be(1)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it_should_behave_like 'an #each method'
|
|
15
|
+
|
|
16
|
+
it 'should have correct method name' do
|
|
17
|
+
name.should eql(method_name)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'should have correct line number' do
|
|
21
|
+
(node.location.expression.line - base).should eql(method_line)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'should have correct arity' do
|
|
25
|
+
arguments.children.length.should eql(method_arity)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'should have correct scope in context' do
|
|
29
|
+
context.send(:scope).should eql(scope)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'should have the correct node type' do
|
|
33
|
+
node.type.should be(type)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -1,11 +1,51 @@
|
|
|
1
|
+
class Subject
|
|
2
|
+
|
|
3
|
+
include Equalizer.new(:source)
|
|
4
|
+
|
|
5
|
+
Undefined = Object.new.freeze
|
|
6
|
+
|
|
7
|
+
attr_reader :source
|
|
8
|
+
|
|
9
|
+
def self.coerce(input)
|
|
10
|
+
case input
|
|
11
|
+
when Parser::AST::Node
|
|
12
|
+
new(input)
|
|
13
|
+
when String
|
|
14
|
+
new(Parser::CurrentRuby.parse(input))
|
|
15
|
+
else
|
|
16
|
+
raise
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_s
|
|
21
|
+
"#{@node.inspect}\n#{@source}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def initialize(node)
|
|
25
|
+
source = Unparser.unparse(node)
|
|
26
|
+
@node, @source = node, source
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def assert_transitive!
|
|
30
|
+
generated = Unparser.generate(@node)
|
|
31
|
+
parsed = Parser::CurrentRuby.parse(generated)
|
|
32
|
+
again = Unparser.generate(parsed)
|
|
33
|
+
unless generated == again
|
|
34
|
+
# mostly an unparser bug!
|
|
35
|
+
fail "Untransitive:\n%s\n---\n%s" % [generated, again]
|
|
36
|
+
end
|
|
37
|
+
self
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
1
41
|
shared_examples_for 'a mutator' do
|
|
2
42
|
subject { object.each(node) { |item| yields << item } }
|
|
3
43
|
|
|
4
|
-
let(:yields)
|
|
5
|
-
let(:object)
|
|
44
|
+
let(:yields) { [] }
|
|
45
|
+
let(:object) { described_class }
|
|
6
46
|
|
|
7
47
|
unless instance_methods.map(&:to_s).include?('node')
|
|
8
|
-
let(:node)
|
|
48
|
+
let(:node) { parse(source) }
|
|
9
49
|
end
|
|
10
50
|
|
|
11
51
|
it_should_behave_like 'a command method'
|
|
@@ -15,44 +55,35 @@ shared_examples_for 'a mutator' do
|
|
|
15
55
|
|
|
16
56
|
it { should be_instance_of(to_enum.class) }
|
|
17
57
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
again = ToSource.to_source(parsed)
|
|
22
|
-
unless generated == again
|
|
23
|
-
fail "Untransitive:\n%s\n---\n%s" % [generated, again]
|
|
58
|
+
let(:expected_mutations) do
|
|
59
|
+
mutations.map do |mutation|
|
|
60
|
+
Subject.coerce(mutation)
|
|
24
61
|
end
|
|
25
62
|
end
|
|
26
63
|
|
|
27
|
-
|
|
28
|
-
let(:expected_mutations) do
|
|
29
|
-
mutations.map do |mutation|
|
|
30
|
-
case mutation
|
|
31
|
-
when String
|
|
32
|
-
ast = mutation.to_ast
|
|
33
|
-
assert_transitive(ast)
|
|
34
|
-
ast
|
|
35
|
-
when Rubinius::AST::Node
|
|
36
|
-
assert_transitive(mutation)
|
|
37
|
-
mutation
|
|
38
|
-
else
|
|
39
|
-
raise
|
|
40
|
-
end
|
|
41
|
-
end.map do |node|
|
|
42
|
-
ToSource.to_source(node)
|
|
43
|
-
end.to_set
|
|
44
|
-
end
|
|
64
|
+
let(:generated_mutations) do
|
|
45
65
|
end
|
|
46
66
|
|
|
47
67
|
it 'generates the expected mutations' do
|
|
48
|
-
generated = self.subject.map { |mutation| ToSource.to_source(mutation) }.to_set
|
|
49
68
|
|
|
50
|
-
|
|
51
|
-
unexpected = (generated - expected_mutations).to_a
|
|
69
|
+
generated = subject.map { |node| Subject.new(node) }
|
|
52
70
|
|
|
53
|
-
|
|
54
|
-
|
|
71
|
+
missing = expected_mutations - generated
|
|
72
|
+
unexpected = generated - expected_mutations
|
|
73
|
+
|
|
74
|
+
message = []
|
|
75
|
+
|
|
76
|
+
if missing.any?
|
|
77
|
+
message << 'Missing mutations (%i):' % missing.length
|
|
78
|
+
message.concat(missing)
|
|
55
79
|
end
|
|
80
|
+
|
|
81
|
+
if unexpected.any?
|
|
82
|
+
message << 'Unexpected mutations (%i):' % unexpected.length
|
|
83
|
+
message.concat(unexpected)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
fail "Original:\n#{generate(node)}\n-----\n#{message.join("\n-----\n")}" if message.any?
|
|
56
87
|
end
|
|
57
88
|
end
|
|
58
89
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,13 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
require 'mutant'
|
|
3
2
|
require 'devtools'
|
|
4
3
|
Devtools.init_spec_helper
|
|
5
4
|
|
|
6
5
|
$: << File.join(TestApp.root,'lib')
|
|
7
6
|
|
|
8
7
|
require 'test_app'
|
|
9
|
-
|
|
8
|
+
|
|
9
|
+
module ParserHelper
|
|
10
|
+
def generate(node)
|
|
11
|
+
Unparser.unparse(node)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def parse(string)
|
|
15
|
+
Parser::CurrentRuby.parse(string)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
10
18
|
|
|
11
19
|
RSpec.configure do |config|
|
|
12
20
|
config.include(CompressHelper)
|
|
21
|
+
config.include(ParserHelper)
|
|
22
|
+
config.include(Mutant::NodeHelpers)
|
|
13
23
|
end
|
data/spec/support/rspec.rb
CHANGED