mutant 0.8.7 → 0.8.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Changelog.md +5 -0
- data/README.md +64 -3
- data/config/flay.yml +1 -1
- data/lib/mutant.rb +2 -0
- data/lib/mutant/cli.rb +1 -1
- data/lib/mutant/env/bootstrap.rb +36 -8
- data/lib/mutant/expression/method.rb +3 -5
- data/lib/mutant/expression/methods.rb +2 -4
- data/lib/mutant/expression/namespace.rb +4 -8
- data/lib/mutant/matcher.rb +3 -18
- data/lib/mutant/matcher/chain.rb +7 -13
- data/lib/mutant/matcher/compiler.rb +2 -13
- data/lib/mutant/matcher/filter.rb +6 -19
- data/lib/mutant/matcher/method.rb +124 -104
- data/lib/mutant/matcher/method/instance.rb +40 -34
- data/lib/mutant/matcher/method/singleton.rb +80 -61
- data/lib/mutant/matcher/methods.rb +19 -29
- data/lib/mutant/matcher/namespace.rb +22 -16
- data/lib/mutant/matcher/null.rb +4 -7
- data/lib/mutant/matcher/scope.rb +23 -13
- data/lib/mutant/matcher/static.rb +17 -0
- data/lib/mutant/mutation.rb +0 -5
- data/lib/mutant/reporter/cli/format.rb +2 -3
- data/lib/mutant/reporter/cli/printer/env_progress.rb +37 -11
- data/lib/mutant/reporter/cli/printer/status_progressive.rb +1 -1
- data/lib/mutant/scope.rb +6 -0
- data/lib/mutant/subject/method.rb +0 -7
- data/lib/mutant/subject/method/instance.rb +0 -10
- data/lib/mutant/subject/method/singleton.rb +0 -10
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/zombifier.rb +2 -1
- data/mutant-rspec.gemspec +1 -1
- data/spec/integration/mutant/rspec_spec.rb +1 -1
- data/spec/shared/method_matcher_behavior.rb +21 -14
- data/spec/spec_helper.rb +6 -0
- data/spec/unit/mutant/env/boostrap_spec.rb +88 -26
- data/spec/unit/mutant/env_spec.rb +0 -1
- data/spec/unit/mutant/expression/method_spec.rb +3 -3
- data/spec/unit/mutant/expression/methods_spec.rb +3 -4
- data/spec/unit/mutant/expression/namespace/flat_spec.rb +2 -3
- data/spec/unit/mutant/expression/namespace/recursive_spec.rb +2 -4
- data/spec/unit/mutant/matcher/chain_spec.rb +21 -29
- data/spec/unit/mutant/matcher/compiler/subject_prefix_spec.rb +16 -13
- data/spec/unit/mutant/matcher/compiler_spec.rb +49 -60
- data/spec/unit/mutant/matcher/filter_spec.rb +15 -31
- data/spec/unit/mutant/matcher/method/instance_spec.rb +84 -128
- data/spec/unit/mutant/matcher/method/singleton_spec.rb +48 -52
- data/spec/unit/mutant/matcher/methods/instance_spec.rb +21 -24
- data/spec/unit/mutant/matcher/methods/singleton_spec.rb +18 -21
- data/spec/unit/mutant/matcher/namespace_spec.rb +30 -38
- data/spec/unit/mutant/matcher/null_spec.rb +5 -20
- data/spec/unit/mutant/matcher/scope_spec.rb +33 -0
- data/spec/unit/mutant/matcher/static_spec.rb +11 -0
- data/spec/unit/mutant/mutation_spec.rb +30 -10
- data/spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb +6 -0
- data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +2 -0
- data/spec/unit/mutant/reporter/cli/printer/status_spec.rb +10 -0
- data/spec/unit/mutant/reporter/cli_spec.rb +4 -0
- data/spec/unit/mutant/subject/method/instance_spec.rb +0 -28
- data/spec/unit/mutant/subject/method/singleton_spec.rb +0 -28
- data/test_app/Gemfile.rspec3.4 +7 -0
- data/test_app/lib/test_app.rb +16 -12
- data/test_app/lib/test_app/literal.rb +3 -0
- metadata +9 -2
@@ -55,7 +55,6 @@ RSpec.describe Mutant::Env do
|
|
55
55
|
|
56
56
|
before do
|
57
57
|
expect(isolation).to receive(:call).and_yield.and_return(test_result)
|
58
|
-
expect(mutation_subject).to receive(:public?).and_return(true).ordered
|
59
58
|
expect(mutation_subject).to receive(:prepare).and_return(mutation_subject).ordered
|
60
59
|
expect(context).to receive(:root).with(s(:nil)).and_return(wrapped_node).ordered
|
61
60
|
expect(Mutant::Loader::Eval).to receive(:call).with(wrapped_node, mutation_subject).and_return(nil).ordered
|
@@ -23,13 +23,13 @@ RSpec.describe Mutant::Expression::Method do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
describe '#matcher' do
|
26
|
-
subject { object.matcher
|
26
|
+
subject { object.matcher }
|
27
27
|
|
28
28
|
context 'with an instance method' do
|
29
29
|
let(:input) { instance_method }
|
30
30
|
|
31
31
|
it 'returns correct matcher' do
|
32
|
-
expect(subject.map(&:expression)).to eql([object])
|
32
|
+
expect(subject.call(env).map(&:expression)).to eql([object])
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
@@ -37,7 +37,7 @@ RSpec.describe Mutant::Expression::Method do
|
|
37
37
|
let(:input) { singleton_method }
|
38
38
|
|
39
39
|
it 'returns correct matcher' do
|
40
|
-
expect(subject.map(&:expression)).to eql([object])
|
40
|
+
expect(subject.call(env).map(&:expression)).to eql([object])
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
RSpec.describe Mutant::Expression::Methods do
|
2
|
-
let(:env) { Fixtures::TEST_ENV }
|
3
2
|
let(:object) { described_class.new(attributes) }
|
4
3
|
|
5
4
|
describe '#match_length' do
|
@@ -43,18 +42,18 @@ RSpec.describe Mutant::Expression::Methods do
|
|
43
42
|
end
|
44
43
|
|
45
44
|
describe '#matcher' do
|
46
|
-
subject { object.matcher
|
45
|
+
subject { object.matcher }
|
47
46
|
|
48
47
|
context 'with an instance method' do
|
49
48
|
let(:attributes) { { scope_name: 'TestApp::Literal', scope_symbol: '#' } }
|
50
49
|
|
51
|
-
it { should eql(Mutant::Matcher::Methods::Instance.new(
|
50
|
+
it { should eql(Mutant::Matcher::Methods::Instance.new(TestApp::Literal)) }
|
52
51
|
end
|
53
52
|
|
54
53
|
context 'with a singleton method' do
|
55
54
|
let(:attributes) { { scope_name: 'TestApp::Literal', scope_symbol: '.' } }
|
56
55
|
|
57
|
-
it { should eql(Mutant::Matcher::Methods::Singleton.new(
|
56
|
+
it { should eql(Mutant::Matcher::Methods::Singleton.new(TestApp::Literal)) }
|
58
57
|
end
|
59
58
|
end
|
60
59
|
end
|
@@ -1,12 +1,11 @@
|
|
1
1
|
RSpec.describe Mutant::Expression::Namespace::Exact do
|
2
2
|
let(:object) { parse_expression(input) }
|
3
|
-
let(:env) { Fixtures::TEST_ENV }
|
4
3
|
let(:input) { 'TestApp::Literal' }
|
5
4
|
|
6
5
|
describe '#matcher' do
|
7
|
-
subject { object.matcher
|
6
|
+
subject { object.matcher }
|
8
7
|
|
9
|
-
it { should eql(Mutant::Matcher::Scope.new(
|
8
|
+
it { should eql(Mutant::Matcher::Scope.new(TestApp::Literal)) }
|
10
9
|
end
|
11
10
|
|
12
11
|
describe '#match_length' do
|
@@ -1,13 +1,11 @@
|
|
1
1
|
RSpec.describe Mutant::Expression::Namespace::Recursive do
|
2
|
-
|
3
2
|
let(:object) { parse_expression(input) }
|
4
3
|
let(:input) { 'TestApp::Literal*' }
|
5
|
-
let(:env) { Fixtures::TEST_ENV }
|
6
4
|
|
7
5
|
describe '#matcher' do
|
8
|
-
subject { object.matcher
|
6
|
+
subject { object.matcher }
|
9
7
|
|
10
|
-
it { should eql(Mutant::Matcher::Namespace.new(
|
8
|
+
it { should eql(Mutant::Matcher::Namespace.new(object)) }
|
11
9
|
end
|
12
10
|
|
13
11
|
describe '#syntax' do
|
@@ -1,32 +1,24 @@
|
|
1
|
-
RSpec.describe Mutant::Matcher::Chain do
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
it { should be_instance_of(to_enum.class) }
|
22
|
-
|
23
|
-
it 'yields the expected values' do
|
24
|
-
expect(subject.to_a).to eql(object.to_a)
|
25
|
-
end
|
26
|
-
end
|
1
|
+
RSpec.describe Mutant::Matcher::Chain, '#call' do
|
2
|
+
subject { object.call(env) }
|
3
|
+
|
4
|
+
let(:object) { described_class.new([matcher_a, matcher_b]) }
|
5
|
+
let(:env) { instance_double(Mutant::Env) }
|
6
|
+
let(:matcher_a) { instance_double(Mutant::Matcher) }
|
7
|
+
let(:matcher_b) { instance_double(Mutant::Matcher) }
|
8
|
+
let(:subject_a) { instance_double(Mutant::Subject) }
|
9
|
+
let(:subject_b) { instance_double(Mutant::Subject) }
|
10
|
+
|
11
|
+
before do
|
12
|
+
expect(matcher_a).to receive(:call)
|
13
|
+
.with(env)
|
14
|
+
.and_return([subject_a])
|
15
|
+
|
16
|
+
expect(matcher_b).to receive(:call)
|
17
|
+
.with(env)
|
18
|
+
.and_return([subject_b])
|
19
|
+
end
|
27
20
|
|
28
|
-
|
29
|
-
|
30
|
-
end
|
21
|
+
it 'returns concatenated matches' do
|
22
|
+
should eql([subject_a, subject_b])
|
31
23
|
end
|
32
24
|
end
|
@@ -1,21 +1,24 @@
|
|
1
|
-
RSpec.describe Mutant::Matcher::Compiler::SubjectPrefix do
|
2
|
-
let(:object)
|
1
|
+
RSpec.describe Mutant::Matcher::Compiler::SubjectPrefix, '#call' do
|
2
|
+
let(:object) { described_class.new(parse_expression('Foo*')) }
|
3
3
|
|
4
|
-
let(:_subject)
|
4
|
+
let(:_subject) do
|
5
|
+
instance_double(
|
6
|
+
Mutant::Subject,
|
7
|
+
expression: parse_expression(subject_expression)
|
8
|
+
)
|
9
|
+
end
|
5
10
|
|
6
|
-
|
7
|
-
subject { object.call(_subject) }
|
11
|
+
subject { object.call(_subject) }
|
8
12
|
|
9
|
-
|
10
|
-
|
13
|
+
context 'when subject expression is prefixed by expression' do
|
14
|
+
let(:subject_expression) { 'Foo::Bar' }
|
11
15
|
|
12
|
-
|
13
|
-
|
16
|
+
it { should be(true) }
|
17
|
+
end
|
14
18
|
|
15
|
-
|
16
|
-
|
19
|
+
context 'when subject expression is NOT prefixed by expression' do
|
20
|
+
let(:subject_expression) { 'Bar' }
|
17
21
|
|
18
|
-
|
19
|
-
end
|
22
|
+
it { should be(false) }
|
20
23
|
end
|
21
24
|
end
|
@@ -1,89 +1,78 @@
|
|
1
|
-
RSpec.describe Mutant::Matcher::Compiler do
|
2
|
-
let(:object)
|
3
|
-
|
4
|
-
let(:
|
5
|
-
|
6
|
-
let(:
|
7
|
-
let(:
|
8
|
-
|
9
|
-
let(:matcher_a) { expression_a.matcher(env) }
|
10
|
-
let(:matcher_b) { expression_b.matcher(env) }
|
1
|
+
RSpec.describe Mutant::Matcher::Compiler, '#call' do
|
2
|
+
let(:object) { described_class }
|
3
|
+
let(:env) { Fixtures::TEST_ENV }
|
4
|
+
let(:matcher_config) { Mutant::Matcher::Config::DEFAULT }
|
5
|
+
let(:expression_a) { parse_expression('Foo*') }
|
6
|
+
let(:expression_b) { parse_expression('Bar*') }
|
7
|
+
let(:matcher_a) { expression_a.matcher }
|
8
|
+
let(:matcher_b) { expression_b.matcher }
|
11
9
|
|
12
10
|
let(:expected_matcher) do
|
13
|
-
Mutant::Matcher::Filter.new(
|
11
|
+
Mutant::Matcher::Filter.new(
|
12
|
+
expected_positive_matcher,
|
13
|
+
expected_predicate
|
14
|
+
)
|
14
15
|
end
|
15
16
|
|
16
17
|
let(:expected_predicate) do
|
17
18
|
Morpher.compile(s(:and, s(:negate, s(:or)), s(:and)))
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
-
subject { object.call(env, matcher_config.with(attributes)) }
|
21
|
+
subject { object.call(matcher_config.with(attributes)) }
|
22
22
|
|
23
|
-
|
23
|
+
context 'on empty config' do
|
24
|
+
let(:attributes) { {} }
|
24
25
|
|
25
|
-
|
26
|
-
let(:attributes) { {} }
|
26
|
+
let(:expected_positive_matcher) { Mutant::Matcher::Chain.new([]) }
|
27
27
|
|
28
|
-
|
28
|
+
it { should eql(expected_matcher) }
|
29
|
+
end
|
29
30
|
|
30
|
-
|
31
|
+
context 'on config with match expression' do
|
32
|
+
let(:expected_predicate) do
|
33
|
+
Morpher::Evaluator::Predicate::Boolean::And.new(
|
34
|
+
[
|
35
|
+
Morpher::Evaluator::Predicate::Negation.new(
|
36
|
+
Morpher::Evaluator::Predicate::Boolean::Or.new(ignore_expression_predicates)
|
37
|
+
),
|
38
|
+
Morpher::Evaluator::Predicate::Boolean::And.new(subject_filter_predicates)
|
39
|
+
]
|
40
|
+
)
|
31
41
|
end
|
32
42
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
Morpher::Evaluator::Predicate::Negation.new(
|
38
|
-
Morpher::Evaluator::Predicate::Boolean::Or.new(ignore_expression_predicates)
|
39
|
-
),
|
40
|
-
Morpher::Evaluator::Predicate::Boolean::And.new(subject_filter_predicates)
|
41
|
-
]
|
42
|
-
)
|
43
|
-
end
|
43
|
+
let(:expected_positive_matcher) { Mutant::Matcher::Chain.new([matcher_a]) }
|
44
|
+
let(:attributes) { { match_expressions: [expression_a] } }
|
45
|
+
let(:ignore_expression_predicates) { [] }
|
46
|
+
let(:subject_filter_predicates) { [] }
|
44
47
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
let(:subject_filter_predicates) { [] }
|
48
|
+
context 'and no other constraints' do
|
49
|
+
it { should eql(expected_matcher) }
|
50
|
+
end
|
49
51
|
|
50
|
-
|
51
|
-
|
52
|
+
context 'and ignore expressions' do
|
53
|
+
let(:attributes) do
|
54
|
+
super().merge(ignore_expressions: [expression_b])
|
52
55
|
end
|
53
56
|
|
54
|
-
|
55
|
-
|
56
|
-
super().merge(ignore_expressions: [expression_b])
|
57
|
-
end
|
58
|
-
|
59
|
-
let(:ignore_expression_predicates) do
|
60
|
-
[Mutant::Matcher::Compiler::SubjectPrefix.new(expression_b)]
|
61
|
-
end
|
62
|
-
|
63
|
-
it { should eql(expected_matcher) }
|
57
|
+
let(:ignore_expression_predicates) do
|
58
|
+
[Mutant::Matcher::Compiler::SubjectPrefix.new(expression_b)]
|
64
59
|
end
|
65
60
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
let(:attributes) do
|
70
|
-
super().merge(subject_filters: [filter])
|
71
|
-
end
|
61
|
+
it { should eql(expected_matcher) }
|
62
|
+
end
|
72
63
|
|
73
|
-
|
74
|
-
|
75
|
-
end
|
64
|
+
context 'and subject filters' do
|
65
|
+
let(:filter) { double('filter') }
|
76
66
|
|
77
|
-
|
67
|
+
let(:attributes) do
|
68
|
+
super().merge(subject_filters: [filter])
|
78
69
|
end
|
79
|
-
end
|
80
70
|
|
81
|
-
|
82
|
-
|
83
|
-
{ match_expressions: [expression_a, expression_b] }
|
71
|
+
let(:subject_filter_predicates) do
|
72
|
+
[filter]
|
84
73
|
end
|
85
74
|
|
86
|
-
|
75
|
+
it { should eql(expected_matcher) }
|
87
76
|
end
|
88
77
|
end
|
89
78
|
end
|
@@ -1,36 +1,20 @@
|
|
1
|
-
RSpec.describe Mutant::Matcher::Filter do
|
2
|
-
|
3
|
-
let(:matcher) { [subject_a, subject_b] }
|
4
|
-
let(:subject_a) { double('Subject A') }
|
5
|
-
let(:subject_b) { double('Subject B') }
|
6
|
-
|
7
|
-
describe '#each' do
|
8
|
-
let(:yields) { [] }
|
9
|
-
subject { object.each { |entry| yields << entry } }
|
10
|
-
|
11
|
-
let(:predicate) { ->(node) { node.eql?(subject_a) } }
|
12
|
-
|
13
|
-
# it_should_behave_like 'an #each method'
|
14
|
-
context 'with no block' do
|
15
|
-
subject { object.each }
|
16
|
-
|
17
|
-
it { should be_instance_of(to_enum.class) }
|
1
|
+
RSpec.describe Mutant::Matcher::Filter, '#call' do
|
2
|
+
subject { object.call(env) }
|
18
3
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
4
|
+
let(:object) { described_class.new(matcher, predicate) }
|
5
|
+
let(:matcher) { instance_double(Mutant::Matcher) }
|
6
|
+
let(:subject_a) { instance_double(Mutant::Subject) }
|
7
|
+
let(:subject_b) { instance_double(Mutant::Subject) }
|
8
|
+
let(:env) { instance_double(Mutant::Env) }
|
9
|
+
let(:predicate) { ->(node) { node.eql?(subject_a) } }
|
10
|
+
|
11
|
+
before do
|
12
|
+
expect(matcher).to receive(:call)
|
13
|
+
.with(env)
|
14
|
+
.and_return([subject_a, subject_b])
|
27
15
|
end
|
28
16
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
let(:predicate) { ->(_subject) { false } }
|
33
|
-
|
34
|
-
its(:to_a) { should eql([]) }
|
17
|
+
it 'returns subjects after filtering' do
|
18
|
+
should eql([subject_a])
|
35
19
|
end
|
36
20
|
end
|
@@ -1,157 +1,113 @@
|
|
1
|
-
RSpec.describe Mutant::Matcher::Method::Instance do
|
2
|
-
|
3
|
-
|
4
|
-
let(:
|
1
|
+
RSpec.describe Mutant::Matcher::Method::Instance, '#call' do
|
2
|
+
subject { object.call(env) }
|
3
|
+
|
4
|
+
let(:object) { described_class.new(scope, method) }
|
5
|
+
let(:env) { test_env }
|
6
|
+
let(:method_name) { :foo }
|
7
|
+
let(:source_path) { MutantSpec::ROOT.join('test_app/lib/test_app.rb') }
|
8
|
+
let(:method) { scope.instance_method(method_name) }
|
9
|
+
let(:namespace) { self.class }
|
10
|
+
let(:type) { :def }
|
11
|
+
let(:method_arity) { 0 }
|
12
|
+
let(:base) { TestApp::InstanceMethodTests }
|
13
|
+
|
14
|
+
def name
|
15
|
+
node.children.fetch(0)
|
16
|
+
end
|
5
17
|
|
6
|
-
|
7
|
-
|
18
|
+
def arguments
|
19
|
+
node.children.fetch(1)
|
20
|
+
end
|
8
21
|
|
9
|
-
|
10
|
-
let(:
|
11
|
-
let(:
|
12
|
-
let(:
|
13
|
-
let(:type) { :def }
|
14
|
-
let(:method_name) { :foo }
|
15
|
-
let(:method_arity) { 0 }
|
16
|
-
let(:base) { TestApp::InstanceMethodTests }
|
22
|
+
context 'when method is defined inside eval' do
|
23
|
+
let(:scope) { base::WithMemoizer }
|
24
|
+
let(:method) { scope.instance_method(:boz) }
|
25
|
+
let(:method_name) { :boz }
|
17
26
|
|
18
|
-
|
19
|
-
|
27
|
+
let(:expected_warnings) do
|
28
|
+
[
|
29
|
+
"#{method} does not have a valid source location, unable to emit subject"
|
30
|
+
]
|
20
31
|
end
|
21
32
|
|
22
|
-
|
23
|
-
|
24
|
-
end
|
33
|
+
include_examples 'skipped candidate'
|
34
|
+
end
|
25
35
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
it 'does warn' do
|
36
|
-
subject
|
37
|
-
expect(reporter.warn_calls.last).to(
|
38
|
-
eql("#{method.inspect} does not have valid source location unable to emit subject")
|
39
|
-
)
|
40
|
-
end
|
36
|
+
context 'when method is defined without source location' do
|
37
|
+
let(:scope) { Module }
|
38
|
+
let(:method) { scope.instance_method(:object_id) }
|
39
|
+
|
40
|
+
let(:expected_warnings) do
|
41
|
+
[
|
42
|
+
"#{method} does not have a valid source location, unable to emit subject"
|
43
|
+
]
|
41
44
|
end
|
42
45
|
|
43
|
-
|
44
|
-
|
45
|
-
let(:source_path) { MutantSpec::ROOT.join('test_app/lib/test_app.rb') }
|
46
|
-
let(:method_line) { 10 }
|
46
|
+
include_examples 'skipped candidate'
|
47
|
+
end
|
47
48
|
|
48
|
-
|
49
|
+
context 'in module eval' do
|
50
|
+
let(:scope) { base::InModuleEval }
|
51
|
+
|
52
|
+
let(:expected_warnings) do
|
53
|
+
[
|
54
|
+
"#{method} is dynamically defined in a closure, unable to emit subject"
|
55
|
+
]
|
49
56
|
end
|
50
57
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
58
|
+
include_examples 'skipped candidate'
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'in class eval' do
|
62
|
+
let(:scope) { base::InClassEval }
|
55
63
|
|
56
|
-
|
64
|
+
let(:expected_warnings) do
|
65
|
+
[
|
66
|
+
"#{method} is dynamically defined in a closure, unable to emit subject"
|
67
|
+
]
|
57
68
|
end
|
58
69
|
|
59
|
-
|
60
|
-
context 'on different lines' do
|
61
|
-
let(:scope) { base::DefinedMultipleTimes::DifferentLines }
|
62
|
-
let(:source_path) { MutantSpec::ROOT.join('test_app/lib/test_app.rb') }
|
63
|
-
let(:method_line) { 24 }
|
64
|
-
let(:method_arity) { 1 }
|
65
|
-
|
66
|
-
it_should_behave_like 'a method matcher'
|
67
|
-
end
|
68
|
-
|
69
|
-
context 'on the same line' do
|
70
|
-
let(:scope) { base::DefinedMultipleTimes::SameLineSameScope }
|
71
|
-
let(:source_path) { MutantSpec::ROOT.join('test_app/lib/test_app.rb') }
|
72
|
-
let(:method_line) { 29 }
|
73
|
-
let(:method_arity) { 1 }
|
74
|
-
|
75
|
-
it_should_behave_like 'a method matcher'
|
76
|
-
end
|
77
|
-
|
78
|
-
context 'on the same line with different scope' do
|
79
|
-
let(:scope) { base::DefinedMultipleTimes::SameLineDifferentScope }
|
80
|
-
let(:source_path) { MutantSpec::ROOT.join('test_app/lib/test_app.rb') }
|
81
|
-
let(:method_line) { 33 }
|
82
|
-
let(:method_arity) { 1 }
|
83
|
-
|
84
|
-
it_should_behave_like 'a method matcher'
|
85
|
-
end
|
86
|
-
|
87
|
-
context 'in module eval' do
|
88
|
-
let(:scope) { base::InModuleEval }
|
89
|
-
|
90
|
-
it 'does not emit matcher' do
|
91
|
-
subject
|
92
|
-
expect(yields.length).to be(0)
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'does warn' do
|
96
|
-
subject
|
97
|
-
expect(reporter.warn_calls.last).to(
|
98
|
-
eql("#{method.inspect} is defined from a 3rd party lib unable to emit subject")
|
99
|
-
)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
context 'in class eval' do
|
104
|
-
let(:scope) { base::InClassEval }
|
105
|
-
|
106
|
-
it 'does not emit matcher' do
|
107
|
-
subject
|
108
|
-
expect(yields.length).to be(0)
|
109
|
-
end
|
110
|
-
|
111
|
-
it 'does warn' do
|
112
|
-
subject
|
113
|
-
expect(reporter.warn_calls.last).to(
|
114
|
-
eql("#{method.inspect} is defined from a 3rd party lib unable to emit subject")
|
115
|
-
)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
70
|
+
include_examples 'skipped candidate'
|
119
71
|
end
|
120
72
|
|
121
|
-
|
122
|
-
let(:
|
73
|
+
context 'when method is defined once' do
|
74
|
+
let(:method_name) { :bar }
|
75
|
+
let(:scope) { base::WithMemoizer }
|
76
|
+
let(:method_line) { 13 }
|
123
77
|
|
124
|
-
|
78
|
+
it_should_behave_like 'a method matcher'
|
79
|
+
end
|
125
80
|
|
126
|
-
|
127
|
-
|
128
|
-
|
81
|
+
context 'when method is defined once with a memoizer' do
|
82
|
+
let(:scope) { base::WithMemoizer }
|
83
|
+
let(:method_line) { 15 }
|
129
84
|
|
130
|
-
|
131
|
-
|
132
|
-
memoize :foo
|
85
|
+
it_should_behave_like 'a method matcher'
|
86
|
+
end
|
133
87
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
88
|
+
context 'when method is defined multiple times' do
|
89
|
+
context 'on different lines' do
|
90
|
+
let(:scope) { base::DefinedMultipleTimes::DifferentLines }
|
91
|
+
let(:method_line) { 24 }
|
92
|
+
let(:method_arity) { 1 }
|
138
93
|
|
139
|
-
|
140
|
-
scope.instance_method(method_name)
|
94
|
+
it_should_behave_like 'a method matcher'
|
141
95
|
end
|
142
96
|
|
143
|
-
context '
|
144
|
-
|
145
|
-
|
97
|
+
context 'on the same line' do
|
98
|
+
let(:scope) { base::DefinedMultipleTimes::SameLineSameScope }
|
99
|
+
let(:method_line) { 29 }
|
100
|
+
let(:method_arity) { 1 }
|
146
101
|
|
147
|
-
|
148
|
-
|
102
|
+
it_should_behave_like 'a method matcher'
|
103
|
+
end
|
149
104
|
|
150
|
-
|
151
|
-
|
105
|
+
context 'on the same line with different scope' do
|
106
|
+
let(:scope) { base::DefinedMultipleTimes::SameLineDifferentScope }
|
107
|
+
let(:method_line) { 33 }
|
108
|
+
let(:method_arity) { 1 }
|
152
109
|
|
153
|
-
|
154
|
-
end
|
110
|
+
it_should_behave_like 'a method matcher'
|
155
111
|
end
|
156
112
|
end
|
157
113
|
end
|