spectus 3.0.10 → 3.1.4
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/LICENSE.md +1 -1
- data/README.md +75 -84
- data/lib/spectus.rb +3 -5
- data/lib/spectus/exam.rb +56 -0
- data/lib/spectus/expectation_target.rb +87 -70
- data/lib/spectus/requirement_level/base.rb +40 -81
- data/lib/spectus/requirement_level/may.rb +17 -0
- data/lib/spectus/requirement_level/must.rb +17 -0
- data/lib/spectus/requirement_level/should.rb +17 -0
- data/lib/spectus/result.rb +15 -0
- data/lib/spectus/result/common.rb +180 -0
- data/lib/spectus/result/fail.rb +38 -17
- data/lib/spectus/result/pass.rb +47 -22
- metadata +69 -42
- data/lib/spectus/matchers.rb +0 -33
- data/lib/spectus/report.rb +0 -92
- data/lib/spectus/requirement_level/high.rb +0 -27
- data/lib/spectus/requirement_level/low.rb +0 -27
- data/lib/spectus/requirement_level/medium.rb +0 -27
- data/lib/spectus/result/base.rb +0 -112
- data/lib/spectus/sandbox.rb +0 -61
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73306cc997a51543203fcfbec28fedae74de8ca9f382040db66d1c6aebbfc4bd
|
4
|
+
data.tar.gz: c9d9365b33cc4cca9cb54630306f9320c254a42ad64161d8a609107eeb8f95e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5cdfb58c6e5e3b748f8c5071f354793618a6e6e00053e3139175c5afde4cbc2fd39a419fbe516970354a6eaaee585637077d6dcc65b1d3ba7ae5412f26dcce60
|
7
|
+
data.tar.gz: 8211f7d6955d70067071a691bfa80b1f640930c01db4cec6433534141c3f7c7a4e386ee82c80f00941b3c6a04426d2266be7cdb416960e04c5e8a36b0f35bc95
|
data/LICENSE.md
CHANGED
data/README.md
CHANGED
@@ -1,31 +1,19 @@
|
|
1
1
|
# Spectus
|
2
2
|
|
3
|
-
[][travis]
|
4
4
|
[][codeclimate]
|
5
5
|
[][gem]
|
6
|
-
[][inchpages]
|
7
|
+
[][rubydoc]
|
8
8
|
|
9
|
-
> Expectation library with [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt)'s requirement levels
|
10
|
-
|
11
|
-
## Contact
|
12
|
-
|
13
|
-
* Home page: https://github.com/fixrb/spectus
|
14
|
-
* Bugs/issues: https://github.com/fixrb/spectus/issues
|
15
|
-
* Support: https://stackoverflow.com/questions/tagged/spectus
|
16
|
-
|
17
|
-
## Rubies
|
18
|
-
|
19
|
-
* [MRI](https://www.ruby-lang.org/)
|
20
|
-
* [Rubinius](http://rubini.us/)
|
21
|
-
* [JRuby](http://jruby.org/)
|
9
|
+
> Expectation library with [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt)'s requirement levels 🚥
|
22
10
|
|
23
11
|
## Installation
|
24
12
|
|
25
13
|
Add this line to your application's Gemfile:
|
26
14
|
|
27
15
|
```ruby
|
28
|
-
gem
|
16
|
+
gem "spectus"
|
29
17
|
```
|
30
18
|
|
31
19
|
And then execute:
|
@@ -40,6 +28,8 @@ Or install it yourself as:
|
|
40
28
|
|
41
29
|
An expectation is an assertion that is either `true` or `false`.
|
42
30
|
|
31
|
+
There are several scenarios:
|
32
|
+
|
43
33
|
| Requirement levels | **MUST** | **SHOULD** | **MAY** |
|
44
34
|
| ------------------------- | -------- | ---------- | ------- |
|
45
35
|
| Implemented & Matched | `true` | `true` | `true` |
|
@@ -47,39 +37,51 @@ An expectation is an assertion that is either `true` or `false`.
|
|
47
37
|
| Implemented & Exception | `false` | `false` | `false` |
|
48
38
|
| Not implemented | `false` | `false` | `true` |
|
49
39
|
|
50
|
-
|
40
|
+
Thus,
|
51
41
|
|
52
|
-
|
42
|
+
* when an assertion is `true`, a `Spectus::Result::Pass` instance is returned;
|
43
|
+
* when an assertion is `false`, a `Spectus::Result::Fail` exception is raised.
|
53
44
|
|
54
|
-
|
55
|
-
* when the requirement level of an expectation does not end with `!`, the test is performed without isolation.
|
45
|
+
Both results share a common interface.
|
56
46
|
|
57
|
-
|
47
|
+
Passed expectations can be classified as:
|
58
48
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
49
|
+
* ✅ success
|
50
|
+
* ⚠️ warning
|
51
|
+
* 💡 info
|
52
|
+
|
53
|
+
Failed expectations can be classified as:
|
54
|
+
|
55
|
+
* ❌ failure
|
56
|
+
* 💥 error
|
57
|
+
|
58
|
+
## Code Isolation
|
59
|
+
|
60
|
+
When executing expectations, side-effects may occur.
|
61
|
+
Because they may or may not be desired, each requirement level has 2 versions:
|
62
|
+
|
63
|
+
* if it does not end with `!`, its test is performed without isolation;
|
64
|
+
* if it ends with `!`, its test is performed in isolation.
|
65
65
|
|
66
66
|
Example of test without isolation:
|
67
67
|
|
68
68
|
```ruby
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
include Spectus
|
70
|
+
greeting = "Hello, world!"
|
71
|
+
it { greeting.gsub!("world", "Alice") }.MUST eql "Hello, Alice!"
|
72
|
+
# => Spectus::Result::Pass(actual: "Hello, Alice!", error: nil, expected: "Hello, Alice!", got: true, matcher: :eql, negate: false, level: :MUST, valid: true)
|
72
73
|
greeting # => "Hello, Alice!"
|
73
74
|
```
|
74
75
|
|
75
|
-
|
76
|
-
|
77
|
-
There are two cases:
|
78
|
-
|
79
|
-
* when an expectation is `true`, an instance of `Spectus::Result::Pass` is returned;
|
80
|
-
* when an expectation is `false`, an instance of `Spectus::Result::Fail` is raised.
|
76
|
+
Example of test in isolation:
|
81
77
|
|
82
|
-
|
78
|
+
```ruby
|
79
|
+
include Spectus
|
80
|
+
greeting = "Hello, world!"
|
81
|
+
it { greeting.gsub!("world", "Alice") }.MUST! eql "Hello, Alice!"
|
82
|
+
# => Spectus::Result::Pass(actual: "Hello, Alice!", error: nil, expected: "Hello, Alice!", got: true, matcher: :eql, negate: false, level: :MUST, valid: true)
|
83
|
+
greeting # => "Hello, world!"
|
84
|
+
```
|
83
85
|
|
84
86
|
## Usage
|
85
87
|
|
@@ -89,24 +91,24 @@ To begin with, let's include __Spectus__:
|
|
89
91
|
include Spectus
|
90
92
|
```
|
91
93
|
|
92
|
-
### Absolute
|
94
|
+
### Absolute Requirement
|
93
95
|
|
94
|
-
Given the
|
96
|
+
Given the "`ルビー`" object, when it receives `valid_encoding?` method, then it **MUST** be `true`:
|
95
97
|
|
96
98
|
```ruby
|
97
|
-
it {
|
98
|
-
# =>
|
99
|
+
it { "ルビー".valid_encoding? }.MUST be_true
|
100
|
+
# => Spectus::Result::Pass(actual: true, error: nil, expected: nil, got: true, matcher: :be_true, negate: false, level: :MUST, valid: true)
|
99
101
|
```
|
100
102
|
|
101
103
|
The result of the test shows that the spec passed.
|
102
104
|
|
103
|
-
### Absolute
|
105
|
+
### Absolute Prohibition
|
104
106
|
|
105
|
-
Given the `
|
107
|
+
Given the "`foo`" object, when it receives `length` method, then it **MUST NOT** raise the `NoMethodError` exception:
|
106
108
|
|
107
109
|
```ruby
|
108
|
-
it {
|
109
|
-
# =>
|
110
|
+
it { "foo".length }.MUST_NOT raise_exception NoMethodError
|
111
|
+
# => Spectus::Result::Pass(actual: 3, error: nil, expected: NoMethodError, got: true, matcher: :raise_exception, negate: true, level: :MUST, valid: true)
|
110
112
|
```
|
111
113
|
|
112
114
|
The result of the test shows that the spec passed.
|
@@ -117,74 +119,63 @@ Given the `BasicObject` object, when it receives `superclass` method, then it **
|
|
117
119
|
|
118
120
|
```ruby
|
119
121
|
it { BasicObject.superclass }.SHOULD equal NilClass
|
120
|
-
# =>
|
122
|
+
# => Spectus::Result::Pass(actual: nil, error: nil, expected: NilClass, got: false, matcher: :equal, negate: false, level: :SHOULD, valid: false)
|
121
123
|
```
|
122
124
|
|
123
125
|
Instead of the expected `NilClass` class, its sole instance (which is `nil`) was returned.
|
124
126
|
However, because there isn't any exception, the result of the test shows that the spec passed.
|
125
127
|
|
126
|
-
### Not
|
128
|
+
### Not Recommended
|
127
129
|
|
128
|
-
Given the `
|
130
|
+
Given the "`1`" object, when it receives `+(1)` method, then it **SHOULD NOT** return the "`11`" value:
|
129
131
|
|
130
132
|
```ruby
|
131
|
-
it {
|
132
|
-
# Spectus::Result::Fail:
|
133
|
-
# from (irb):5
|
134
|
-
# from ./bin/console:7:in `<main>'
|
133
|
+
it { "1" + 1 }.SHOULD_NOT eql "11"
|
134
|
+
# raise Spectus::Result::Fail(actual: nil, error: #<TypeError: no implicit conversion of Integer into String>, expected: "11", got: nil, matcher: :eql, negate: true, level: :SHOULD, valid: false)
|
135
135
|
```
|
136
136
|
|
137
137
|
There was a `TypeError` exception, the result of the test shows that the spec failed.
|
138
138
|
|
139
139
|
### Optional
|
140
140
|
|
141
|
-
Given the `
|
141
|
+
Given the "`foo`" object, when it receives `blank?` method, then it **MAY** be `false`:
|
142
142
|
|
143
143
|
```ruby
|
144
|
-
it {
|
145
|
-
# =>
|
144
|
+
it { "foo".blank? }.MAY be_false
|
145
|
+
# => Spectus::Result::Pass(actual: nil, error: #<NoMethodError: undefined method `blank?' for "foo":String>, expected: nil, got: nil, matcher: :be_false, negate: false, level: :MAY, valid: false)
|
146
146
|
```
|
147
147
|
|
148
|
-
The optional `blank?` method is not implemented (unlike in [Ruby on Rails](
|
148
|
+
The optional `blank?` method is not implemented (unlike in [Ruby on Rails](https://api.rubyonrails.org/classes/Object.html#method-i-blank-3F), for instance), so the result of the test shows that the spec passed.
|
149
149
|
|
150
|
-
|
150
|
+
### More Examples
|
151
151
|
|
152
|
-
|
153
|
-
|
154
|
-
Although these checksums do not prevent malicious users from tampering with a
|
155
|
-
built Gem they can be used for basic integrity verification purposes.
|
152
|
+
A full list of unit tests can be viewed (and executed) here:
|
153
|
+
[./test.rb](https://github.com/fixrb/spectus/blob/main/test.rb)
|
156
154
|
|
157
|
-
|
158
|
-
example:
|
155
|
+
## Contact
|
159
156
|
|
160
|
-
|
161
|
-
|
157
|
+
* Home page: https://github.com/fixrb/spectus
|
158
|
+
* Bugs/issues: https://github.com/fixrb/spectus/issues
|
162
159
|
|
163
160
|
## Versioning
|
164
161
|
|
165
|
-
__Spectus__ follows [Semantic Versioning 2.0](
|
162
|
+
__Spectus__ follows [Semantic Versioning 2.0](https://semver.org/).
|
166
163
|
|
167
|
-
##
|
164
|
+
## License
|
168
165
|
|
169
|
-
|
170
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
171
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
172
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
173
|
-
5. Create a new Pull Request
|
166
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
174
167
|
|
175
|
-
|
168
|
+
***
|
176
169
|
|
177
|
-
|
170
|
+
<p>
|
171
|
+
This project is sponsored by:<br />
|
172
|
+
<a href="https://sashite.com/"><img
|
173
|
+
src="https://github.com/fixrb/spectus/raw/main/img/sashite.png"
|
174
|
+
alt="Sashite" /></a>
|
175
|
+
</p>
|
178
176
|
|
179
177
|
[gem]: https://rubygems.org/gems/spectus
|
180
178
|
[travis]: https://travis-ci.org/fixrb/spectus
|
181
179
|
[codeclimate]: https://codeclimate.com/github/fixrb/spectus
|
182
|
-
[
|
183
|
-
[
|
184
|
-
[rubydoc]: http://rubydoc.info/gems/spectus/frames
|
185
|
-
|
186
|
-
***
|
187
|
-
|
188
|
-
This project is sponsored by:
|
189
|
-
|
190
|
-
[](https://sashite.com/)
|
180
|
+
[inchpages]: https://inch-ci.org/github/fixrb/spectus
|
181
|
+
[rubydoc]: https://rubydoc.info/gems/spectus/frames
|
data/lib/spectus.rb
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "matchi/helper"
|
4
4
|
|
5
5
|
# Namespace for the Spectus library.
|
6
6
|
#
|
7
|
-
# @api public
|
8
|
-
#
|
9
7
|
# @example It MUST equal 42.
|
10
8
|
# require 'spectus'
|
11
9
|
# it { 42 }.MUST equal 42 # => #<Spectus::Result::Pass...>
|
12
10
|
module Spectus
|
13
|
-
include
|
11
|
+
include ::Matchi::Helper
|
14
12
|
|
15
13
|
# Expectations are built with this method.
|
16
14
|
#
|
@@ -25,4 +23,4 @@ module Spectus
|
|
25
23
|
end
|
26
24
|
end
|
27
25
|
|
28
|
-
require_relative File.join(
|
26
|
+
require_relative File.join("spectus", "expectation_target")
|
data/lib/spectus/exam.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "defi"
|
4
|
+
|
5
|
+
module Spectus
|
6
|
+
# This class evaluate the expectation with the passed block.
|
7
|
+
class Exam
|
8
|
+
# Execute the untested code from the passed block against the matcher.
|
9
|
+
#
|
10
|
+
# rubocop:disable Lint/RescueException
|
11
|
+
#
|
12
|
+
# @param callable [#call] The callable object to test.
|
13
|
+
# @param isolation [Boolean] Compute actual in isolation?
|
14
|
+
# @param negate [Boolean] Positive or negative assertion?
|
15
|
+
# @param matcher [#matches?] The matcher.
|
16
|
+
def initialize(callable:, isolation:, negate:, matcher:)
|
17
|
+
@got = negate ^ matcher.matches? do
|
18
|
+
value = if isolation
|
19
|
+
send_call.to!(callable)
|
20
|
+
else
|
21
|
+
send_call.to(callable)
|
22
|
+
end
|
23
|
+
|
24
|
+
@actual = value.object
|
25
|
+
|
26
|
+
value.call
|
27
|
+
end
|
28
|
+
rescue ::Exception => e
|
29
|
+
@actual = nil
|
30
|
+
@exception = e
|
31
|
+
end
|
32
|
+
# rubocop:enable Lint/RescueException
|
33
|
+
|
34
|
+
# @return [#object_id] The actual value.
|
35
|
+
attr_reader :actual
|
36
|
+
|
37
|
+
# @return [Exception, nil] An exception.
|
38
|
+
attr_reader :exception
|
39
|
+
|
40
|
+
# @return [Boolean, nil] Report to the spec requirement level if the
|
41
|
+
# expectation is true or false.
|
42
|
+
attr_reader :got
|
43
|
+
|
44
|
+
# @return [Defi::Challenge] The challenge for the callable object.
|
45
|
+
def send_call
|
46
|
+
::Defi.send(:call)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Report to the spec requirement level if the test pass or fail.
|
50
|
+
#
|
51
|
+
# @return [Boolean] Report if the test pass or fail?
|
52
|
+
def valid?
|
53
|
+
exception.nil? ? got : false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -1,49 +1,49 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'defi'
|
4
|
-
|
5
3
|
module Spectus
|
6
4
|
# Wraps the target of an expectation.
|
7
5
|
#
|
8
|
-
# @api public
|
9
|
-
#
|
10
6
|
# @example
|
11
7
|
# it { actual value } # => ExpectationTarget wrapping the block
|
12
8
|
class ExpectationTarget
|
13
|
-
# Create a new
|
9
|
+
# Create a new expectation target
|
14
10
|
#
|
15
|
-
# @
|
16
|
-
|
17
|
-
|
18
|
-
def initialize(&subject)
|
19
|
-
@subject = subject
|
20
|
-
@challenges = [block_challenge]
|
11
|
+
# @param callable [Proc] The object to test.
|
12
|
+
def initialize(&callable)
|
13
|
+
@callable = callable
|
21
14
|
end
|
22
15
|
|
23
|
-
# rubocop:disable
|
24
|
-
# rubocop:disable Naming/UncommunicativeMethodParamName
|
16
|
+
# rubocop:disable Naming/MethodName
|
25
17
|
|
26
|
-
# @api public
|
27
|
-
#
|
28
18
|
# This word, or the terms "REQUIRED" or "SHALL", mean that the
|
29
19
|
# definition is an absolute requirement of the specification.
|
30
20
|
#
|
31
21
|
# @example _Absolute requirement_ definition
|
32
22
|
# it { 'foo'.upcase }.MUST eql 'FOO'
|
33
23
|
#
|
34
|
-
# @param
|
24
|
+
# @param matcher [#matches?] The matcher.
|
35
25
|
#
|
36
26
|
# @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
|
37
|
-
def MUST(
|
38
|
-
RequirementLevel::
|
27
|
+
def MUST(matcher)
|
28
|
+
RequirementLevel::Must.new(
|
29
|
+
callable: callable,
|
30
|
+
isolation: false,
|
31
|
+
negate: false,
|
32
|
+
matcher: matcher
|
33
|
+
).call
|
39
34
|
end
|
40
35
|
|
41
36
|
# @example _Absolute requirement_ definition with isolation
|
42
37
|
# it { 'foo'.upcase }.MUST! eql 'FOO'
|
43
38
|
#
|
44
39
|
# @see MUST
|
45
|
-
def MUST!(
|
46
|
-
RequirementLevel::
|
40
|
+
def MUST!(matcher)
|
41
|
+
RequirementLevel::Must.new(
|
42
|
+
callable: callable,
|
43
|
+
isolation: true,
|
44
|
+
negate: false,
|
45
|
+
matcher: matcher
|
46
|
+
).call
|
47
47
|
end
|
48
48
|
|
49
49
|
# This phrase, or the phrase "SHALL NOT", mean that the
|
@@ -52,19 +52,29 @@ module Spectus
|
|
52
52
|
# @example _Absolute prohibition_ definition
|
53
53
|
# it { 'foo'.size }.MUST_NOT equal 42
|
54
54
|
#
|
55
|
-
# @param
|
55
|
+
# @param matcher [#matches?] The matcher.
|
56
56
|
#
|
57
57
|
# @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
|
58
|
-
def MUST_NOT(
|
59
|
-
RequirementLevel::
|
58
|
+
def MUST_NOT(matcher)
|
59
|
+
RequirementLevel::Must.new(
|
60
|
+
callable: callable,
|
61
|
+
isolation: false,
|
62
|
+
negate: true,
|
63
|
+
matcher: matcher
|
64
|
+
).call
|
60
65
|
end
|
61
66
|
|
62
67
|
# @example _Absolute prohibition_ definition with isolation
|
63
68
|
# it { 'foo'.size }.MUST_NOT! equal 42
|
64
69
|
#
|
65
70
|
# @see MUST_NOT
|
66
|
-
def MUST_NOT!(
|
67
|
-
RequirementLevel::
|
71
|
+
def MUST_NOT!(matcher)
|
72
|
+
RequirementLevel::Must.new(
|
73
|
+
callable: callable,
|
74
|
+
isolation: true,
|
75
|
+
negate: true,
|
76
|
+
matcher: matcher
|
77
|
+
).call
|
68
78
|
end
|
69
79
|
|
70
80
|
# This word, or the adjective "RECOMMENDED", mean that there
|
@@ -75,19 +85,29 @@ module Spectus
|
|
75
85
|
# @example _Recommended_ definition
|
76
86
|
# it { 'foo'.valid_encoding? }.SHOULD equal true
|
77
87
|
#
|
78
|
-
# @param
|
88
|
+
# @param matcher [#matches?] The matcher.
|
79
89
|
#
|
80
90
|
# @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
|
81
|
-
def SHOULD(
|
82
|
-
RequirementLevel::
|
91
|
+
def SHOULD(matcher)
|
92
|
+
RequirementLevel::Should.new(
|
93
|
+
callable: callable,
|
94
|
+
isolation: false,
|
95
|
+
negate: false,
|
96
|
+
matcher: matcher
|
97
|
+
).call
|
83
98
|
end
|
84
99
|
|
85
100
|
# @example _Recommended_ definition with isolation
|
86
101
|
# it { 'foo'.valid_encoding? }.SHOULD! equal true
|
87
102
|
#
|
88
103
|
# @see SHOULD
|
89
|
-
def SHOULD!(
|
90
|
-
RequirementLevel::
|
104
|
+
def SHOULD!(matcher)
|
105
|
+
RequirementLevel::Should.new(
|
106
|
+
callable: callable,
|
107
|
+
isolation: true,
|
108
|
+
negate: false,
|
109
|
+
matcher: matcher
|
110
|
+
).call
|
91
111
|
end
|
92
112
|
|
93
113
|
# This phrase, or the phrase "NOT RECOMMENDED" mean that
|
@@ -99,19 +119,29 @@ module Spectus
|
|
99
119
|
# @example _Not recommended_ definition
|
100
120
|
# it { ''.blank? }.SHOULD_NOT raise_exception NoMethodError
|
101
121
|
#
|
102
|
-
# @param
|
122
|
+
# @param matcher [#matches?] The matcher.
|
103
123
|
#
|
104
124
|
# @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
|
105
|
-
def SHOULD_NOT(
|
106
|
-
RequirementLevel::
|
125
|
+
def SHOULD_NOT(matcher)
|
126
|
+
RequirementLevel::Should.new(
|
127
|
+
callable: callable,
|
128
|
+
isolation: false,
|
129
|
+
negate: true,
|
130
|
+
matcher: matcher
|
131
|
+
).call
|
107
132
|
end
|
108
133
|
|
109
134
|
# @example _Not recommended_ definition with isolation
|
110
135
|
# it { ''.blank? }.SHOULD_NOT! raise_exception NoMethodError
|
111
136
|
#
|
112
137
|
# @see SHOULD_NOT
|
113
|
-
def SHOULD_NOT!(
|
114
|
-
RequirementLevel::
|
138
|
+
def SHOULD_NOT!(matcher)
|
139
|
+
RequirementLevel::Should.new(
|
140
|
+
callable: callable,
|
141
|
+
isolation: true,
|
142
|
+
negate: true,
|
143
|
+
matcher: matcher
|
144
|
+
).call
|
115
145
|
end
|
116
146
|
|
117
147
|
# This word, or the adjective "OPTIONAL", mean that an item is
|
@@ -129,53 +159,40 @@ module Spectus
|
|
129
159
|
# @example _Optional_ definition
|
130
160
|
# it { 'foo'.bar }.MAY match /^foo$/
|
131
161
|
#
|
132
|
-
# @param
|
162
|
+
# @param matcher [#matches?] The matcher.
|
133
163
|
#
|
134
164
|
# @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
|
135
|
-
def MAY(
|
136
|
-
RequirementLevel::
|
165
|
+
def MAY(matcher)
|
166
|
+
RequirementLevel::May.new(
|
167
|
+
callable: callable,
|
168
|
+
isolation: false,
|
169
|
+
negate: false,
|
170
|
+
matcher: matcher
|
171
|
+
).call
|
137
172
|
end
|
138
173
|
|
139
174
|
# @example _Optional_ definition with isolation
|
140
175
|
# it { 'foo'.bar }.MAY! match /^foo$/
|
141
176
|
#
|
142
177
|
# @see MAY
|
143
|
-
def MAY!(
|
144
|
-
RequirementLevel::
|
178
|
+
def MAY!(matcher)
|
179
|
+
RequirementLevel::May.new(
|
180
|
+
callable: callable,
|
181
|
+
isolation: true,
|
182
|
+
negate: false,
|
183
|
+
matcher: matcher
|
184
|
+
).call
|
145
185
|
end
|
146
186
|
|
147
|
-
# rubocop:enable
|
148
|
-
# rubocop:enable Naming/UncommunicativeMethodParamName
|
187
|
+
# rubocop:enable Naming/MethodName
|
149
188
|
|
150
|
-
|
189
|
+
protected
|
151
190
|
|
152
|
-
#
|
153
|
-
|
154
|
-
# @return [BasicObject] The front object to be tested.
|
155
|
-
attr_reader :subject
|
156
|
-
private :subject
|
157
|
-
|
158
|
-
# @!attribute [r] challenges
|
159
|
-
#
|
160
|
-
# @return [Array] The challenges to call on the subject.
|
161
|
-
attr_reader :challenges
|
162
|
-
private :challenges
|
163
|
-
|
164
|
-
# rubocop:enable Style/AccessModifierDeclarations
|
165
|
-
|
166
|
-
private
|
167
|
-
|
168
|
-
# The first default challenge for blocks.
|
169
|
-
#
|
170
|
-
# @since 2.10.0
|
171
|
-
#
|
172
|
-
# @return [Defi] The challenge for blocks.
|
173
|
-
def block_challenge
|
174
|
-
::Defi.send(:call)
|
175
|
-
end
|
191
|
+
# @return [#call] The callable object to test.
|
192
|
+
attr_reader :callable
|
176
193
|
end
|
177
194
|
end
|
178
195
|
|
179
|
-
require_relative File.join(
|
180
|
-
require_relative File.join(
|
181
|
-
require_relative File.join(
|
196
|
+
require_relative File.join("requirement_level", "must")
|
197
|
+
require_relative File.join("requirement_level", "should")
|
198
|
+
require_relative File.join("requirement_level", "may")
|