r_spec 1.0.0.beta7 → 1.0.0
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/README.md +33 -28
- data/lib/r_spec.rb +94 -1
- data/lib/r_spec/dsl.rb +8 -5
- data/lib/r_spec/error/pending_expectation.rb +1 -2
- data/lib/r_spec/expectation_target/base.rb +4 -4
- data/lib/r_spec/expectation_target/block.rb +9 -11
- data/lib/r_spec/expectation_target/value.rb +10 -6
- metadata +23 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b251a708b0d9e2f0dcc8a17f7ef08cfeeafa6e553446e9a650431c9aaf7b6951
|
4
|
+
data.tar.gz: 528cbc2cd07397ba094a5f08703be53467ac04ee85c82f1cd1465e419f4c5c92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7132f226d0510929ec1a466c2c3e9a3c90a654efd399646476eb04b5fbdcad84254791eb270b83ca68e2c17ad06ca98581a79251714ae7032a9eb888f8716db2
|
7
|
+
data.tar.gz: 55d0b1f4e98feeca3c875c542529e1ea5a4f43093a30658f56670f380de23f7f5402e562fccfb85e69e234a066f06ec8600493fcdedd871d78183ea419d055f6
|
data/README.md
CHANGED
@@ -6,33 +6,32 @@ A minimalist __[RSpec](https://github.com/rspec/rspec) clone__ with all the esse
|
|
6
6
|
|
7
7
|
## Status
|
8
8
|
|
9
|
-
[](https://github.com/cyril/r_spec.rb/releases)
|
10
|
+
[](https://rubydoc.info/github/cyril/r_spec.rb/main)
|
11
|
+
[](https://github.com/cyril/r_spec.rb/actions?query=workflow%3Aci+branch%3Amain)
|
12
|
+
[](https://github.com/cyril/r_spec.rb/actions?query=workflow%3Arubocop+branch%3Amain)
|
13
|
+
[](https://github.com/cyril/r_spec.rb/raw/main/LICENSE.md)
|
13
14
|
|
14
|
-
## Project
|
15
|
+
## Project goals
|
15
16
|
|
16
17
|
* Enforce the guidelines and best practices outlined in the community [RSpec style guide](https://rspec.rubystyle.guide/).
|
17
|
-
* Provide most of RSpec's DSL to express expected outcomes of a code example
|
18
|
+
* Provide most of RSpec's DSL to express expected outcomes of a code example with no magical powers.
|
18
19
|
|
19
|
-
## Some
|
20
|
+
## Some differences
|
20
21
|
|
21
22
|
* Less features and an implementation with much less code complexity.
|
22
23
|
* Spec files can also be executed directly with the `ruby` executable.
|
23
24
|
* There is no option to activate monkey-patching.
|
24
25
|
* It does not rely on hacks such as `at_exit` hook to trigger the tests.
|
25
|
-
* Built-in matchers do not trust _actual_ and do not send it messages.
|
26
|
+
* Built-in matchers [do not trust _actual_](https://asciinema.org/a/29172?autoplay=1&speed=2) and do not send it messages.
|
26
27
|
* If no `subject` has been explicitly determined, none is defined.
|
27
28
|
* If no described class is set, `described_class` is undefined instead of `nil`.
|
28
29
|
* Expectations cannot be added inside a `before` block.
|
29
30
|
* [Arbitrary helper methods](https://relishapp.com/rspec/rspec-core/v/3-10/docs/helper-methods/arbitrary-helper-methods) are not exposed to examples.
|
30
31
|
* The `let` method defines a helper method rather than a memoized helper method.
|
31
32
|
* The one-liner `is_expected` syntax also works with block expectations.
|
32
|
-
*
|
33
|
-
*
|
34
|
-
* All `after` definitions must come _before_ examples.
|
35
|
-
* All `let` definitions must come _before_ examples.
|
33
|
+
* `subject`, `before`, `after` and `let` definitions must come before examples.
|
34
|
+
* Each [`context` runs its tests in _isolation_](https://asciinema.org/a/29070?autoplay=1&speed=2) to prevent side effects.
|
36
35
|
|
37
36
|
## Important ⚠️
|
38
37
|
|
@@ -51,7 +50,7 @@ Following [RubyGems naming conventions](https://guides.rubygems.org/name-your-ge
|
|
51
50
|
Add this line to your application's Gemfile:
|
52
51
|
|
53
52
|
```ruby
|
54
|
-
gem "r_spec"
|
53
|
+
gem "r_spec"
|
55
54
|
```
|
56
55
|
|
57
56
|
And then execute:
|
@@ -63,7 +62,7 @@ bundle
|
|
63
62
|
Or install it yourself as:
|
64
63
|
|
65
64
|
```sh
|
66
|
-
gem install r_spec
|
65
|
+
gem install r_spec
|
67
66
|
```
|
68
67
|
|
69
68
|
## Overview
|
@@ -74,7 +73,7 @@ Inspired by [RSpec](https://rspec.info/), it includes a domain specific language
|
|
74
73
|
|
75
74
|
A basic spec looks something like this:
|
76
75
|
|
77
|
-
[](https://asciinema.org/a/422210?autoplay=1&speed=2)
|
78
77
|
|
79
78
|
## Usage
|
80
79
|
|
@@ -105,7 +104,8 @@ For unit tests, it is recommended to follow the conventions for method names:
|
|
105
104
|
* instance methods are prefixed with `#`, class methods with `.`.
|
106
105
|
|
107
106
|
To establish certain contexts — think _empty array_ versus _array with elements_ — the `context` method may be used to communicate this to the reader.
|
108
|
-
|
107
|
+
Its behavior is slightly different from `describe` because each `context` runs its tests in isolation,
|
108
|
+
so side effects caused by testing do not propagate out of contexts.
|
109
109
|
|
110
110
|
`describe` and `context` take an optional description as argument and a block containing the individual specs or nested groupings.
|
111
111
|
|
@@ -224,31 +224,28 @@ task default: :test
|
|
224
224
|
|
225
225
|
Benchmark against [100 executions of a file containing one expectation](https://github.com/cyril/r_spec.rb/blob/main/benchmark/) (lower is better).
|
226
226
|
|
227
|
-
|
228
|
-
|-------------|---------------------|
|
229
|
-
| `r_spec` | 13.0 |
|
230
|
-
| `rspec` | 32.2 |
|
231
|
-
| `minitest` | 17.5 |
|
232
|
-
| `test-unit` | 20.5 |
|
227
|
+

|
233
228
|
|
234
|
-
## Test
|
229
|
+
## Test suite
|
235
230
|
|
236
231
|
__RSpec clone__'s specifications are self-described here: [spec/](https://github.com/cyril/r_spec.rb/blob/main/spec/)
|
237
232
|
|
238
233
|
## Contact
|
239
234
|
|
240
|
-
* Home page: https://r-spec.dev
|
241
|
-
*
|
235
|
+
* Home page: [https://r-spec.dev/](https://r-spec.dev/)
|
236
|
+
* Cheatsheet: [https://r-spec.dev/cheatsheet.html](https://r-spec.dev/cheatsheet.html)
|
237
|
+
* Source code: [https://github.com/cyril/r_spec.rb](https://github.com/cyril/r_spec.rb)
|
238
|
+
* API Doc: [https://rubydoc.info/gems/r_spec](https://rubydoc.info/gems/r_spec)
|
242
239
|
* Twitter: [https://twitter.com/cyri\_](https://twitter.com/cyri\_)
|
243
240
|
|
244
|
-
## Special
|
241
|
+
## Special thanks ❤️
|
245
242
|
|
246
243
|
I would like to thank the whole [RSpec team](https://rspec.info/about/) for all their work.
|
247
244
|
It's a great framework and it's a pleasure to work with every day.
|
248
245
|
|
249
246
|
Without RSpec, this clone would not have been possible.
|
250
247
|
|
251
|
-
## Buy me a
|
248
|
+
## Buy me a coffee ☕
|
252
249
|
|
253
250
|
If you like this project please consider making a small donation.
|
254
251
|
|
@@ -260,4 +257,12 @@ __RSpec clone__ follows [Semantic Versioning 2.0](https://semver.org/).
|
|
260
257
|
|
261
258
|
## License
|
262
259
|
|
263
|
-
The [gem](https://rubygems.org/gems/r_spec) is available as open source under the terms of the [MIT License](https://
|
260
|
+
The [gem](https://rubygems.org/gems/r_spec) is available as open source under the terms of the [MIT License](https://github.com/cyril/r_spec.rb/raw/main/LICENSE.md).
|
261
|
+
|
262
|
+
## One more thing
|
263
|
+
|
264
|
+
Under the hood, __RSpec clone__ is largely animated by [a collection of testing libraries designed to make programmers happy](https://github.com/fixrb/).
|
265
|
+
|
266
|
+
It's a living example of what we can do combining small libraries together that can boost the fun of programming.
|
267
|
+
|
268
|
+

|
data/lib/r_spec.rb
CHANGED
@@ -65,7 +65,46 @@ require_relative File.join("r_spec", "dsl")
|
|
65
65
|
#
|
66
66
|
# @api public
|
67
67
|
module RSpec
|
68
|
-
#
|
68
|
+
# Defines an example group that establishes a specific context, like _empty
|
69
|
+
# array_ versus _array with elements_.
|
70
|
+
#
|
71
|
+
# Unlike {.describe}, the block is evaluated in isolation in order to scope
|
72
|
+
# possible side effects inside its context.
|
73
|
+
#
|
74
|
+
# @example
|
75
|
+
# require "r_spec"
|
76
|
+
#
|
77
|
+
# RSpec.context "when divided by zero" do
|
78
|
+
# subject { 42 / 0 }
|
79
|
+
#
|
80
|
+
# it { is_expected.to raise_exception ZeroDivisionError }
|
81
|
+
# end
|
82
|
+
#
|
83
|
+
# # Output to the console
|
84
|
+
# # Success: divided by 0.
|
85
|
+
#
|
86
|
+
# @param description [String] A description that usually begins with "when",
|
87
|
+
# "with" or "without".
|
88
|
+
# @param block [Proc] The block to define the specs.
|
89
|
+
#
|
90
|
+
# @api public
|
91
|
+
def self.context(description, &block)
|
92
|
+
Dsl.context(description, &block)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Defines an example group that describes a unit to be tested.
|
96
|
+
#
|
97
|
+
# @example
|
98
|
+
# require "r_spec"
|
99
|
+
#
|
100
|
+
# RSpec.describe String do
|
101
|
+
# describe "+" do
|
102
|
+
# it("concats") { expect("foo" + "bar").to eq "foobar" }
|
103
|
+
# end
|
104
|
+
# end
|
105
|
+
#
|
106
|
+
# # Output to the console
|
107
|
+
# # Success: expected to eq "foobar".
|
69
108
|
#
|
70
109
|
# @param const [Module, String] A module to include in block context.
|
71
110
|
# @param block [Proc] The block to define the specs.
|
@@ -74,4 +113,58 @@ module RSpec
|
|
74
113
|
def self.describe(const, &block)
|
75
114
|
Dsl.describe(const, &block)
|
76
115
|
end
|
116
|
+
|
117
|
+
# Defines a concrete test case.
|
118
|
+
#
|
119
|
+
# The test is performed by the block supplied to &block.
|
120
|
+
#
|
121
|
+
# @example The integer after 41
|
122
|
+
# require "r_spec"
|
123
|
+
#
|
124
|
+
# RSpec.it { expect(41.next).to be 42 }
|
125
|
+
#
|
126
|
+
# # Output to the console
|
127
|
+
# # Success: expected to be 42.
|
128
|
+
#
|
129
|
+
# It is usually used inside a {Dsl.describe} or {Dsl.context} section.
|
130
|
+
#
|
131
|
+
# @param name [String, nil] The name of the spec.
|
132
|
+
# @param block [Proc] An expectation to evaluate.
|
133
|
+
#
|
134
|
+
# @raise (see RSpec::ExpectationTarget::Base#result)
|
135
|
+
# @return (see RSpec::ExpectationTarget::Base#result)
|
136
|
+
#
|
137
|
+
# @api public
|
138
|
+
def self.it(name = nil, &block)
|
139
|
+
Dsl.it(name, &block)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Defines a pending test case.
|
143
|
+
#
|
144
|
+
# `&block` is never evaluated. It can be used to describe behaviour that is
|
145
|
+
# not yet implemented.
|
146
|
+
#
|
147
|
+
# @example
|
148
|
+
# require "r_spec"
|
149
|
+
#
|
150
|
+
# RSpec.pending "is implemented but waiting" do
|
151
|
+
# expect something to be finished
|
152
|
+
# end
|
153
|
+
#
|
154
|
+
# RSpec.pending "is not yet implemented and waiting"
|
155
|
+
#
|
156
|
+
# # Output to the console
|
157
|
+
# # Warning: is implemented but waiting.
|
158
|
+
# # Warning: is not yet implemented and waiting.
|
159
|
+
#
|
160
|
+
# It is usually used inside a {Dsl.describe} or {Dsl.context} section.
|
161
|
+
#
|
162
|
+
# @param message [String] The reason why the example is pending.
|
163
|
+
#
|
164
|
+
# @return [nil] Write a message to STDOUT.
|
165
|
+
#
|
166
|
+
# @api public
|
167
|
+
def self.pending(message)
|
168
|
+
Dsl.pending(message)
|
169
|
+
end
|
77
170
|
end
|
data/lib/r_spec/dsl.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "aw"
|
4
|
+
|
3
5
|
require_relative "console"
|
4
6
|
require_relative "error"
|
5
7
|
require_relative "expectation_helper"
|
@@ -155,7 +157,8 @@ module RSpec
|
|
155
157
|
# Defines an example group that establishes a specific context, like _empty
|
156
158
|
# array_ versus _array with elements_.
|
157
159
|
#
|
158
|
-
#
|
160
|
+
# Unlike {.describe}, the block is evaluated in isolation in order to scope
|
161
|
+
# possible side effects inside its context.
|
159
162
|
#
|
160
163
|
# @example
|
161
164
|
# require "r_spec"
|
@@ -177,9 +180,9 @@ module RSpec
|
|
177
180
|
# @param _description [String] A description that usually begins with
|
178
181
|
# "when", "with" or "without".
|
179
182
|
# @param block [Proc] The block to define the specs.
|
180
|
-
def self.context(_description
|
183
|
+
def self.context(_description, &block)
|
181
184
|
desc = ::Class.new(self)
|
182
|
-
desc.instance_eval(&block)
|
185
|
+
::Aw.fork! { desc.instance_eval(&block) }
|
183
186
|
end
|
184
187
|
|
185
188
|
# Defines a concrete test case.
|
@@ -230,7 +233,7 @@ module RSpec
|
|
230
233
|
|
231
234
|
exit false
|
232
235
|
ensure
|
233
|
-
example
|
236
|
+
example&.send(AFTER_METHOD)
|
234
237
|
end
|
235
238
|
|
236
239
|
# Use the {.its} method to define a single spec that specifies the actual
|
@@ -295,7 +298,7 @@ module RSpec
|
|
295
298
|
|
296
299
|
exit false
|
297
300
|
ensure
|
298
|
-
example
|
301
|
+
example&.send(AFTER_METHOD)
|
299
302
|
end
|
300
303
|
|
301
304
|
# Defines a pending test case.
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "expresenter"
|
4
|
+
require "test_tube"
|
4
5
|
|
5
6
|
require_relative File.join("..", "console")
|
6
7
|
|
@@ -50,12 +51,12 @@ module RSpec
|
|
50
51
|
|
51
52
|
protected
|
52
53
|
|
54
|
+
# @param passed [Boolean] The high expectation passed or failed.
|
53
55
|
# @param actual [#object_id] The actual value.
|
54
56
|
# @param error [Exception, nil] Any raised exception.
|
55
57
|
# @param got [Boolean, nil] Any returned value.
|
56
58
|
# @param matcher [#matches?] The matcher.
|
57
59
|
# @param negate [Boolean] The assertion is positive or negative.
|
58
|
-
# @param valid [Boolean] The result of an expectation.
|
59
60
|
#
|
60
61
|
# @return [nil] Write a message to STDOUT.
|
61
62
|
#
|
@@ -63,14 +64,13 @@ module RSpec
|
|
63
64
|
# `Kernel.exit(false)` with a failure message written to STDERR.
|
64
65
|
#
|
65
66
|
# @api private
|
66
|
-
def result(actual:, error:, got:, matcher:, negate
|
67
|
-
Console.passed_spec ::Expresenter.call(
|
67
|
+
def result(passed, actual:, error:, got:, matcher:, negate:)
|
68
|
+
Console.passed_spec ::Expresenter.call(passed).with(
|
68
69
|
actual: actual,
|
69
70
|
error: error,
|
70
71
|
expected: matcher.expected,
|
71
72
|
got: got,
|
72
73
|
negate: negate,
|
73
|
-
valid: valid,
|
74
74
|
matcher: matcher.class.to_sym,
|
75
75
|
level: :MUST
|
76
76
|
)
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "spectus/exam"
|
4
|
-
|
5
3
|
require_relative "base"
|
6
4
|
|
7
5
|
module RSpec
|
@@ -30,20 +28,20 @@ module RSpec
|
|
30
28
|
# @raise [SystemExit] Terminate execution immediately by calling
|
31
29
|
# `Kernel.exit(false)` with a failure message written to STDERR.
|
32
30
|
def absolute_requirement(matcher:, negate:)
|
33
|
-
|
34
|
-
|
31
|
+
experiment = ::TestTube.invoke(
|
32
|
+
@actual,
|
35
33
|
isolation: false,
|
36
|
-
|
37
|
-
|
34
|
+
matcher: matcher,
|
35
|
+
negate: negate
|
38
36
|
)
|
39
37
|
|
40
38
|
result(
|
41
|
-
|
42
|
-
|
43
|
-
|
39
|
+
experiment.got.equal?(true),
|
40
|
+
actual: experiment.actual,
|
41
|
+
error: experiment.error,
|
42
|
+
got: experiment.got,
|
44
43
|
matcher: matcher,
|
45
|
-
negate: negate
|
46
|
-
valid: exam.valid?
|
44
|
+
negate: negate
|
47
45
|
)
|
48
46
|
end
|
49
47
|
end
|
@@ -28,15 +28,19 @@ module RSpec
|
|
28
28
|
# @raise [SystemExit] Terminate execution immediately by calling
|
29
29
|
# `Kernel.exit(false)` with a failure message written to STDERR.
|
30
30
|
def absolute_requirement(matcher:, negate:)
|
31
|
-
|
31
|
+
experiment = ::TestTube.pass(
|
32
|
+
@actual,
|
33
|
+
matcher: matcher,
|
34
|
+
negate: negate
|
35
|
+
)
|
32
36
|
|
33
37
|
result(
|
34
|
-
|
35
|
-
|
36
|
-
|
38
|
+
experiment.got.equal?(true),
|
39
|
+
actual: experiment.actual,
|
40
|
+
error: experiment.error,
|
41
|
+
got: experiment.got,
|
37
42
|
matcher: matcher,
|
38
|
-
negate: negate
|
39
|
-
valid: valid
|
43
|
+
negate: negate
|
40
44
|
)
|
41
45
|
end
|
42
46
|
end
|
metadata
CHANGED
@@ -1,29 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: r_spec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cyril Kato
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-06-
|
11
|
+
date: 2021-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aw
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.12
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.12
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: expresenter
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
31
|
- - "~>"
|
18
32
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
33
|
+
version: 1.3.0
|
20
34
|
type: :runtime
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
38
|
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.
|
40
|
+
version: 1.3.0
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: matchi-rspec
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,19 +53,19 @@ dependencies:
|
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: 1.1.2
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
56
|
+
name: test_tube
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
61
|
+
version: 1.1.0
|
48
62
|
type: :runtime
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
68
|
+
version: 1.1.0
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: bundler
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -221,9 +235,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
221
235
|
version: 2.7.0
|
222
236
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
223
237
|
requirements:
|
224
|
-
- - "
|
238
|
+
- - ">="
|
225
239
|
- !ruby/object:Gem::Version
|
226
|
-
version:
|
240
|
+
version: '0'
|
227
241
|
requirements: []
|
228
242
|
rubygems_version: 3.1.6
|
229
243
|
signing_key:
|