xspec 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +22 -50
- data/bin/xspec +4 -2
- data/lib/xspec.rb +18 -11
- data/lib/xspec/data_structures.rb +15 -15
- data/lib/xspec/defaults.rb +6 -6
- data/lib/xspec/dsl.rb +5 -0
- data/lib/xspec/evaluators.rb +316 -22
- data/lib/xspec/notifiers.rb +2 -0
- data/lib/xspec/schedulers.rb +39 -0
- data/spec/integration/rspec_expectations_spec.rb +3 -3
- data/spec/spec_helper.rb +0 -2
- data/spec/unit/assertion_spec.rb +7 -7
- data/spec/unit/doubles_spec.rb +93 -115
- data/xspec.gemspec +2 -2
- metadata +4 -4
- data/lib/xspec/assertion_contexts.rb +0 -382
data/lib/xspec/notifiers.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
# # Schedulers
|
2
|
+
|
3
|
+
# Schedulers are responsible for collecting all units of work to be run and
|
4
|
+
# scheduling them.
|
5
|
+
module XSpec
|
6
|
+
module Scheduler
|
7
|
+
# The serial scheduler, unsurprisingly, runs all units of works serially in
|
8
|
+
# a loop. It is about as simple a scheduler as you can imagine. Parents
|
9
|
+
# are responsible for actually executing the work.
|
10
|
+
class Serial
|
11
|
+
def initialize(opts = {})
|
12
|
+
@clock = opts.fetch(:clock, ->{ Time.now.to_f })
|
13
|
+
end
|
14
|
+
|
15
|
+
def run(context, notifier)
|
16
|
+
notifier.run_start
|
17
|
+
|
18
|
+
context.nested_units_of_work.each do |x|
|
19
|
+
notifier.evaluate_start(x)
|
20
|
+
|
21
|
+
start_time = clock.()
|
22
|
+
errors = x.immediate_parent.execute(x)
|
23
|
+
finish_time = clock.()
|
24
|
+
|
25
|
+
result = ExecutedUnitOfWork.new(x, errors, finish_time - start_time)
|
26
|
+
notifier.evaluate_finish(result)
|
27
|
+
end
|
28
|
+
|
29
|
+
notifier.run_finish
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
attr_reader :clock
|
35
|
+
end
|
36
|
+
|
37
|
+
DEFAULT = Serial.new
|
38
|
+
end
|
39
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
require 'xspec/
|
3
|
+
require 'xspec/evaluators'
|
4
4
|
|
5
5
|
it 'integrates with rspec' do
|
6
6
|
opts = {
|
7
|
-
|
8
|
-
include XSpec::
|
7
|
+
evaluator: XSpec::Evaluator.stack {
|
8
|
+
include XSpec::Evaluator::RSpecExpectations
|
9
9
|
}
|
10
10
|
}
|
11
11
|
|
data/spec/spec_helper.rb
CHANGED
data/spec/unit/assertion_spec.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe 'simple assertion context' do
|
4
|
-
let(:subject) { Class.new { include XSpec::
|
5
|
-
include XSpec::
|
4
|
+
let(:subject) { Class.new { include XSpec::Evaluator.stack {
|
5
|
+
include XSpec::Evaluator::Simple
|
6
6
|
}}.new }
|
7
7
|
|
8
8
|
describe 'assert' do
|
@@ -14,7 +14,7 @@ describe 'simple assertion context' do
|
|
14
14
|
begin
|
15
15
|
subject.assert(false)
|
16
16
|
fail "Assertion did not fail"
|
17
|
-
rescue XSpec::
|
17
|
+
rescue XSpec::Evaluator::Simple::AssertionFailed => e
|
18
18
|
assert_equal "assertion failed", e.message
|
19
19
|
end
|
20
20
|
end
|
@@ -23,7 +23,7 @@ describe 'simple assertion context' do
|
|
23
23
|
begin
|
24
24
|
subject.assert(false, "nope")
|
25
25
|
fail "Assertion did not fail"
|
26
|
-
rescue XSpec::
|
26
|
+
rescue XSpec::Evaluator::Simple::AssertionFailed => e
|
27
27
|
assert_equal "nope", e.message
|
28
28
|
end
|
29
29
|
end
|
@@ -38,7 +38,7 @@ describe 'simple assertion context' do
|
|
38
38
|
begin
|
39
39
|
subject.assert_equal("a", "b")
|
40
40
|
fail "Assertion did not fail"
|
41
|
-
rescue XSpec::
|
41
|
+
rescue XSpec::Evaluator::Simple::AssertionFailed => e
|
42
42
|
assert_include 'want: "a"', e.message
|
43
43
|
assert_include 'got: "b"', e.message
|
44
44
|
end
|
@@ -50,7 +50,7 @@ describe 'simple assertion context' do
|
|
50
50
|
begin
|
51
51
|
subject.fail
|
52
52
|
assert false, "fail did not fail"
|
53
|
-
rescue XSpec::
|
53
|
+
rescue XSpec::Evaluator::Simple::AssertionFailed => e
|
54
54
|
assert_equal "failed", e.message
|
55
55
|
end
|
56
56
|
end
|
@@ -59,7 +59,7 @@ describe 'simple assertion context' do
|
|
59
59
|
begin
|
60
60
|
subject.fail ":("
|
61
61
|
assert false, "fail did not fail"
|
62
|
-
rescue XSpec::
|
62
|
+
rescue XSpec::Evaluator::Simple::AssertionFailed => e
|
63
63
|
assert_equal ":(", e.message
|
64
64
|
end
|
65
65
|
end
|
data/spec/unit/doubles_spec.rb
CHANGED
@@ -6,127 +6,135 @@ class LoadedClass
|
|
6
6
|
end
|
7
7
|
|
8
8
|
describe 'doubles assertion context' do
|
9
|
-
let(:subject) { Class.new { include XSpec::
|
10
|
-
include XSpec::
|
9
|
+
let(:subject) { Class.new { include XSpec::Evaluator.stack {
|
10
|
+
include XSpec::Evaluator::Doubles
|
11
11
|
}}.new }
|
12
12
|
|
13
13
|
it 'converts double exceptions to failures' do
|
14
14
|
result = subject.call(XSpec::UnitOfWork.new(nil, ->{
|
15
|
-
raise XSpec::
|
15
|
+
raise XSpec::Evaluator::Doubles::DoubleFailure, "nope"
|
16
16
|
}))
|
17
17
|
assert_equal "nope", result[0].message
|
18
18
|
end
|
19
19
|
|
20
20
|
describe 'doubles of unloaded classes' do
|
21
|
-
it 'allows
|
22
|
-
assert_equal
|
21
|
+
it 'allows a stub to be used multiple times' do
|
22
|
+
assert_equal 1, subject.instance_eval {
|
23
23
|
double = instance_double('Bogus')
|
24
|
-
|
25
|
-
double.foo
|
24
|
+
stub(double).foo("a") { 1 }
|
25
|
+
double.foo("a")
|
26
|
+
double.foo("a")
|
26
27
|
}
|
27
28
|
end
|
28
29
|
|
29
|
-
it 'allows any return value to be
|
30
|
+
it 'allows any return value to be stubbed' do
|
30
31
|
assert_equal 1, subject.instance_eval {
|
31
32
|
double = instance_double('Bogus')
|
32
|
-
|
33
|
-
|
33
|
+
stub(double).foo("a") { 2 }
|
34
|
+
stub(double).foo("b") { 3 }
|
34
35
|
double.foo("b") - double.foo("a")
|
35
36
|
}
|
36
37
|
end
|
37
38
|
|
38
39
|
it 'requires matching method name' do
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
}
|
45
|
-
fail "no error raised"
|
46
|
-
rescue XSpec::AssertionContext::Doubles::DoubleFailure => e
|
47
|
-
assert_include "Unexpectedly received", e.message
|
48
|
-
assert_include 'bar("a")', e.message
|
49
|
-
end
|
40
|
+
assert_equal nil, subject.instance_eval {
|
41
|
+
double = instance_double('Bogus')
|
42
|
+
stub(double).foo("a") { 1 }
|
43
|
+
double.bar("a")
|
44
|
+
}
|
50
45
|
end
|
51
46
|
|
52
47
|
it 'requires exact arguments' do
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
}
|
59
|
-
fail "no error raised"
|
60
|
-
rescue XSpec::AssertionContext::Doubles::DoubleFailure => e
|
61
|
-
assert_include "Unexpectedly received", e.message
|
62
|
-
assert_include 'foo("b")', e.message
|
63
|
-
end
|
48
|
+
assert_equal nil, subject.instance_eval {
|
49
|
+
double = instance_double('Bogus')
|
50
|
+
stub(double).foo("a") { 1 }
|
51
|
+
double.foo("b")
|
52
|
+
}
|
64
53
|
end
|
65
54
|
end
|
66
55
|
|
67
|
-
describe '
|
68
|
-
it '
|
56
|
+
describe 'verify' do
|
57
|
+
it 'can verify a method was called with no setup' do
|
69
58
|
assert subject.instance_eval {
|
70
59
|
double = instance_double('Bogus')
|
71
|
-
expect(double).foo
|
72
60
|
double.foo
|
73
|
-
|
61
|
+
verify(double).foo
|
74
62
|
true
|
75
63
|
}
|
76
64
|
end
|
77
65
|
|
78
|
-
it '
|
66
|
+
it 'can verify a method that was stubbed' do
|
67
|
+
assert subject.instance_eval {
|
68
|
+
double = instance_double('Bogus')
|
69
|
+
stub(double).foo { 1 }
|
70
|
+
double.foo
|
71
|
+
verify(double).foo
|
72
|
+
true
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'raises if method was not called' do
|
79
77
|
begin
|
80
78
|
subject.instance_eval {
|
81
79
|
double = instance_double('Bogus')
|
82
|
-
|
83
|
-
|
80
|
+
double.bar
|
81
|
+
verify(double).foo("b")
|
84
82
|
}
|
85
83
|
fail "no error raised"
|
86
|
-
rescue XSpec::
|
87
|
-
assert_include "
|
88
|
-
assert_include 'foo(
|
84
|
+
rescue XSpec::Evaluator::Doubles::DoubleFailure => e
|
85
|
+
assert_include "Did not receive", e.message
|
86
|
+
assert_include 'foo("b")', e.message
|
89
87
|
end
|
90
88
|
end
|
91
89
|
|
92
|
-
it '
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
ret
|
109
|
-
}
|
90
|
+
it 'raises if method was not called with right arguments' do
|
91
|
+
begin
|
92
|
+
subject.instance_eval {
|
93
|
+
double = instance_double('Bogus')
|
94
|
+
double.foo("a")
|
95
|
+
double.foo("b")
|
96
|
+
verify(double).foo("c")
|
97
|
+
}
|
98
|
+
fail "no error raised"
|
99
|
+
rescue XSpec::Evaluator::Doubles::DoubleFailure => e
|
100
|
+
assert_include "Did not receive", e.message
|
101
|
+
assert_include 'foo("b")', e.message
|
102
|
+
assert_include "Did receive", e.message
|
103
|
+
assert_include 'foo("a")', e.message
|
104
|
+
assert_include 'foo("b")', e.message
|
105
|
+
end
|
110
106
|
end
|
111
107
|
end
|
112
108
|
|
113
109
|
describe 'instance_double' do
|
114
110
|
describe 'when doubled class is loaded' do
|
115
|
-
it 'allows instance methods to be
|
111
|
+
it 'allows instance methods to be stubbed' do
|
116
112
|
assert subject.instance_eval {
|
117
113
|
double = instance_double('LoadedClass')
|
118
|
-
|
114
|
+
stub(double).instance_method { 123 }
|
119
115
|
}
|
120
116
|
end
|
121
117
|
|
122
|
-
it 'does not allow non-existing methods to be
|
118
|
+
it 'does not allow non-existing methods to be stubbed' do
|
119
|
+
begin
|
120
|
+
assert subject.instance_eval {
|
121
|
+
double = instance_double('LoadedClass')
|
122
|
+
stub(double).bogus_method { 123 }
|
123
|
+
}
|
124
|
+
fail "no error raised"
|
125
|
+
rescue XSpec::Evaluator::Doubles::DoubleFailure => e
|
126
|
+
assert_include "LoadedClass#bogus_method", e.message
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'does not allow non-existing methods to be verified' do
|
123
131
|
begin
|
124
132
|
assert subject.instance_eval {
|
125
133
|
double = instance_double('LoadedClass')
|
126
|
-
|
134
|
+
verify(double).bogus_method { 123 }
|
127
135
|
}
|
128
136
|
fail "no error raised"
|
129
|
-
rescue XSpec::
|
137
|
+
rescue XSpec::Evaluator::Doubles::DoubleFailure => e
|
130
138
|
assert_include "LoadedClass#bogus_method", e.message
|
131
139
|
end
|
132
140
|
end
|
@@ -135,21 +143,33 @@ describe 'doubles assertion context' do
|
|
135
143
|
|
136
144
|
describe 'class_double' do
|
137
145
|
describe 'when doubled class is loaded' do
|
138
|
-
it 'allows instance methods to be
|
146
|
+
it 'allows instance methods to be stubbed' do
|
139
147
|
assert subject.instance_eval {
|
140
148
|
double = class_double('LoadedClass')
|
141
|
-
|
149
|
+
stub(double).class_method { 123 }
|
142
150
|
}
|
143
151
|
end
|
144
152
|
|
145
|
-
it 'does not allow non-existing methods to be
|
153
|
+
it 'does not allow non-existing methods to be stubbed' do
|
146
154
|
begin
|
147
155
|
assert subject.instance_eval {
|
148
156
|
double = class_double('LoadedClass')
|
149
|
-
|
157
|
+
stub(double).bogus_method { 123 }
|
150
158
|
}
|
151
159
|
fail "no error raised"
|
152
|
-
rescue XSpec::
|
160
|
+
rescue XSpec::Evaluator::Doubles::DoubleFailure => e
|
161
|
+
assert_include "LoadedClass.bogus_method", e.message
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'does not allow non-existing methods to be verified' do
|
166
|
+
begin
|
167
|
+
assert subject.instance_eval {
|
168
|
+
double = class_double('LoadedClass')
|
169
|
+
verify(double).bogus_method
|
170
|
+
}
|
171
|
+
fail "no error raised"
|
172
|
+
rescue XSpec::Evaluator::Doubles::DoubleFailure => e
|
153
173
|
assert_include "LoadedClass.bogus_method", e.message
|
154
174
|
end
|
155
175
|
end
|
@@ -158,8 +178,8 @@ describe 'doubles assertion context' do
|
|
158
178
|
end
|
159
179
|
|
160
180
|
describe 'strict doubles assertion context' do
|
161
|
-
let(:subject) { Class.new { include XSpec::
|
162
|
-
include XSpec::
|
181
|
+
let(:subject) { Class.new { include XSpec::Evaluator.stack {
|
182
|
+
include XSpec::Evaluator::Doubles.with(:strict)
|
163
183
|
}}.new }
|
164
184
|
|
165
185
|
it 'allows doubling of loaded classes' do
|
@@ -170,50 +190,8 @@ describe 'strict doubles assertion context' do
|
|
170
190
|
begin
|
171
191
|
subject.instance_double("Bogus")
|
172
192
|
fail "no error raised"
|
173
|
-
rescue XSpec::
|
193
|
+
rescue XSpec::Evaluator::Doubles::DoubleFailure => e
|
174
194
|
assert_include "Bogus", e.message
|
175
195
|
end
|
176
196
|
end
|
177
197
|
end
|
178
|
-
|
179
|
-
describe 'auto-verifying doubles assertion context' do
|
180
|
-
let(:subject) { Class.new { include XSpec::AssertionContext.stack {
|
181
|
-
include XSpec::AssertionContext::Doubles.with(:auto_verify)
|
182
|
-
}}.new }
|
183
|
-
|
184
|
-
it 'verifies all used instance doubles on successful result' do
|
185
|
-
result = subject.call(XSpec::UnitOfWork.new(nil, ->{
|
186
|
-
double = instance_double('Bogus')
|
187
|
-
expect(double).foo
|
188
|
-
}))
|
189
|
-
|
190
|
-
assert_equal 1, result.length
|
191
|
-
assert_include "did not receive", result[0].message
|
192
|
-
assert_include "foo()", result[0].message
|
193
|
-
end
|
194
|
-
|
195
|
-
it 'verifies all used class doubles on successful result' do
|
196
|
-
result = subject.call(XSpec::UnitOfWork.new(nil, ->{
|
197
|
-
double = class_double('Bogus')
|
198
|
-
expect(double).foo
|
199
|
-
}))
|
200
|
-
|
201
|
-
assert_equal 1, result.length
|
202
|
-
assert_include "did not receive", result[0].message
|
203
|
-
assert_include "foo()", result[0].message
|
204
|
-
end
|
205
|
-
|
206
|
-
it 'does not verify doubles if errors occurred' do
|
207
|
-
result = subject.call(XSpec::UnitOfWork.new(nil, ->{
|
208
|
-
double = instance_double('Bogus')
|
209
|
-
expect(double).foo
|
210
|
-
fail "nope"
|
211
|
-
}))
|
212
|
-
assert_equal 1, result.length
|
213
|
-
assert_include "nope", result[0].message
|
214
|
-
end
|
215
|
-
|
216
|
-
it 'returns successful result if all doubles are valid' do
|
217
|
-
assert_equal [], subject.call(XSpec::UnitOfWork.new(nil, ->{}))
|
218
|
-
end
|
219
|
-
end
|
data/xspec.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |gem|
|
|
11
11
|
gem.homepage = "http://github.com/xaviershay/xspec"
|
12
12
|
|
13
13
|
gem.executables = []
|
14
|
-
gem.required_ruby_version = '>= 1.
|
14
|
+
gem.required_ruby_version = '>= 2.1.0'
|
15
15
|
gem.files = Dir.glob("{spec,lib}/**/*.rb") + %w(
|
16
16
|
README.md
|
17
17
|
xspec.gemspec
|
@@ -22,6 +22,6 @@ Gem::Specification.new do |gem|
|
|
22
22
|
gem.bindir = "bin"
|
23
23
|
gem.executables << "xspec"
|
24
24
|
gem.license = "Apache 2.0"
|
25
|
-
gem.version = "0.0
|
25
|
+
gem.version = "0.1.0"
|
26
26
|
gem.has_rdoc = false
|
27
27
|
end
|