mutant 0.8.7 → 0.8.8
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 +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
|