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,85 +0,0 @@
1
- module Mutant
2
- class Runner
3
- # Subject specific runner
4
- class Subject < self
5
- include Equalizer.new(:config, :subject)
6
-
7
- # Return subject
8
- #
9
- # @return [Subject]
10
- #
11
- # @api private
12
- #
13
- attr_reader :subject
14
-
15
- register Mutant::Subject
16
-
17
- # Initialize object
18
- #
19
- # @param [Config] config
20
- # @param [Subject] subject
21
- #
22
- # @return [undefined]
23
- #
24
- # @api private
25
- #
26
- def initialize(config, subject)
27
- @subject = subject
28
- super(config)
29
- end
30
-
31
- # Return mutation runners
32
- #
33
- # @return [Enumerable<Runner::Mutation>]
34
- #
35
- # @api private
36
- #
37
- attr_reader :mutations
38
-
39
- # Return failed mutations
40
- #
41
- # @return [Enumerable<Mutation>]
42
- #
43
- # @api private
44
- #
45
- def failed_mutations
46
- mutations.reject(&:success?)
47
- end
48
- memoize :failed_mutations
49
-
50
- # Test if subject was processed successful
51
- #
52
- # @return [Boolean]
53
- #
54
- # @api private
55
- #
56
- def success?
57
- failed_mutations.empty?
58
- end
59
-
60
- # Return tests used to kill mutations on this subject
61
- #
62
- # @return [Enumerable<Test>]
63
- #
64
- # @api private
65
- #
66
- def tests
67
- config.tests(subject)
68
- end
69
- memoize :tests
70
-
71
- private
72
-
73
- # Perform operation
74
- #
75
- # @return [undefined]
76
- #
77
- # @api private
78
- #
79
- def run
80
- @mutations = visit_collection(subject.mutations, tests)
81
- end
82
-
83
- end # Subject
84
- end # Runner
85
- end # Mutant
@@ -1,59 +0,0 @@
1
- module Mutant
2
- class Test
3
- # Object to report test status
4
- class Report
5
- include Adamantium::Flat, Anima::Update, Anima.new(
6
- :test,
7
- :output,
8
- :success
9
- )
10
-
11
- # Test if test was successful
12
- #
13
- # @return [Boolean]
14
- #
15
- # @api private
16
- #
17
- alias_method :success?, :success
18
-
19
- # Test if test failed
20
- #
21
- # @return [Boolean]
22
- #
23
- # @api private
24
- #
25
- def failed?
26
- !success?
27
- end
28
-
29
- # Return marshallable data
30
- #
31
- # NOTE:
32
- #
33
- # The test is intentionally NOT part of the mashalled data.
34
- # In rspec the example group cannot deterministically being marshalled, because
35
- # they reference a crazy mix of IO objects, global objects etc.
36
- #
37
- # @return [Array]
38
- #
39
- # @api private
40
- #
41
- def marshal_dump
42
- [@output, @success]
43
- end
44
-
45
- # Load marshalled data
46
- #
47
- # @param [Array] arry
48
- #
49
- # @return [undefined]
50
- #
51
- # @api private
52
- #
53
- def marshal_load(array)
54
- @output, @success = array
55
- end
56
-
57
- end # Report
58
- end # Test
59
- end # Mutant
@@ -1,147 +0,0 @@
1
- require 'spec_helper'
2
-
3
- shared_examples_for 'an invalid cli run' do
4
- it 'should raise error' do
5
- expect do
6
- subject
7
- end.to raise_error(Mutant::CLI::Error, expected_message)
8
- end
9
- end
10
-
11
- shared_examples_for 'a cli parser' do
12
- subject { cli.config }
13
-
14
- it { expect(subject.integration).to eql(expected_integration) }
15
- it { expect(subject.reporter).to eql(expected_reporter) }
16
- it { expect(subject.matcher).to eql(expected_matcher) }
17
- end
18
-
19
- describe Mutant::CLI, '.new' do
20
- let(:object) { described_class }
21
- let(:time) { Time.now }
22
-
23
- before do
24
- Time.stub(now: time)
25
- end
26
-
27
- # Defaults
28
- let(:expected_filter) { Morpher.evaluator(s(:true)) }
29
- let(:expected_integration) { Mutant::Integration::Null.new }
30
- let(:expected_reporter) { Mutant::Reporter::CLI.new($stdout) }
31
-
32
- let(:ns) { Mutant::Matcher }
33
- let(:env) { Fixtures::BOOT_ENV }
34
-
35
- let(:cli) { object.new(arguments) }
36
-
37
- subject { cli }
38
-
39
- context 'with unknown flag' do
40
- let(:arguments) { %w[--invalid] }
41
-
42
- let(:expected_message) { 'invalid option: --invalid' }
43
-
44
- it_should_behave_like 'an invalid cli run'
45
- end
46
-
47
- context 'with unknown option' do
48
- let(:arguments) { %w[--invalid Foo] }
49
-
50
- let(:expected_message) { 'invalid option: --invalid' }
51
-
52
- it_should_behave_like 'an invalid cli run'
53
- end
54
-
55
- context 'without arguments' do
56
- let(:arguments) { [] }
57
-
58
- let(:expected_message) { 'No patterns given' }
59
-
60
- it_should_behave_like 'an invalid cli run'
61
- end
62
-
63
- context 'with code filter and missing argument' do
64
- let(:arguments) { %w[--code] }
65
- let(:expected_message) { 'missing argument: --code' }
66
-
67
- it_should_behave_like 'an invalid cli run'
68
- end
69
-
70
- context 'with explicit method pattern' do
71
- let(:arguments) { %w[TestApp::Literal#float] }
72
-
73
- let(:expected_matcher) do
74
- ns::Method::Instance.new(env, TestApp::Literal, TestApp::Literal.instance_method(:float))
75
- end
76
-
77
- it_should_behave_like 'a cli parser'
78
- end
79
-
80
- context 'with debug flag' do
81
- let(:pattern) { 'TestApp*' }
82
- let(:arguments) { %W[--debug #{pattern}] }
83
- let(:expected_matcher) { ns::Namespace.new(env, Mutant::Expression.parse(pattern)) }
84
-
85
- it_should_behave_like 'a cli parser'
86
-
87
- it 'should set the debug option' do
88
- expect(subject.config.debug).to be(true)
89
- end
90
- end
91
-
92
- context 'with zombie flag' do
93
- let(:pattern) { 'TestApp*' }
94
- let(:arguments) { %W[--zombie #{pattern}] }
95
- let(:expected_matcher) { ns::Namespace.new(env, Mutant::Expression.parse(pattern)) }
96
-
97
- it_should_behave_like 'a cli parser'
98
-
99
- it 'should set the zombie option' do
100
- expect(subject.config.zombie).to be(true)
101
- end
102
- end
103
-
104
- context 'with namespace pattern' do
105
- let(:pattern) { 'TestApp*' }
106
- let(:arguments) { [pattern] }
107
- let(:expected_matcher) { ns::Namespace.new(env, Mutant::Expression.parse(pattern)) }
108
-
109
- it_should_behave_like 'a cli parser'
110
- end
111
-
112
- context 'with subject code filter' do
113
- let(:pattern) { 'TestApp::Literal#float' }
114
- let(:arguments) { %W[--code faa --code bbb #{pattern}] }
115
-
116
- let(:expected_filter) do
117
- Morpher.evaluator(
118
- s(:mxor,
119
- s(:eql, s(:attribute, :code), s(:value, 'faa')),
120
- s(:eql, s(:attribute, :code), s(:value, 'bbb'))
121
- )
122
- )
123
- end
124
-
125
- let(:expected_matcher) do
126
- matcher = ns::Method::Instance.new(
127
- env,
128
- TestApp::Literal, TestApp::Literal.instance_method(:float)
129
- )
130
- predicate = Morpher.compile(
131
- s(:or,
132
- s(:eql,
133
- s(:attribute, :code),
134
- s(:static, 'faa')
135
- ),
136
- s(:eql,
137
- s(:attribute, :code),
138
- s(:static, 'bbb')
139
- )
140
- )
141
- )
142
- ns::Filter.new(matcher, predicate)
143
- end
144
-
145
- it_should_behave_like 'a cli parser'
146
- end
147
- end
@@ -1,46 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Mutant::CLI, '.run' do
4
- subject { object.run(argv) }
5
-
6
- let(:object) { described_class }
7
- let(:argv) { double('ARGV') }
8
- let(:attributes) { double('Options') }
9
- let(:runner) { double('Runner', success?: success) }
10
- let(:config) { double('Config') }
11
- let(:instance) { double(described_class.name, config: config) }
12
-
13
- before do
14
- described_class.stub(new: instance)
15
- Mutant::Runner::Config.stub(run: runner)
16
- end
17
-
18
- context 'when runner is successful' do
19
- let(:success) { true }
20
-
21
- it { should be(0) }
22
-
23
- it 'should run with attributes' do
24
- Mutant::Runner::Config
25
- .should_receive(:run)
26
- .with(config)
27
- .and_return(runner)
28
- should be(0)
29
- end
30
- end
31
-
32
- context 'when runner fails' do
33
- let(:success) { false }
34
-
35
- it { should be(1) }
36
-
37
- it 'should run with attributes' do
38
- Mutant::Runner::Config
39
- .should_receive(:run)
40
- .with(config)
41
- .and_return(runner)
42
- should be(1)
43
- end
44
- end
45
-
46
- end
@@ -1,157 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Mutant::Runner::Config do
4
- let(:object) { described_class.run(config) }
5
-
6
- let(:config) do
7
- Mutant::Config.new(
8
- matcher: [subject_a, subject_b],
9
- debug: false,
10
- integration: integration,
11
- reporter: reporter,
12
- fail_fast: fail_fast,
13
- expected_coverage: expected_coverage,
14
- zombie: false
15
- )
16
- end
17
-
18
- let(:fail_fast) { false }
19
- let(:expected_coverage) { 100.0 }
20
- let(:reporter) { Mutant::Reporter::Trace.new }
21
- let(:integration) { double('Integration') }
22
- let(:subject_a) { double('Subject A') }
23
- let(:subject_b) { double('Subject B') }
24
-
25
- before do
26
- integration.stub(:setup)
27
- integration.stub(:teardown)
28
- Mutant::Runner.stub(:run).with(config, subject_a).and_return(runner_a)
29
- Mutant::Runner.stub(:run).with(config, subject_b).and_return(runner_b)
30
- end
31
-
32
- describe '#subjects' do
33
-
34
- subject { object.subjects }
35
-
36
- let(:runner_a) { double('Runner A', stop?: stop_a) }
37
- let(:runner_b) { double('Runner B', stop?: stop_b) }
38
-
39
- context 'without early stop' do
40
- let(:stop_a) { false }
41
- let(:stop_b) { false }
42
-
43
- it { should eql([runner_a, runner_b]) }
44
-
45
- it_should_behave_like 'an idempotent method'
46
- end
47
-
48
- context 'with early stop' do
49
- let(:stop_a) { true }
50
- let(:stop_b) { false }
51
-
52
- it { should eql([runner_a]) }
53
-
54
- it_should_behave_like 'an idempotent method'
55
- end
56
- end
57
-
58
- describe '#coverage' do
59
- subject { object.coverage }
60
-
61
- let(:runner_a) { double('Runner A', stop?: false, :mutations => mutations_a) }
62
- let(:runner_b) { double('Runner B', stop?: false, :mutations => []) }
63
-
64
- let(:mutations_a) do
65
- Array.new(amount_mutations) do |number|
66
- double('Mutation', success?: number <= amount_kills - 1)
67
- end
68
- end
69
-
70
- context 'with zero mutations and kills' do
71
- let(:amount_mutations) { 0 }
72
- let(:amount_kills) { 0 }
73
-
74
- it { should eql(0.0) }
75
- end
76
-
77
- context 'with one mutation' do
78
- let(:amount_mutations) { 1 }
79
-
80
- context 'and one kill' do
81
- let(:amount_kills) { 1 }
82
- it { should eql(100.0) }
83
- end
84
-
85
- context 'and no kills' do
86
- let(:amount_kills) { 0 }
87
- it { should eql(0.0) }
88
- end
89
- end
90
-
91
- context 'with many mutations' do
92
- let(:amount_mutations) { 10 }
93
-
94
- context 'and no kill' do
95
- let(:amount_kills) { 0 }
96
- it { should eql(0.0) }
97
- end
98
-
99
- context 'and some kills' do
100
- let(:amount_kills) { 2 }
101
- it { should eql(20.0) }
102
- end
103
-
104
- context 'and as many kills' do
105
- let(:amount_kills) { amount_mutations }
106
- it { should eql(100.0) }
107
- end
108
- end
109
- end
110
-
111
- describe '#success?' do
112
- subject { object.success? }
113
-
114
- let(:mutation_a) do
115
- double('Mutation A', success?: false)
116
- end
117
-
118
- let(:mutation_b) do
119
- double('Mutation B', success?: true)
120
- end
121
-
122
- let(:runner_a) do
123
- double('Runner A', stop?: false, success?: false, mutations: [mutation_a])
124
- end
125
-
126
- let(:runner_b) do
127
- double('Runner B', stop?: false, success?: true, mutations: [mutation_b])
128
- end
129
-
130
- let(:runner_a) do
131
- double('Runner A', stop?: false, success?: false, mutations: [mutation_a])
132
- end
133
-
134
- let(:runner_b) do
135
- double('Runner B', stop?: false, success?: true, mutations: [mutation_b])
136
- end
137
-
138
- context 'without fail fast' do
139
-
140
- context 'when expected coverage equals actual coverage' do
141
- let(:expected_coverage) { 50.0 }
142
- it { should be(true) }
143
- end
144
-
145
- context 'when expected coverage closely equals actual coverage' do
146
- let(:expected_coverage) { 50.01 }
147
- it { should be(true) }
148
- end
149
-
150
- context 'when expected coverage does not equal actual coverage' do
151
- let(:expected_coverage) { 51.00 }
152
- it { should be(false) }
153
- end
154
-
155
- end
156
- end
157
- end