mutant 0.5.24 → 0.5.25

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +8 -0
  3. data/config/flay.yml +1 -1
  4. data/config/flog.yml +1 -1
  5. data/config/reek.yml +15 -13
  6. data/lib/mutant.rb +28 -12
  7. data/lib/mutant/ast/meta.rb +0 -10
  8. data/lib/mutant/ast/named_children.rb +1 -0
  9. data/lib/mutant/ast/types.rb +5 -5
  10. data/lib/mutant/cli.rb +84 -64
  11. data/lib/mutant/config.rb +7 -39
  12. data/lib/mutant/delegator.rb +2 -0
  13. data/lib/mutant/env.rb +119 -16
  14. data/lib/mutant/expression.rb +8 -2
  15. data/lib/mutant/expression/method.rb +6 -16
  16. data/lib/mutant/expression/methods.rb +5 -5
  17. data/lib/mutant/expression/namespace.rb +7 -7
  18. data/lib/mutant/integration.rb +0 -10
  19. data/lib/mutant/isolation.rb +41 -15
  20. data/lib/mutant/matcher/chain.rb +1 -17
  21. data/lib/mutant/matcher/compiler.rb +108 -0
  22. data/lib/mutant/matcher/config.rb +28 -0
  23. data/lib/mutant/matcher/method.rb +1 -1
  24. data/lib/mutant/matcher/namespace.rb +5 -52
  25. data/lib/mutant/matcher/null.rb +1 -1
  26. data/lib/mutant/matcher/scope.rb +1 -1
  27. data/lib/mutant/mutation.rb +29 -13
  28. data/lib/mutant/mutator/node.rb +2 -12
  29. data/lib/mutant/mutator/node/named_value/variable_assignment.rb +1 -1
  30. data/lib/mutant/reporter/cli.rb +0 -2
  31. data/lib/mutant/reporter/cli/printer.rb +14 -0
  32. data/lib/mutant/reporter/cli/progress.rb +1 -3
  33. data/lib/mutant/reporter/cli/progress/config.rb +5 -9
  34. data/lib/mutant/reporter/cli/progress/env.rb +30 -0
  35. data/lib/mutant/reporter/cli/progress/noop.rb +4 -1
  36. data/lib/mutant/reporter/cli/progress/result.rb +12 -0
  37. data/lib/mutant/reporter/cli/progress/result/mutation.rb +45 -0
  38. data/lib/mutant/reporter/cli/progress/result/subject.rb +54 -0
  39. data/lib/mutant/reporter/cli/progress/subject.rb +7 -90
  40. data/lib/mutant/reporter/cli/registry.rb +2 -0
  41. data/lib/mutant/reporter/cli/report/env.rb +92 -0
  42. data/lib/mutant/reporter/cli/report/mutation.rb +58 -77
  43. data/lib/mutant/reporter/cli/report/subject.rb +4 -3
  44. data/lib/mutant/reporter/cli/report/test.rb +28 -0
  45. data/lib/mutant/reporter/null.rb +1 -1
  46. data/lib/mutant/reporter/trace.rb +16 -3
  47. data/lib/mutant/result.rb +302 -0
  48. data/lib/mutant/runner.rb +77 -123
  49. data/lib/mutant/subject.rb +32 -16
  50. data/lib/mutant/subject/method.rb +0 -15
  51. data/lib/mutant/subject/method/instance.rb +3 -3
  52. data/lib/mutant/version.rb +1 -1
  53. data/lib/mutant/warning_expectation.rb +12 -5
  54. data/spec/integration/mutant/corpus_spec.rb +1 -1
  55. data/spec/spec_helper.rb +5 -1
  56. data/spec/unit/mutant/cli_spec.rb +248 -0
  57. data/spec/unit/mutant/expression/namespace/flat_spec.rb +1 -1
  58. data/spec/unit/mutant/expression_spec.rb +55 -0
  59. data/spec/unit/mutant/integration_spec.rb +0 -5
  60. data/spec/unit/mutant/isolation_spec.rb +36 -5
  61. data/spec/unit/mutant/matcher/chain_spec.rb +1 -13
  62. data/spec/unit/mutant/matcher/compiler_spec.rb +95 -0
  63. data/spec/unit/mutant/matcher/filter_spec.rb +31 -0
  64. data/spec/unit/mutant/matcher/method/instance_spec.rb +33 -2
  65. data/spec/unit/mutant/matcher/method/singleton_spec.rb +1 -1
  66. data/spec/unit/mutant/matcher/methods/instance_spec.rb +1 -1
  67. data/spec/unit/mutant/matcher/methods/singleton_spec.rb +1 -1
  68. data/spec/unit/mutant/matcher/namespace_spec.rb +10 -6
  69. data/spec/unit/mutant/matcher/null_spec.rb +26 -0
  70. data/spec/unit/mutant/reporter/cli_spec.rb +337 -0
  71. data/spec/unit/mutant/reporter/null_spec.rb +12 -0
  72. data/spec/unit/mutant/runner_spec.rb +130 -0
  73. data/spec/unit/mutant/subject/context_spec.rb +4 -3
  74. data/spec/unit/mutant/subject/method/instance_spec.rb +5 -3
  75. data/spec/unit/mutant/subject/method/singleton_spec.rb +3 -2
  76. data/spec/unit/mutant/subject_spec.rb +36 -1
  77. data/spec/unit/mutant/test_spec.rb +25 -0
  78. data/spec/unit/mutant/warning_expectation.rb +11 -8
  79. data/spec/unit/mutant_spec.rb +11 -2
  80. metadata +27 -28
  81. data/lib/mutant/killer.rb +0 -44
  82. data/lib/mutant/matcher/builder.rb +0 -142
  83. data/lib/mutant/mutation/evil.rb +0 -23
  84. data/lib/mutant/mutation/neutral.rb +0 -18
  85. data/lib/mutant/reporter/cli/progress/mutation.rb +0 -46
  86. data/lib/mutant/reporter/cli/report/config.rb +0 -116
  87. data/lib/mutant/rspec.rb +0 -0
  88. data/lib/mutant/runner/config.rb +0 -138
  89. data/lib/mutant/runner/killer.rb +0 -75
  90. data/lib/mutant/runner/mutation.rb +0 -78
  91. data/lib/mutant/runner/subject.rb +0 -85
  92. data/lib/mutant/test/report.rb +0 -59
  93. data/spec/unit/mutant/cli_new_spec.rb +0 -147
  94. data/spec/unit/mutant/cli_run_spec.rb +0 -46
  95. data/spec/unit/mutant/runner/config_spec.rb +0 -157
  96. data/spec/unit/mutant/runner/mutation_spec.rb +0 -101
  97. data/spec/unit/mutant/runner/subject_spec.rb +0 -59
  98. data/spec/unit/mutant/subject/mutations_spec.rb +0 -23
  99. data/spec/unit/mutant/subject/node_spec.rb +0 -17
@@ -1,23 +0,0 @@
1
- module Mutant
2
- class Mutation
3
- # Evul mutation
4
- class Evil < self
5
-
6
- SHOULD_FAIL = true
7
- SYMBOL = 'evil'.freeze
8
-
9
- # Test if killer is successful
10
- #
11
- # @param [Killer] killer
12
- #
13
- # @return [Boolean]
14
- #
15
- # @api private
16
- #
17
- def success?(killer)
18
- killer.killed?
19
- end
20
-
21
- end # Evil
22
- end # Mutation
23
- end # Mutant
@@ -1,18 +0,0 @@
1
- module Mutant
2
- class Mutation
3
- # Neutral mutation
4
- class Neutral < self
5
-
6
- SYMBOL = 'neutral'.freeze
7
- SHOULD_FAIL = false
8
-
9
- # Noop mutation, special case of neutral
10
- class Noop < self
11
-
12
- SYMBOL = 'noop'.freeze
13
-
14
- end # Noop
15
-
16
- end # Neutral
17
- end # Mutation
18
- end # Mutant
@@ -1,46 +0,0 @@
1
- module Mutant
2
- class Reporter
3
- class CLI
4
- class Progress
5
-
6
- # Mutation progress reporter
7
- class Mutation < self
8
-
9
- handle(Runner::Mutation)
10
-
11
- SUCCESS = '.'.freeze
12
- FAILURE = 'F'.freeze
13
-
14
- # Run printer
15
- #
16
- # @return [self]
17
- #
18
- # @api private
19
- #
20
- def run
21
- unless running?
22
- char(success? ? SUCCESS : FAILURE)
23
- end
24
- self
25
- end
26
-
27
- private
28
-
29
- # Write colorized char
30
- #
31
- # @param [String] char
32
- #
33
- # @return [undefined]
34
- #
35
- # @api private
36
- #
37
- def char(char)
38
- output.write(colorize(status_color, char))
39
- output.flush
40
- end
41
-
42
- end # Mutation
43
- end # Progress
44
- end # CLI
45
- end # Reporter
46
- end # Mutant
@@ -1,116 +0,0 @@
1
- module Mutant
2
- class Reporter
3
- class CLI
4
- class Report
5
-
6
- # Printer for configuration
7
- class Config < self
8
-
9
- handle(Mutant::Runner::Config)
10
-
11
- delegate(
12
- :amount_kills, :amount_mutations, :amount_kils,
13
- :coverage, :subjects, :failed_subjects, :runtime, :mutations
14
- )
15
-
16
- # Run printer
17
- #
18
- # @return [self]
19
- #
20
- # @api private
21
- #
22
- def run
23
- failed_subjects.each(&method(:visit))
24
- info 'Subjects: %s', amount_subjects
25
- info 'Mutations: %s', amount_mutations
26
- info 'Kills: %s', amount_kills
27
- info 'Alive: %s', amount_alive
28
- info 'Runtime: %0.2fs', runtime
29
- info 'Killtime: %0.2fs', killtime
30
- info 'Overhead: %0.2f%%', overhead
31
- status 'Coverage: %0.2f%%', coverage
32
- status 'Expected: %0.2f%%', object.config.expected_coverage
33
- print_generic_stats
34
- self
35
- end
36
-
37
- private
38
-
39
- # Print generic stats
40
- #
41
- # @return [undefined]
42
- #
43
- # @api private
44
- #
45
- def print_generic_stats
46
- stats = generic_stats.to_a.sort_by(&:last)
47
- return if stats.empty?
48
- info('Nodes handled by generic mutator (type:occurrences):')
49
- stats.reverse_each do |type, amount|
50
- info('%-10s: %d', type, amount)
51
- end
52
- end
53
-
54
- # Return stats for nodes handled by generic mutator
55
- #
56
- # @return [Hash<Symbo, Fixnum>]
57
- #
58
- # @api private
59
- #
60
- def generic_stats
61
- subjects.each_with_object(Hash.new(0)) do |runner, stats|
62
- Walker.run(runner.subject.node) do |node|
63
- if Mutator::Registry.lookup(node).equal?(Mutator::Node::Generic)
64
- stats[node.type] += 1
65
- end
66
- end
67
- end
68
- end
69
-
70
- # Return amount of subjects
71
- #
72
- # @return [Fixnum]
73
- #
74
- # @api private
75
- #
76
- def amount_subjects
77
- subjects.length
78
- end
79
-
80
- # Return amount of time in killers
81
- #
82
- # @return [Float]
83
- #
84
- # @api private
85
- #
86
- def killtime
87
- mutations.map(&:runtime).inject(0, :+)
88
- end
89
- memoize :killtime
90
-
91
- # Return mutant overhead
92
- #
93
- # @return [Float]
94
- #
95
- # @api private
96
- #
97
- def overhead
98
- return 0 if runtime.zero?
99
- Rational(runtime - killtime, runtime) * 100
100
- end
101
-
102
- # Return amount of alive mutations
103
- #
104
- # @return [Fixnum]
105
- #
106
- # @api private
107
- #
108
- def amount_alive
109
- object.amount_mutations - amount_kills
110
- end
111
-
112
- end # Config
113
- end # Report
114
- end # CLI
115
- end # Reporter
116
- end # Mutant
File without changes
@@ -1,138 +0,0 @@
1
- module Mutant
2
- class Runner
3
- # Runner for object config
4
- class Config < self
5
-
6
- # The expected coverage precision
7
- COVERAGE_PRECISION = 1
8
-
9
- register Mutant::Config
10
-
11
- # Run runner for object
12
- #
13
- # @param [Config] config
14
- # @param [Object] object
15
- #
16
- # @return [Runner]
17
- #
18
- # @api private
19
- #
20
- def self.run(config)
21
- handler = lookup(config.class)
22
- handler.new(config)
23
- end
24
-
25
- # Return subject runners
26
- #
27
- # @return [Enumerable<Runner::Subject>]
28
- #
29
- # @api private
30
- #
31
- attr_reader :subjects
32
-
33
- # Return failed subjects
34
- #
35
- # @return [Enumerable<Subject>]
36
- #
37
- # @api private
38
- #
39
- def failed_subjects
40
- subjects.reject(&:success?)
41
- end
42
- memoize :failed_subjects
43
-
44
- # Test if run was successful
45
- #
46
- # @return [Boolean]
47
- #
48
- # @api private
49
- #
50
- def success?
51
- coverage.round(COVERAGE_PRECISION).eql?(config.expected_coverage.round(COVERAGE_PRECISION))
52
- end
53
- memoize :success?
54
-
55
- # Return integration
56
- #
57
- # @return [Integration]
58
- #
59
- # @api private
60
- #
61
- def integration
62
- config.integration
63
- end
64
-
65
- # Return coverage
66
- #
67
- # @return [Float]
68
- #
69
- # @api private
70
- #
71
- def coverage
72
- return 0.0 if amount_mutations.zero? && amount_kills.zero?
73
- (amount_kills.to_f / amount_mutations) * 100
74
- end
75
- memoize :coverage
76
-
77
- # Return amount of kills
78
- #
79
- # @return [Fixnum]
80
- #
81
- # @api private
82
- #
83
- def amount_kills
84
- mutations.select(&:success?).length
85
- end
86
- memoize :amount_kills
87
-
88
- # Return mutations
89
- #
90
- # @return [Array<Mutation>]
91
- #
92
- # @api private
93
- #
94
- def mutations
95
- subjects.map(&:mutations).flatten
96
- end
97
- memoize :mutations
98
-
99
- # Return amount of mutations
100
- #
101
- # @return [Fixnum]
102
- #
103
- # @api private
104
- #
105
- def amount_mutations
106
- mutations.length
107
- end
108
-
109
- private
110
-
111
- # Run config
112
- #
113
- # @return [undefined]
114
- #
115
- # @api private
116
- #
117
- def run_subjects
118
- integration = self.integration
119
- integration.setup
120
- @subjects = visit_collection(config.subjects)
121
- integration.teardown
122
- end
123
-
124
- # Run configuration
125
- #
126
- # @return [undefined]
127
- #
128
- # @api private
129
- #
130
- def run
131
- run_subjects
132
- @end = Time.now
133
- reporter.report(self)
134
- end
135
-
136
- end # Config
137
- end # Runner
138
- end # Mutant
@@ -1,75 +0,0 @@
1
- module Mutant
2
- class Runner
3
- # Killer runner
4
- class Killer < self
5
- include Equalizer.new(:config, :killer)
6
-
7
- register Mutant::Killer
8
-
9
- # Return killer
10
- #
11
- # @return [Killer]
12
- #
13
- # @api private
14
- #
15
- attr_reader :killer
16
- protected :killer
17
-
18
- # Return kill report
19
- #
20
- # @return [Killer::Report]
21
- #
22
- # @api private
23
- #
24
- attr_reader :report
25
-
26
- # Test if killer ran successfully
27
- #
28
- # @return [Boolean]
29
- #
30
- # @api private
31
- #
32
- def success?
33
- @report.success?
34
- end
35
-
36
- # Test if this killer ALONE can determine if mutation is dead
37
- #
38
- # @return [Boolean]
39
- #
40
- # @api private
41
- #
42
- def mutation_dead?
43
- test_report = report.test_report
44
- killer.mutation.should_fail? && test_report.failed?
45
- end
46
-
47
- # Initialize object
48
- #
49
- # @param [Config] config
50
- # @param [Mutation] mutation
51
- #
52
- # @return [undefined]
53
- #
54
- # @api private
55
- #
56
- def initialize(config, killer)
57
- @killer = killer
58
- super(config)
59
- end
60
-
61
- private
62
-
63
- # Run killer
64
- #
65
- # @return [undefined]
66
- #
67
- # @api private
68
- #
69
- def run
70
- @report = killer.run
71
- end
72
-
73
- end # Killer
74
- end # Runner
75
- end # Mutant
@@ -1,78 +0,0 @@
1
- module Mutant
2
- class Runner
3
- # Mutation runner
4
- class Mutation < self
5
- include Equalizer.new(:config, :mutation, :tests)
6
-
7
- register Mutant::Mutation
8
-
9
- # Return mutation
10
- #
11
- # @return [Mutation]
12
- #
13
- # @api private
14
- #
15
- attr_reader :mutation
16
-
17
- # Return killers
18
- #
19
- # @return [Enumerable<Runner::Killer>]
20
- #
21
- # @api private
22
- #
23
- attr_reader :killers
24
-
25
- # Initialize object
26
- #
27
- # @param [Config] config
28
- # @param [Mutation] mutation
29
- # @param [Enumerable<Test>] tests
30
- #
31
- # @return [undefined]
32
- #
33
- # @api private
34
- #
35
- def initialize(config, mutation, tests)
36
- @mutation, @tests = mutation, tests
37
- super(config)
38
- @stop = config.fail_fast && !success?
39
- end
40
-
41
- # Test if mutation was handeled successfully
42
- #
43
- # @return [Boolean]
44
- #
45
- # @api private
46
- #
47
- def success?
48
- killers.any?(&:success?)
49
- end
50
-
51
- private
52
-
53
- # Perform operation
54
- #
55
- # @return [undefined]
56
- #
57
- # @api private
58
- #
59
- def run
60
- @killers = []
61
-
62
- killers = @tests.map do |test|
63
- Mutant::Killer.new(
64
- mutation: mutation,
65
- test: test
66
- )
67
- end
68
-
69
- killers.each do |killer|
70
- runner = visit(killer)
71
- @killers << runner
72
- return if runner.mutation_dead?
73
- end
74
- end
75
-
76
- end # Mutation
77
- end # Runner
78
- end # Mutant