mutant 0.5.24 → 0.5.25
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Changelog.md +8 -0
- data/config/flay.yml +1 -1
- data/config/flog.yml +1 -1
- data/config/reek.yml +15 -13
- data/lib/mutant.rb +28 -12
- data/lib/mutant/ast/meta.rb +0 -10
- data/lib/mutant/ast/named_children.rb +1 -0
- data/lib/mutant/ast/types.rb +5 -5
- data/lib/mutant/cli.rb +84 -64
- data/lib/mutant/config.rb +7 -39
- data/lib/mutant/delegator.rb +2 -0
- data/lib/mutant/env.rb +119 -16
- data/lib/mutant/expression.rb +8 -2
- data/lib/mutant/expression/method.rb +6 -16
- data/lib/mutant/expression/methods.rb +5 -5
- data/lib/mutant/expression/namespace.rb +7 -7
- data/lib/mutant/integration.rb +0 -10
- data/lib/mutant/isolation.rb +41 -15
- data/lib/mutant/matcher/chain.rb +1 -17
- data/lib/mutant/matcher/compiler.rb +108 -0
- data/lib/mutant/matcher/config.rb +28 -0
- data/lib/mutant/matcher/method.rb +1 -1
- data/lib/mutant/matcher/namespace.rb +5 -52
- data/lib/mutant/matcher/null.rb +1 -1
- data/lib/mutant/matcher/scope.rb +1 -1
- data/lib/mutant/mutation.rb +29 -13
- data/lib/mutant/mutator/node.rb +2 -12
- data/lib/mutant/mutator/node/named_value/variable_assignment.rb +1 -1
- data/lib/mutant/reporter/cli.rb +0 -2
- data/lib/mutant/reporter/cli/printer.rb +14 -0
- data/lib/mutant/reporter/cli/progress.rb +1 -3
- data/lib/mutant/reporter/cli/progress/config.rb +5 -9
- data/lib/mutant/reporter/cli/progress/env.rb +30 -0
- data/lib/mutant/reporter/cli/progress/noop.rb +4 -1
- data/lib/mutant/reporter/cli/progress/result.rb +12 -0
- data/lib/mutant/reporter/cli/progress/result/mutation.rb +45 -0
- data/lib/mutant/reporter/cli/progress/result/subject.rb +54 -0
- data/lib/mutant/reporter/cli/progress/subject.rb +7 -90
- data/lib/mutant/reporter/cli/registry.rb +2 -0
- data/lib/mutant/reporter/cli/report/env.rb +92 -0
- data/lib/mutant/reporter/cli/report/mutation.rb +58 -77
- data/lib/mutant/reporter/cli/report/subject.rb +4 -3
- data/lib/mutant/reporter/cli/report/test.rb +28 -0
- data/lib/mutant/reporter/null.rb +1 -1
- data/lib/mutant/reporter/trace.rb +16 -3
- data/lib/mutant/result.rb +302 -0
- data/lib/mutant/runner.rb +77 -123
- data/lib/mutant/subject.rb +32 -16
- data/lib/mutant/subject/method.rb +0 -15
- data/lib/mutant/subject/method/instance.rb +3 -3
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/warning_expectation.rb +12 -5
- data/spec/integration/mutant/corpus_spec.rb +1 -1
- data/spec/spec_helper.rb +5 -1
- data/spec/unit/mutant/cli_spec.rb +248 -0
- data/spec/unit/mutant/expression/namespace/flat_spec.rb +1 -1
- data/spec/unit/mutant/expression_spec.rb +55 -0
- data/spec/unit/mutant/integration_spec.rb +0 -5
- data/spec/unit/mutant/isolation_spec.rb +36 -5
- data/spec/unit/mutant/matcher/chain_spec.rb +1 -13
- data/spec/unit/mutant/matcher/compiler_spec.rb +95 -0
- data/spec/unit/mutant/matcher/filter_spec.rb +31 -0
- data/spec/unit/mutant/matcher/method/instance_spec.rb +33 -2
- data/spec/unit/mutant/matcher/method/singleton_spec.rb +1 -1
- data/spec/unit/mutant/matcher/methods/instance_spec.rb +1 -1
- data/spec/unit/mutant/matcher/methods/singleton_spec.rb +1 -1
- data/spec/unit/mutant/matcher/namespace_spec.rb +10 -6
- data/spec/unit/mutant/matcher/null_spec.rb +26 -0
- data/spec/unit/mutant/reporter/cli_spec.rb +337 -0
- data/spec/unit/mutant/reporter/null_spec.rb +12 -0
- data/spec/unit/mutant/runner_spec.rb +130 -0
- data/spec/unit/mutant/subject/context_spec.rb +4 -3
- data/spec/unit/mutant/subject/method/instance_spec.rb +5 -3
- data/spec/unit/mutant/subject/method/singleton_spec.rb +3 -2
- data/spec/unit/mutant/subject_spec.rb +36 -1
- data/spec/unit/mutant/test_spec.rb +25 -0
- data/spec/unit/mutant/warning_expectation.rb +11 -8
- data/spec/unit/mutant_spec.rb +11 -2
- metadata +27 -28
- data/lib/mutant/killer.rb +0 -44
- data/lib/mutant/matcher/builder.rb +0 -142
- data/lib/mutant/mutation/evil.rb +0 -23
- data/lib/mutant/mutation/neutral.rb +0 -18
- data/lib/mutant/reporter/cli/progress/mutation.rb +0 -46
- data/lib/mutant/reporter/cli/report/config.rb +0 -116
- data/lib/mutant/rspec.rb +0 -0
- data/lib/mutant/runner/config.rb +0 -138
- data/lib/mutant/runner/killer.rb +0 -75
- data/lib/mutant/runner/mutation.rb +0 -78
- data/lib/mutant/runner/subject.rb +0 -85
- data/lib/mutant/test/report.rb +0 -59
- data/spec/unit/mutant/cli_new_spec.rb +0 -147
- data/spec/unit/mutant/cli_run_spec.rb +0 -46
- data/spec/unit/mutant/runner/config_spec.rb +0 -157
- data/spec/unit/mutant/runner/mutation_spec.rb +0 -101
- data/spec/unit/mutant/runner/subject_spec.rb +0 -59
- data/spec/unit/mutant/subject/mutations_spec.rb +0 -23
- data/spec/unit/mutant/subject/node_spec.rb +0 -17
@@ -9,7 +9,7 @@ describe Mutant::Expression::Namespace::Exact do
|
|
9
9
|
describe '#matcher' do
|
10
10
|
subject { object.matcher(cache) }
|
11
11
|
|
12
|
-
it { should eql(Mutant::Matcher::Scope.new(cache, TestApp::Literal)) }
|
12
|
+
it { should eql(Mutant::Matcher::Scope.new(cache, TestApp::Literal, object)) }
|
13
13
|
end
|
14
14
|
|
15
15
|
describe '#match_length' do
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mutant::Expression do
|
4
|
+
let(:object) { described_class }
|
5
|
+
|
6
|
+
describe '.try_parse' do
|
7
|
+
subject { object.try_parse(input) }
|
8
|
+
|
9
|
+
context 'on nonsense' do
|
10
|
+
let(:input) { 'foo bar' }
|
11
|
+
|
12
|
+
it { should be(nil) }
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'on a valid expression' do
|
16
|
+
let(:input) { 'Foo' }
|
17
|
+
|
18
|
+
it { should eql(Mutant::Expression::Namespace::Exact.new('Foo')) }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'on ambigious expression' do
|
22
|
+
class ExpressionA < Mutant::Expression
|
23
|
+
register(/\Atest-syntax\z/)
|
24
|
+
end
|
25
|
+
|
26
|
+
class ExpressionB < Mutant::Expression
|
27
|
+
register(/^test-syntax$/)
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:input) { 'test-syntax' }
|
31
|
+
|
32
|
+
it 'raises an exception' do
|
33
|
+
expect { subject }.to raise_error(Mutant::Expression::AmbigousExpressionError, 'Ambigous expression: "test-syntax"')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '.parse' do
|
39
|
+
subject { object.parse(input) }
|
40
|
+
|
41
|
+
context 'on nonsense' do
|
42
|
+
let(:input) { 'foo bar' }
|
43
|
+
|
44
|
+
it 'raises an exception' do
|
45
|
+
expect { subject }.to raise_error(Mutant::Expression::InvalidExpressionError, 'Expression: "foo bar" is not valid')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'on a valid expression' do
|
50
|
+
let(:input) { 'Foo' }
|
51
|
+
|
52
|
+
it { should eql(Mutant::Expression::Namespace::Exact.new('Foo')) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -8,11 +8,6 @@ describe Mutant::Integration do
|
|
8
8
|
|
9
9
|
let(:object) { class_under_test.new }
|
10
10
|
|
11
|
-
describe '#teardown' do
|
12
|
-
subject { object.teardown }
|
13
|
-
it_should_behave_like 'a command method'
|
14
|
-
end
|
15
|
-
|
16
11
|
describe '#setup' do
|
17
12
|
subject { object.setup }
|
18
13
|
it_should_behave_like 'a command method'
|
@@ -1,18 +1,49 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Mutant::Isolation do
|
3
|
+
describe Mutant::Isolation::None do
|
4
|
+
before do
|
5
|
+
@initial = 1
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '.run' do
|
9
|
+
let(:object) { described_class }
|
10
|
+
|
11
|
+
it 'does not isolate side effects' do
|
12
|
+
object.call { @initial = 2 }
|
13
|
+
expect(@initial).to be(2)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'return block value' do
|
17
|
+
expect(object.call { :foo }).to be(:foo)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'wraps *all* exceptions' do
|
21
|
+
expect { object.call { fail } }.to raise_error(Mutant::Isolation::Error)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe Mutant::Isolation::Fork do
|
28
|
+
before do
|
29
|
+
@initial = 1
|
30
|
+
end
|
31
|
+
|
4
32
|
describe '.run' do
|
5
33
|
let(:object) { described_class }
|
6
34
|
|
7
|
-
it '
|
8
|
-
|
9
|
-
|
10
|
-
expect(defined?(::TestConstant)).to be(nil)
|
35
|
+
it 'does isolate side effects' do
|
36
|
+
object.call { @initial = 2 }
|
37
|
+
expect(@initial).to be(1)
|
11
38
|
end
|
12
39
|
|
13
40
|
it 'return block value' do
|
14
41
|
expect(object.call { :foo }).to be(:foo)
|
15
42
|
end
|
16
43
|
|
44
|
+
it 'wraps Parallel::DeadWorker exceptions' do
|
45
|
+
expect { object.call { fail Parallel::DeadWorker } }.to raise_error(Mutant::Isolation::Error)
|
46
|
+
end
|
47
|
+
|
17
48
|
end
|
18
49
|
end
|
@@ -5,6 +5,7 @@ describe Mutant::Matcher::Chain do
|
|
5
5
|
let(:object) { described_class.new(matchers) }
|
6
6
|
|
7
7
|
describe '#each' do
|
8
|
+
let(:yields) { [] }
|
8
9
|
subject { object.each { |entry| yields << entry } }
|
9
10
|
|
10
11
|
let(:matchers) { [matcher_a, matcher_b] }
|
@@ -26,21 +27,8 @@ describe Mutant::Matcher::Chain do
|
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
29
|
-
let(:yields) { [] }
|
30
|
-
|
31
30
|
it 'should yield subjects' do
|
32
31
|
expect { subject }.to change { yields }.from([]).to([subject_a, subject_b])
|
33
32
|
end
|
34
33
|
end
|
35
|
-
|
36
|
-
describe '#matchers' do
|
37
|
-
subject { object.matchers }
|
38
|
-
|
39
|
-
let(:matchers) { double('Matchers') }
|
40
|
-
|
41
|
-
it { should be(matchers) }
|
42
|
-
|
43
|
-
it_should_behave_like 'an idempotent method'
|
44
|
-
end
|
45
|
-
|
46
34
|
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mutant::Matcher::Compiler do
|
4
|
+
let(:object) { described_class }
|
5
|
+
|
6
|
+
let(:env) { Fixtures::TEST_ENV }
|
7
|
+
|
8
|
+
let(:expression_a) { Mutant::Expression.parse('Foo*') }
|
9
|
+
let(:expression_b) { Mutant::Expression.parse('Bar*') }
|
10
|
+
|
11
|
+
let(:matcher_a) { expression_a.matcher(env) }
|
12
|
+
let(:matcher_b) { expression_b.matcher(env) }
|
13
|
+
|
14
|
+
let(:expected_matcher) do
|
15
|
+
Mutant::Matcher::Filter.new(expected_positive_matcher, expected_predicate)
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:expected_predicate) do
|
19
|
+
Morpher.compile(s(:true))
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '.call' do
|
23
|
+
subject { object.call(env, matcher_config.update(attributes)) }
|
24
|
+
|
25
|
+
let(:matcher_config) { Mutant::Matcher::Config::DEFAULT }
|
26
|
+
|
27
|
+
context 'on empty config' do
|
28
|
+
let(:attributes) { {} }
|
29
|
+
|
30
|
+
let(:expected_positive_matcher) { Mutant::Matcher::Chain.new([]) }
|
31
|
+
|
32
|
+
it { should eql(expected_matcher) }
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'on config with match expression' do
|
36
|
+
context 'and no filter' do
|
37
|
+
let(:attributes) do
|
38
|
+
{ match_expressions: [expression_a] }
|
39
|
+
end
|
40
|
+
|
41
|
+
let(:expected_positive_matcher) { Mutant::Matcher::Chain.new([matcher_a]) }
|
42
|
+
|
43
|
+
it { should eql(expected_matcher) }
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'and a subject filter' do
|
47
|
+
let(:attributes) do
|
48
|
+
{
|
49
|
+
match_expressions: [expression_a],
|
50
|
+
subject_ignores: [expression_b]
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
let(:expected_positive_matcher) { Mutant::Matcher::Chain.new([matcher_a]) }
|
55
|
+
|
56
|
+
let(:expected_predicate) do
|
57
|
+
Morpher::Evaluator::Predicate::Negation.new(
|
58
|
+
Morpher::Evaluator::Predicate::Boolean::Or.new([
|
59
|
+
described_class::SubjectPrefix.new(expression_b)
|
60
|
+
])
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
it { should eql(expected_matcher) }
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'and an attribute filter' do
|
68
|
+
let(:attributes) do
|
69
|
+
{
|
70
|
+
match_expressions: [expression_a],
|
71
|
+
subject_selects: [[:code, 'foo']]
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
let(:expected_positive_matcher) { Mutant::Matcher::Chain.new([matcher_a]) }
|
76
|
+
|
77
|
+
let(:expected_predicate) do
|
78
|
+
Morpher::Evaluator::Predicate::Boolean::Or.new([
|
79
|
+
Morpher.compile(s(:eql, s(:attribute, :code), s(:static, 'foo')))
|
80
|
+
])
|
81
|
+
end
|
82
|
+
|
83
|
+
it { should eql(expected_matcher) }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'on config with multiple match expressions' do
|
88
|
+
let(:attributes) do
|
89
|
+
{ match_expressions: [expression_a, expression_b] }
|
90
|
+
end
|
91
|
+
|
92
|
+
let(:expected_positive_matcher) { Mutant::Matcher::Chain.new([matcher_a, matcher_b]) }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mutant::Matcher::Filter do
|
4
|
+
let(:object) { described_class.new(matcher, predicate) }
|
5
|
+
|
6
|
+
describe '#each' do
|
7
|
+
let(:yields) { [] }
|
8
|
+
subject { object.each { |entry| yields << entry } }
|
9
|
+
|
10
|
+
let(:matcher) { [subject_a, subject_b] }
|
11
|
+
let(:predicate) { ->(subject) { subject.eql?(subject_a) } }
|
12
|
+
|
13
|
+
let(:subject_a) { double('Subject A') }
|
14
|
+
let(:subject_b) { double('Subject B') }
|
15
|
+
|
16
|
+
# it_should_behave_like 'an #each method'
|
17
|
+
context 'with no block' do
|
18
|
+
subject { object.each }
|
19
|
+
|
20
|
+
it { should be_instance_of(to_enum.class) }
|
21
|
+
|
22
|
+
it 'yields the expected values' do
|
23
|
+
expect(subject.to_a).to eql(object.to_a)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should yield subjects' do
|
28
|
+
expect { subject }.to change { yields }.from([]).to([subject_a])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -3,12 +3,13 @@ require 'spec_helper'
|
|
3
3
|
# rubocop:disable ClassAndModuleChildren
|
4
4
|
describe Mutant::Matcher::Method::Instance do
|
5
5
|
|
6
|
-
let(:env)
|
6
|
+
let(:env) { Fixtures::TEST_ENV }
|
7
|
+
let(:reporter) { Fixtures::TEST_CONFIG.reporter }
|
7
8
|
|
8
9
|
describe '#each' do
|
9
10
|
subject { object.each { |subject| yields << subject } }
|
10
11
|
|
11
|
-
let(:object) { described_class.
|
12
|
+
let(:object) { described_class.build(env, scope, method) }
|
12
13
|
let(:method) { scope.instance_method(method_name) }
|
13
14
|
let(:yields) { [] }
|
14
15
|
let(:namespace) { self.class }
|
@@ -25,6 +26,23 @@ describe Mutant::Matcher::Method::Instance do
|
|
25
26
|
node.children[1]
|
26
27
|
end
|
27
28
|
|
29
|
+
context 'when method is defined without source location' do
|
30
|
+
let(:scope) { Module }
|
31
|
+
let(:method) { scope.instance_method(:object_id) }
|
32
|
+
|
33
|
+
it 'does not emit matcher' do
|
34
|
+
subject
|
35
|
+
expect(yields.length).to be(0)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'does warn' do
|
39
|
+
subject
|
40
|
+
expect(reporter.warn_calls.last).to(
|
41
|
+
eql("#{method.inspect} does not have valid source location unable to emit matcher")
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
28
46
|
context 'when method is defined once' do
|
29
47
|
let(:base) { __LINE__ }
|
30
48
|
class self::Foo
|
@@ -36,6 +54,19 @@ describe Mutant::Matcher::Method::Instance do
|
|
36
54
|
it_should_behave_like 'a method matcher'
|
37
55
|
end
|
38
56
|
|
57
|
+
context 'when method is defined once with a memoizer' do
|
58
|
+
let(:base) { __LINE__ }
|
59
|
+
class self::Foo
|
60
|
+
def bar; end
|
61
|
+
include Adamantium
|
62
|
+
memoize :bar
|
63
|
+
end
|
64
|
+
|
65
|
+
let(:method_line) { 2 }
|
66
|
+
|
67
|
+
it_should_behave_like 'a method matcher'
|
68
|
+
end
|
69
|
+
|
39
70
|
context 'when method is defined multiple times' do
|
40
71
|
context 'on differend lines' do
|
41
72
|
let(:base) { __LINE__ }
|
@@ -6,7 +6,7 @@ describe Mutant::Matcher::Method::Singleton, '#each' do
|
|
6
6
|
|
7
7
|
let(:object) { described_class.new(env, scope, method) }
|
8
8
|
let(:method) { scope.method(method_name) }
|
9
|
-
let(:env) { Fixtures::
|
9
|
+
let(:env) { Fixtures::TEST_ENV }
|
10
10
|
let(:yields) { [] }
|
11
11
|
let(:namespace) { self.class }
|
12
12
|
let(:scope) { self.class::Foo }
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe Mutant::Matcher::Namespace do
|
4
4
|
let(:object) { described_class.new(env, Mutant::Expression.parse('TestApp*')) }
|
5
5
|
let(:yields) { [] }
|
6
|
-
let(:env) {
|
6
|
+
let(:env) { double('Env') }
|
7
7
|
|
8
8
|
subject { object.each { |item| yields << item } }
|
9
9
|
|
@@ -16,13 +16,17 @@ describe Mutant::Matcher::Namespace do
|
|
16
16
|
let(:subject_b) { double('SubjectB') }
|
17
17
|
|
18
18
|
before do
|
19
|
-
allow(Mutant::Matcher::Methods::Singleton).to receive(:new).with(env, singleton_a).and_return([subject_a])
|
20
|
-
allow(Mutant::Matcher::Methods::Instance).to receive(:new).with(env, singleton_a).and_return([])
|
21
|
-
|
22
19
|
allow(Mutant::Matcher::Methods::Singleton).to receive(:new).with(env, singleton_b).and_return([subject_b])
|
23
20
|
allow(Mutant::Matcher::Methods::Instance).to receive(:new).with(env, singleton_b).and_return([])
|
24
21
|
|
25
|
-
allow(
|
22
|
+
allow(Mutant::Matcher::Methods::Singleton).to receive(:new).with(env, singleton_a).and_return([subject_a])
|
23
|
+
allow(Mutant::Matcher::Methods::Instance).to receive(:new).with(env, singleton_a).and_return([])
|
24
|
+
|
25
|
+
allow(env).to receive(:matchable_scopes).and_return(
|
26
|
+
[singleton_a, singleton_b, singleton_c].map do |scope|
|
27
|
+
Mutant::Matcher::Scope.new(env, scope, Mutant::Expression.parse(scope.name))
|
28
|
+
end
|
29
|
+
)
|
26
30
|
end
|
27
31
|
|
28
32
|
context 'with no block' do
|
@@ -36,7 +40,7 @@ describe Mutant::Matcher::Namespace do
|
|
36
40
|
end
|
37
41
|
|
38
42
|
it 'should yield subjects' do
|
39
|
-
expect { subject }.to change { yields }.from([]).to([
|
43
|
+
expect { subject }.to change { yields }.from([]).to([subject_a, subject_b])
|
40
44
|
end
|
41
45
|
end
|
42
46
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mutant::Matcher::Null do
|
4
|
+
let(:object) { described_class.new }
|
5
|
+
|
6
|
+
describe '#each' do
|
7
|
+
let(:yields) { [] }
|
8
|
+
|
9
|
+
subject { object.each { |entry| yields << entry } }
|
10
|
+
|
11
|
+
# it_should_behave_like 'an #each method'
|
12
|
+
context 'with no block' do
|
13
|
+
subject { object.each }
|
14
|
+
|
15
|
+
it { should be_instance_of(to_enum.class) }
|
16
|
+
|
17
|
+
it 'yields the expected values' do
|
18
|
+
expect(subject.to_a).to eql(object.to_a)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should yield subjects' do
|
23
|
+
expect { subject }.not_to change { yields }.from([])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|