spectus 3.1.1 → 3.3.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/LICENSE.md +1 -1
- data/README.md +38 -67
- data/lib/spectus.rb +2 -2
- data/lib/spectus/exam.rb +1 -1
- data/lib/spectus/expectation_target.rb +22 -18
- data/lib/spectus/requirement_level/base.rb +9 -24
- data/lib/spectus/requirement_level/may.rb +1 -1
- data/lib/spectus/requirement_level/must.rb +1 -1
- data/lib/spectus/requirement_level/should.rb +1 -1
- data/lib/spectus/result.rb +18 -0
- data/lib/spectus/result/fail.rb +2 -67
- data/lib/spectus/result/pass.rb +2 -76
- metadata +69 -27
- data/lib/spectus/result/common.rb +0 -174
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91207456a98d2640cdeb0dbf52ce04c532f72060c904aa15474f2eb86eb67481
|
4
|
+
data.tar.gz: 26e7073807fa4bb734eb8e349682c41d2b23bd83c11012818ce443b5615089e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '018827c15c82d74b1af062e57768809c89f6ad18e2b389b4150ae318f12fdbadd6709eff232483d67a7e9aa0234d008ade347503066b78c522f7291fa515f809'
|
7
|
+
data.tar.gz: a57c6cfaf4b7292ca768fc309e61a025d85de984cf62af8f0a88c0b37d58189732babf03e3a8a6eed208838518af088d1d53448cc5c6c71842db1e52f0c60ab7
|
data/LICENSE.md
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# Spectus
|
2
2
|
|
3
|
-
[][travis]
|
4
4
|
[][codeclimate]
|
5
5
|
[][gem]
|
6
|
-
[][inchpages]
|
7
7
|
[][rubydoc]
|
8
8
|
|
9
9
|
> Expectation library with [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt)'s requirement levels 🚥
|
@@ -13,7 +13,7 @@
|
|
13
13
|
Add this line to your application's Gemfile:
|
14
14
|
|
15
15
|
```ruby
|
16
|
-
gem
|
16
|
+
gem "spectus"
|
17
17
|
```
|
18
18
|
|
19
19
|
And then execute:
|
@@ -24,57 +24,6 @@ Or install it yourself as:
|
|
24
24
|
|
25
25
|
$ gem install spectus
|
26
26
|
|
27
|
-
## Expectation
|
28
|
-
|
29
|
-
An expectation is an assertion that is either `true` or `false`.
|
30
|
-
|
31
|
-
There are several scenarios:
|
32
|
-
|
33
|
-
| Requirement levels | **MUST** | **SHOULD** | **MAY** |
|
34
|
-
| ------------------------- | -------- | ---------- | ------- |
|
35
|
-
| Implemented & Matched | `true` | `true` | `true` |
|
36
|
-
| Implemented & Not matched | `false` | `true` | `false` |
|
37
|
-
| Implemented & Exception | `false` | `false` | `false` |
|
38
|
-
| Not implemented | `false` | `false` | `true` |
|
39
|
-
|
40
|
-
Thus,
|
41
|
-
|
42
|
-
* when an expectation is `true`, a `Spectus::Result::Pass` instance is returned;
|
43
|
-
* when an expectation is `false`, a `Spectus::Result::Fail` exception is raised.
|
44
|
-
|
45
|
-
Both results share a common interface, and can be classified respectively as:
|
46
|
-
|
47
|
-
* a ✅ _success_, a ⚠️ _warning_ or an 💡 _info_;
|
48
|
-
* a ❌ _failure_ or an 💥 _error_.
|
49
|
-
|
50
|
-
## Code Isolation
|
51
|
-
|
52
|
-
When executing expectations, side-effects may occur.
|
53
|
-
Because they may or may not be desired, each requirement level has 2 versions:
|
54
|
-
|
55
|
-
* if it does not end with `!`, its test is performed without isolation;
|
56
|
-
* if it ends with `!`, its test is performed in isolation.
|
57
|
-
|
58
|
-
Example of test without isolation:
|
59
|
-
|
60
|
-
```ruby
|
61
|
-
include Spectus
|
62
|
-
greeting = 'Hello, world!'
|
63
|
-
it { greeting.gsub!('world', 'Alice') }.MUST eql 'Hello, Alice!'
|
64
|
-
# => Spectus::Result::Pass(actual: "Hello, Alice!", error: nil, expected: "Hello, Alice!", got: true, matcher: :eql, negate: false, level: :MUST, valid: true)
|
65
|
-
greeting # => "Hello, Alice!"
|
66
|
-
```
|
67
|
-
|
68
|
-
Example of test in isolation:
|
69
|
-
|
70
|
-
```ruby
|
71
|
-
include Spectus
|
72
|
-
greeting = 'Hello, world!'
|
73
|
-
it { greeting.gsub!('world', 'Alice') }.MUST! eql 'Hello, Alice!'
|
74
|
-
# => Spectus::Result::Pass(actual: "Hello, Alice!", error: nil, expected: "Hello, Alice!", got: true, matcher: :eql, negate: false, level: :MUST, valid: true)
|
75
|
-
greeting # => "Hello, world!"
|
76
|
-
```
|
77
|
-
|
78
27
|
## Usage
|
79
28
|
|
80
29
|
To begin with, let's include __Spectus__:
|
@@ -88,7 +37,7 @@ include Spectus
|
|
88
37
|
Given the "`ルビー`" object, when it receives `valid_encoding?` method, then it **MUST** be `true`:
|
89
38
|
|
90
39
|
```ruby
|
91
|
-
it {
|
40
|
+
it { "ルビー".valid_encoding? }.MUST be_true
|
92
41
|
# => Spectus::Result::Pass(actual: true, error: nil, expected: nil, got: true, matcher: :be_true, negate: false, level: :MUST, valid: true)
|
93
42
|
```
|
94
43
|
|
@@ -99,7 +48,7 @@ The result of the test shows that the spec passed.
|
|
99
48
|
Given the "`foo`" object, when it receives `length` method, then it **MUST NOT** raise the `NoMethodError` exception:
|
100
49
|
|
101
50
|
```ruby
|
102
|
-
it {
|
51
|
+
it { "foo".length }.MUST_NOT raise_exception NoMethodError
|
103
52
|
# => Spectus::Result::Pass(actual: 3, error: nil, expected: NoMethodError, got: true, matcher: :raise_exception, negate: true, level: :MUST, valid: true)
|
104
53
|
```
|
105
54
|
|
@@ -122,7 +71,7 @@ However, because there isn't any exception, the result of the test shows that th
|
|
122
71
|
Given the "`1`" object, when it receives `+(1)` method, then it **SHOULD NOT** return the "`11`" value:
|
123
72
|
|
124
73
|
```ruby
|
125
|
-
it {
|
74
|
+
it { "1" + 1 }.SHOULD_NOT eql "11"
|
126
75
|
# 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)
|
127
76
|
```
|
128
77
|
|
@@ -133,7 +82,7 @@ There was a `TypeError` exception, the result of the test shows that the spec fa
|
|
133
82
|
Given the "`foo`" object, when it receives `blank?` method, then it **MAY** be `false`:
|
134
83
|
|
135
84
|
```ruby
|
136
|
-
it {
|
85
|
+
it { "foo".blank? }.MAY be_false
|
137
86
|
# => 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)
|
138
87
|
```
|
139
88
|
|
@@ -141,20 +90,42 @@ The optional `blank?` method is not implemented (unlike in [Ruby on Rails](https
|
|
141
90
|
|
142
91
|
### More Examples
|
143
92
|
|
144
|
-
|
145
|
-
[test.rb](https://github.com/fixrb/spectus/blob/
|
93
|
+
A full list of unit tests can be viewed (and executed) here:
|
94
|
+
[./test.rb](https://github.com/fixrb/spectus/blob/main/test.rb)
|
95
|
+
|
96
|
+
## Code Isolation
|
97
|
+
|
98
|
+
When executing expectations, side-effects may occur.
|
99
|
+
Because they may or may not be desired, each requirement level has 2 versions:
|
100
|
+
|
101
|
+
* if it does not end with `!`, its test is performed without isolation;
|
102
|
+
* if it ends with `!`, its test is performed in isolation.
|
103
|
+
|
104
|
+
Example of test without isolation:
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
include Spectus
|
108
|
+
greeting = "Hello, world!"
|
109
|
+
it { greeting.gsub!("world", "Alice") }.MUST eql "Hello, Alice!"
|
110
|
+
# => Spectus::Result::Pass(actual: "Hello, Alice!", error: nil, expected: "Hello, Alice!", got: true, matcher: :eql, negate: false, level: :MUST, valid: true)
|
111
|
+
greeting # => "Hello, Alice!"
|
112
|
+
```
|
113
|
+
|
114
|
+
Example of test in isolation:
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
include Spectus
|
118
|
+
greeting = "Hello, world!"
|
119
|
+
it { greeting.gsub!("world", "Alice") }.MUST! eql "Hello, Alice!"
|
120
|
+
# => Spectus::Result::Pass(actual: "Hello, Alice!", error: nil, expected: "Hello, Alice!", got: true, matcher: :eql, negate: false, level: :MUST, valid: true)
|
121
|
+
greeting # => "Hello, world!"
|
122
|
+
```
|
146
123
|
|
147
124
|
## Contact
|
148
125
|
|
149
126
|
* Home page: https://github.com/fixrb/spectus
|
150
127
|
* Bugs/issues: https://github.com/fixrb/spectus/issues
|
151
128
|
|
152
|
-
## Rubies
|
153
|
-
|
154
|
-
* [MRI](https://www.ruby-lang.org/)
|
155
|
-
* [Rubinius](https://rubinius.com/)
|
156
|
-
* [JRuby](https://www.jruby.org/)
|
157
|
-
|
158
129
|
## Versioning
|
159
130
|
|
160
131
|
__Spectus__ follows [Semantic Versioning 2.0](https://semver.org/).
|
@@ -168,7 +139,7 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
168
139
|
<p>
|
169
140
|
This project is sponsored by:<br />
|
170
141
|
<a href="https://sashite.com/"><img
|
171
|
-
src="https://github.com/fixrb/spectus/raw/
|
142
|
+
src="https://github.com/fixrb/spectus/raw/main/img/sashite.png"
|
172
143
|
alt="Sashite" /></a>
|
173
144
|
</p>
|
174
145
|
|
data/lib/spectus.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "matchi/helper"
|
4
4
|
|
5
5
|
# Namespace for the Spectus library.
|
6
6
|
#
|
@@ -23,4 +23,4 @@ module Spectus
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
require_relative File.join(
|
26
|
+
require_relative File.join("spectus", "expectation_target")
|
data/lib/spectus/exam.rb
CHANGED
@@ -19,11 +19,12 @@ module Spectus
|
|
19
19
|
# definition is an absolute requirement of the specification.
|
20
20
|
#
|
21
21
|
# @example _Absolute requirement_ definition
|
22
|
-
# it {
|
22
|
+
# it { "foo".upcase }.MUST eql 'FOO'
|
23
23
|
#
|
24
24
|
# @param matcher [#matches?] The matcher.
|
25
25
|
#
|
26
|
-
# @return [Result::Fail, Result::Pass] Report if the spec
|
26
|
+
# @return [Spectus::Result::Fail, Spectus::Result::Pass] Report if the spec
|
27
|
+
# pass or fail.
|
27
28
|
def MUST(matcher)
|
28
29
|
RequirementLevel::Must.new(
|
29
30
|
callable: callable,
|
@@ -34,7 +35,7 @@ module Spectus
|
|
34
35
|
end
|
35
36
|
|
36
37
|
# @example _Absolute requirement_ definition with isolation
|
37
|
-
# it {
|
38
|
+
# it { "foo".upcase }.MUST! eql 'FOO'
|
38
39
|
#
|
39
40
|
# @see MUST
|
40
41
|
def MUST!(matcher)
|
@@ -50,11 +51,12 @@ module Spectus
|
|
50
51
|
# definition is an absolute prohibition of the specification.
|
51
52
|
#
|
52
53
|
# @example _Absolute prohibition_ definition
|
53
|
-
# it {
|
54
|
+
# it { "foo".size }.MUST_NOT equal 42
|
54
55
|
#
|
55
56
|
# @param matcher [#matches?] The matcher.
|
56
57
|
#
|
57
|
-
# @return [Result::Fail, Result::Pass] Report if the spec
|
58
|
+
# @return [Spectus::Result::Fail, Spectus::Result::Pass] Report if the spec
|
59
|
+
# pass or fail.
|
58
60
|
def MUST_NOT(matcher)
|
59
61
|
RequirementLevel::Must.new(
|
60
62
|
callable: callable,
|
@@ -65,7 +67,7 @@ module Spectus
|
|
65
67
|
end
|
66
68
|
|
67
69
|
# @example _Absolute prohibition_ definition with isolation
|
68
|
-
# it {
|
70
|
+
# it { "foo".size }.MUST_NOT! equal 42
|
69
71
|
#
|
70
72
|
# @see MUST_NOT
|
71
73
|
def MUST_NOT!(matcher)
|
@@ -83,11 +85,12 @@ module Spectus
|
|
83
85
|
# carefully weighed before choosing a different course.
|
84
86
|
#
|
85
87
|
# @example _Recommended_ definition
|
86
|
-
# it {
|
88
|
+
# it { "foo".valid_encoding? }.SHOULD equal true
|
87
89
|
#
|
88
90
|
# @param matcher [#matches?] The matcher.
|
89
91
|
#
|
90
|
-
# @return [Result::Fail, Result::Pass] Report if the spec
|
92
|
+
# @return [Spectus::Result::Fail, Spectus::Result::Pass] Report if the spec
|
93
|
+
# pass or fail.
|
91
94
|
def SHOULD(matcher)
|
92
95
|
RequirementLevel::Should.new(
|
93
96
|
callable: callable,
|
@@ -98,7 +101,7 @@ module Spectus
|
|
98
101
|
end
|
99
102
|
|
100
103
|
# @example _Recommended_ definition with isolation
|
101
|
-
# it {
|
104
|
+
# it { "foo".valid_encoding? }.SHOULD! equal true
|
102
105
|
#
|
103
106
|
# @see SHOULD
|
104
107
|
def SHOULD!(matcher)
|
@@ -117,11 +120,12 @@ module Spectus
|
|
117
120
|
# before implementing any behavior described with this label.
|
118
121
|
#
|
119
122
|
# @example _Not recommended_ definition
|
120
|
-
# it {
|
123
|
+
# it { "".blank? }.SHOULD_NOT raise_exception NoMethodError
|
121
124
|
#
|
122
125
|
# @param matcher [#matches?] The matcher.
|
123
126
|
#
|
124
|
-
# @return [Result::Fail, Result::Pass] Report if the spec
|
127
|
+
# @return [Spectus::Result::Fail, Spectus::Result::Pass] Report if the spec
|
128
|
+
# pass or fail.
|
125
129
|
def SHOULD_NOT(matcher)
|
126
130
|
RequirementLevel::Should.new(
|
127
131
|
callable: callable,
|
@@ -132,7 +136,7 @@ module Spectus
|
|
132
136
|
end
|
133
137
|
|
134
138
|
# @example _Not recommended_ definition with isolation
|
135
|
-
# it {
|
139
|
+
# it { "".blank? }.SHOULD_NOT! raise_exception NoMethodError
|
136
140
|
#
|
137
141
|
# @see SHOULD_NOT
|
138
142
|
def SHOULD_NOT!(matcher)
|
@@ -157,11 +161,11 @@ module Spectus
|
|
157
161
|
# option provides.)
|
158
162
|
#
|
159
163
|
# @example _Optional_ definition
|
160
|
-
# it {
|
164
|
+
# it { "foo".bar }.MAY match /^foo$/
|
161
165
|
#
|
162
166
|
# @param matcher [#matches?] The matcher.
|
163
167
|
#
|
164
|
-
# @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
|
168
|
+
# @return [Spectus::Result::Fail, Spectus::Result::Pass] Report if the spec pass or fail.
|
165
169
|
def MAY(matcher)
|
166
170
|
RequirementLevel::May.new(
|
167
171
|
callable: callable,
|
@@ -172,7 +176,7 @@ module Spectus
|
|
172
176
|
end
|
173
177
|
|
174
178
|
# @example _Optional_ definition with isolation
|
175
|
-
# it {
|
179
|
+
# it { "foo".bar }.MAY! match /^foo$/
|
176
180
|
#
|
177
181
|
# @see MAY
|
178
182
|
def MAY!(matcher)
|
@@ -193,6 +197,6 @@ module Spectus
|
|
193
197
|
end
|
194
198
|
end
|
195
199
|
|
196
|
-
require_relative File.join(
|
197
|
-
require_relative File.join(
|
198
|
-
require_relative File.join(
|
200
|
+
require_relative File.join("requirement_level", "must")
|
201
|
+
require_relative File.join("requirement_level", "should")
|
202
|
+
require_relative File.join("requirement_level", "may")
|
@@ -32,26 +32,10 @@ module Spectus
|
|
32
32
|
|
33
33
|
# The result of the expectation.
|
34
34
|
#
|
35
|
-
# @
|
35
|
+
# @raise [Spectus::Result::Fail] The expectation is `false`.
|
36
|
+
# @return [Spectus::Result::Pass] The expectation is `true`.
|
36
37
|
def call
|
37
|
-
pass?
|
38
|
-
end
|
39
|
-
|
40
|
-
protected
|
41
|
-
|
42
|
-
# @return [Result::Pass] A passed spec result.
|
43
|
-
def pass!
|
44
|
-
Result::Pass.new(**details)
|
45
|
-
end
|
46
|
-
|
47
|
-
# @raise [Result::Fail] A failed spec result.
|
48
|
-
def fail!
|
49
|
-
raise Result::Fail.new(**details)
|
50
|
-
end
|
51
|
-
|
52
|
-
# @return [Hash] List of parameters.
|
53
|
-
def details
|
54
|
-
{
|
38
|
+
Result.call(pass?).with(
|
55
39
|
actual: exam.actual,
|
56
40
|
error: exam.exception,
|
57
41
|
expected: matcher.expected,
|
@@ -60,12 +44,14 @@ module Spectus
|
|
60
44
|
valid: exam.valid?,
|
61
45
|
matcher: matcher.class.to_sym,
|
62
46
|
level: level
|
63
|
-
|
47
|
+
)
|
64
48
|
end
|
65
49
|
|
50
|
+
protected
|
51
|
+
|
66
52
|
# @return [Symbol] The requirement level.
|
67
53
|
def level
|
68
|
-
self.class.name.split(
|
54
|
+
self.class.name.split("::").fetch(-1).upcase.to_sym
|
69
55
|
end
|
70
56
|
|
71
57
|
# @note The boolean comparison between the actual value and the expected
|
@@ -79,6 +65,5 @@ module Spectus
|
|
79
65
|
end
|
80
66
|
end
|
81
67
|
|
82
|
-
require_relative File.join(
|
83
|
-
require_relative File.join(
|
84
|
-
require_relative File.join('..', 'result', 'pass')
|
68
|
+
require_relative File.join("..", "exam")
|
69
|
+
require_relative File.join("..", "result")
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spectus
|
4
|
+
# Namespace for the results.
|
5
|
+
module Result
|
6
|
+
# @param is_passed [Boolean] The value of an assertion.
|
7
|
+
# @return [Class<Spectus::Result::Pass>, Class<Spectus::Result::Fail>] The
|
8
|
+
# class of the result.
|
9
|
+
# @example Get the pass class result.
|
10
|
+
# call(true) # => Pass
|
11
|
+
def self.call(is_passed)
|
12
|
+
is_passed ? Pass : Fail
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
require_relative File.join("result", "fail")
|
18
|
+
require_relative File.join("result", "pass")
|
data/lib/spectus/result/fail.rb
CHANGED
@@ -1,76 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "expresenter/fail"
|
4
4
|
|
5
5
|
module Spectus
|
6
6
|
module Result
|
7
7
|
# The class that is responsible for reporting that the expectation is false.
|
8
|
-
class Fail < ::
|
9
|
-
include Common
|
10
|
-
|
11
|
-
# Did the test fail?
|
12
|
-
#
|
13
|
-
# @return [Boolean] The spec passed or failed?
|
14
|
-
def failed?
|
15
|
-
true
|
16
|
-
end
|
17
|
-
|
18
|
-
# Did the test pass?
|
19
|
-
#
|
20
|
-
# @return [Boolean] The spec passed or failed?
|
21
|
-
def passed?
|
22
|
-
!failed?
|
23
|
-
end
|
24
|
-
|
25
|
-
# The state of failure.
|
26
|
-
#
|
27
|
-
# @return [Boolean] The test was a failure?
|
28
|
-
def failure?
|
29
|
-
!error?
|
30
|
-
end
|
31
|
-
|
32
|
-
# The state of info.
|
33
|
-
#
|
34
|
-
# @return [Boolean] The test was an info?
|
35
|
-
def info?
|
36
|
-
false
|
37
|
-
end
|
38
|
-
|
39
|
-
# The state of warning.
|
40
|
-
#
|
41
|
-
# @return [Boolean] The test was a warning?
|
42
|
-
def warning?
|
43
|
-
false
|
44
|
-
end
|
45
|
-
|
46
|
-
# Identify the state of the result.
|
47
|
-
#
|
48
|
-
# @return [Symbol] The identifier of the state.
|
49
|
-
def to_sym
|
50
|
-
failure? ? :failure : :error
|
51
|
-
end
|
52
|
-
|
53
|
-
# Express the result with one char.
|
54
|
-
#
|
55
|
-
# @return [String] The char that identify the result.
|
56
|
-
def char
|
57
|
-
if failure?
|
58
|
-
'F'
|
59
|
-
else
|
60
|
-
'E'
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
# Express the result with one emoji.
|
65
|
-
#
|
66
|
-
# @return [String] The emoji that identify the result.
|
67
|
-
def emoji
|
68
|
-
if failure?
|
69
|
-
'❌'
|
70
|
-
else
|
71
|
-
'💥'
|
72
|
-
end
|
73
|
-
end
|
8
|
+
class Fail < ::Expresenter::Fail
|
74
9
|
end
|
75
10
|
end
|
76
11
|
end
|
data/lib/spectus/result/pass.rb
CHANGED
@@ -1,85 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "expresenter/pass"
|
4
4
|
|
5
5
|
module Spectus
|
6
6
|
module Result
|
7
7
|
# The class that is responsible for reporting that the expectation is true.
|
8
|
-
class Pass
|
9
|
-
include Common
|
10
|
-
|
11
|
-
alias message to_s
|
12
|
-
|
13
|
-
# Did the test fail?
|
14
|
-
#
|
15
|
-
# @return [Boolean] The spec passed or failed?
|
16
|
-
def failed?
|
17
|
-
false
|
18
|
-
end
|
19
|
-
|
20
|
-
# Did the test pass?
|
21
|
-
#
|
22
|
-
# @return [Boolean] The spec passed or failed?
|
23
|
-
def passed?
|
24
|
-
!failed?
|
25
|
-
end
|
26
|
-
|
27
|
-
# The state of failure.
|
28
|
-
#
|
29
|
-
# @return [Boolean] The test was a failure?
|
30
|
-
def failure?
|
31
|
-
false
|
32
|
-
end
|
33
|
-
|
34
|
-
# The state of info.
|
35
|
-
#
|
36
|
-
# @return [Boolean] The test was an info?
|
37
|
-
def info?
|
38
|
-
!error.nil?
|
39
|
-
end
|
40
|
-
|
41
|
-
# The state of warning.
|
42
|
-
#
|
43
|
-
# @return [Boolean] The test was a warning?
|
44
|
-
def warning?
|
45
|
-
got.equal?(false)
|
46
|
-
end
|
47
|
-
|
48
|
-
# Identify the state of the result.
|
49
|
-
#
|
50
|
-
# @return [Symbol] The identifier of the state.
|
51
|
-
def to_sym
|
52
|
-
return :success if success?
|
53
|
-
return :warning if warning?
|
54
|
-
|
55
|
-
:info
|
56
|
-
end
|
57
|
-
|
58
|
-
# Express the result with one char.
|
59
|
-
#
|
60
|
-
# @return [String] The char that identify the result.
|
61
|
-
def char
|
62
|
-
if success?
|
63
|
-
'.'
|
64
|
-
elsif warning?
|
65
|
-
'W'
|
66
|
-
else
|
67
|
-
'I'
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
# Express the result with one emoji.
|
72
|
-
#
|
73
|
-
# @return [String] The emoji that identify the result.
|
74
|
-
def emoji
|
75
|
-
if success?
|
76
|
-
'✅'
|
77
|
-
elsif warning?
|
78
|
-
'⚠️'
|
79
|
-
else
|
80
|
-
'💡'
|
81
|
-
end
|
82
|
-
end
|
8
|
+
class Pass < ::Expresenter::Pass
|
83
9
|
end
|
84
10
|
end
|
85
11
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spectus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.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:
|
11
|
+
date: 2021-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: defi
|
@@ -16,14 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.0.
|
19
|
+
version: 2.0.4
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 2.0.
|
26
|
+
version: 2.0.4
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: expresenter
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.1.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.1.0
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: matchi
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -42,46 +56,46 @@ dependencies:
|
|
42
56
|
name: brutal
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
|
-
- - "
|
59
|
+
- - ">="
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0
|
61
|
+
version: '0'
|
48
62
|
type: :development
|
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: '0
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: bundler
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
|
-
- - "
|
73
|
+
- - ">="
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
75
|
+
version: '0'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
|
-
- - "
|
80
|
+
- - ">="
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rake
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
|
-
- - "
|
87
|
+
- - ">="
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
89
|
+
version: '0'
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
|
-
- - "
|
94
|
+
- - ">="
|
81
95
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
|
-
name: rubocop
|
98
|
+
name: rubocop-md
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
101
|
- - ">="
|
@@ -108,34 +122,62 @@ dependencies:
|
|
108
122
|
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rubocop-rake
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rubocop-thread_safety
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
111
153
|
- !ruby/object:Gem::Dependency
|
112
154
|
name: simplecov
|
113
155
|
requirement: !ruby/object:Gem::Requirement
|
114
156
|
requirements:
|
115
|
-
- - "
|
157
|
+
- - ">="
|
116
158
|
- !ruby/object:Gem::Version
|
117
|
-
version: '0
|
159
|
+
version: '0'
|
118
160
|
type: :development
|
119
161
|
prerelease: false
|
120
162
|
version_requirements: !ruby/object:Gem::Requirement
|
121
163
|
requirements:
|
122
|
-
- - "
|
164
|
+
- - ">="
|
123
165
|
- !ruby/object:Gem::Version
|
124
|
-
version: '0
|
166
|
+
version: '0'
|
125
167
|
- !ruby/object:Gem::Dependency
|
126
168
|
name: yard
|
127
169
|
requirement: !ruby/object:Gem::Requirement
|
128
170
|
requirements:
|
129
|
-
- - "
|
171
|
+
- - ">="
|
130
172
|
- !ruby/object:Gem::Version
|
131
|
-
version: '0
|
173
|
+
version: '0'
|
132
174
|
type: :development
|
133
175
|
prerelease: false
|
134
176
|
version_requirements: !ruby/object:Gem::Requirement
|
135
177
|
requirements:
|
136
|
-
- - "
|
178
|
+
- - ">="
|
137
179
|
- !ruby/object:Gem::Version
|
138
|
-
version: '0
|
180
|
+
version: '0'
|
139
181
|
description: "Expectation library with RFC 2119's requirement levels \U0001F6A5"
|
140
182
|
email: contact@cyril.email
|
141
183
|
executables: []
|
@@ -151,7 +193,7 @@ files:
|
|
151
193
|
- lib/spectus/requirement_level/may.rb
|
152
194
|
- lib/spectus/requirement_level/must.rb
|
153
195
|
- lib/spectus/requirement_level/should.rb
|
154
|
-
- lib/spectus/result
|
196
|
+
- lib/spectus/result.rb
|
155
197
|
- lib/spectus/result/fail.rb
|
156
198
|
- lib/spectus/result/pass.rb
|
157
199
|
homepage: https://github.com/fixrb/spectus
|
@@ -173,7 +215,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
215
|
- !ruby/object:Gem::Version
|
174
216
|
version: '0'
|
175
217
|
requirements: []
|
176
|
-
rubygems_version: 3.1.
|
218
|
+
rubygems_version: 3.1.4
|
177
219
|
signing_key:
|
178
220
|
specification_version: 4
|
179
221
|
summary: "Expectation library with RFC 2119's requirement levels \U0001F6A5"
|
@@ -1,174 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Spectus
|
4
|
-
# Namespace for the results.
|
5
|
-
module Result
|
6
|
-
# Common collection of methods for Result's classes.
|
7
|
-
module Common
|
8
|
-
# @return [#object_id] Returned value by the challenged subject.
|
9
|
-
attr_reader :actual
|
10
|
-
|
11
|
-
# @return [Exception, nil] Any possible raised exception.
|
12
|
-
attr_reader :error
|
13
|
-
|
14
|
-
# @return [#object_id] The expected value.
|
15
|
-
attr_reader :expected
|
16
|
-
|
17
|
-
# @return [#object_id] The result of the boolean comparison between the
|
18
|
-
# actual value and the expected value through the matcher.
|
19
|
-
attr_reader :got
|
20
|
-
|
21
|
-
# @return [#object_id] The matcher.
|
22
|
-
attr_reader :matcher
|
23
|
-
|
24
|
-
# @return [:MUST, :SHOULD, :MAY] The requirement level of the expectation.
|
25
|
-
attr_reader :level
|
26
|
-
|
27
|
-
# Common initialize method.
|
28
|
-
#
|
29
|
-
# @param actual [#object_id] Returned value by the challenged subject.
|
30
|
-
# @param error [Exception, nil] Any possible raised exception.
|
31
|
-
# @param expected [#object_id] The expected value.
|
32
|
-
# @param got [Boolean, nil] The result of the boolean comparison
|
33
|
-
# between the actual value and the expected value through the matcher.
|
34
|
-
# @param negate [Boolean] Evaluated to a negative assertion?
|
35
|
-
# @param valid [Boolean] Report if the test was true or false?
|
36
|
-
# @param matcher [Symbol] The matcher.
|
37
|
-
# @param level [:MUST, :SHOULD, :MAY] The requirement level.
|
38
|
-
def initialize(actual:, error:, expected:, got:, negate:, valid:,
|
39
|
-
matcher:, level:)
|
40
|
-
|
41
|
-
@actual = actual
|
42
|
-
@error = error
|
43
|
-
@expected = expected
|
44
|
-
@got = got
|
45
|
-
@negate = negate
|
46
|
-
@valid = valid
|
47
|
-
@matcher = matcher
|
48
|
-
@level = level
|
49
|
-
|
50
|
-
super(to_s) if failed?
|
51
|
-
end
|
52
|
-
|
53
|
-
# The value of the negate instance variable.
|
54
|
-
#
|
55
|
-
# @return [Boolean] Evaluated to a negative assertion?
|
56
|
-
def negate?
|
57
|
-
@negate
|
58
|
-
end
|
59
|
-
|
60
|
-
# The state of error.
|
61
|
-
#
|
62
|
-
# @return [Boolean] The test raised an error?
|
63
|
-
def error?
|
64
|
-
!error.nil?
|
65
|
-
end
|
66
|
-
|
67
|
-
# The state of success.
|
68
|
-
#
|
69
|
-
# @return [Boolean] The test was a success?
|
70
|
-
def success?
|
71
|
-
got.equal?(true)
|
72
|
-
end
|
73
|
-
|
74
|
-
# The value of the boolean comparison between the actual value and the
|
75
|
-
# expected value.
|
76
|
-
#
|
77
|
-
# @return [Boolean] The test was true or false?
|
78
|
-
def valid?
|
79
|
-
@valid
|
80
|
-
end
|
81
|
-
|
82
|
-
# A string containing a human-readable representation of the result.
|
83
|
-
#
|
84
|
-
# @return [String] The human-readable representation of the result.
|
85
|
-
def inspect
|
86
|
-
"#{self.class}(actual: #{actual.inspect}, " \
|
87
|
-
"error: #{error.inspect}, " \
|
88
|
-
"expected: #{expected.inspect}, " \
|
89
|
-
"got: #{got.inspect}, " \
|
90
|
-
"matcher: #{matcher.inspect}, " \
|
91
|
-
"negate: #{negate?.inspect}, " \
|
92
|
-
"level: #{level.inspect}, " \
|
93
|
-
"valid: #{valid?.inspect})" \
|
94
|
-
end
|
95
|
-
|
96
|
-
# The readable definition.
|
97
|
-
#
|
98
|
-
# @return [String] A readable string of the definition.
|
99
|
-
def definition
|
100
|
-
[matcher, expected&.inspect].compact.join(' ')
|
101
|
-
end
|
102
|
-
|
103
|
-
# The negation, if any.
|
104
|
-
#
|
105
|
-
# @return [String] The negation, or an empty string.
|
106
|
-
def maybe_negate
|
107
|
-
negate? ? ' not' : ''
|
108
|
-
end
|
109
|
-
|
110
|
-
# The summary of the result.
|
111
|
-
#
|
112
|
-
# @return [String] A string representing the summary of the result.
|
113
|
-
def summary
|
114
|
-
if error?
|
115
|
-
error.message
|
116
|
-
elsif actual.is_a?(::Exception)
|
117
|
-
actual.message
|
118
|
-
elsif actual == expected
|
119
|
-
"expected#{maybe_negate} to #{definition}"
|
120
|
-
else
|
121
|
-
"expected #{actual.inspect}#{maybe_negate} to #{definition}"
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
# Express the result with one colored char.
|
126
|
-
#
|
127
|
-
# @return [String] The colored char that identify the result.
|
128
|
-
def colored_char
|
129
|
-
color(char)
|
130
|
-
end
|
131
|
-
|
132
|
-
# The colored string representation of the result.
|
133
|
-
#
|
134
|
-
# @return [String] A string representing the result.
|
135
|
-
def colored_string
|
136
|
-
color(to_s)
|
137
|
-
end
|
138
|
-
|
139
|
-
# The representation of the result.
|
140
|
-
#
|
141
|
-
# @return [String] A string representing the result.
|
142
|
-
def to_s
|
143
|
-
"#{titre}: #{summary}."
|
144
|
-
end
|
145
|
-
|
146
|
-
# Titre for the result.
|
147
|
-
#
|
148
|
-
# @return [String] A string representing the titre.
|
149
|
-
def titre
|
150
|
-
if error?
|
151
|
-
error.class.name
|
152
|
-
else
|
153
|
-
to_sym.to_s.capitalize
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
protected
|
158
|
-
|
159
|
-
def color(str)
|
160
|
-
if success?
|
161
|
-
"\e[32m#{str}\e[0m"
|
162
|
-
elsif info?
|
163
|
-
"\e[36m#{str}\e[0m"
|
164
|
-
elsif warning?
|
165
|
-
"\e[33m#{str}\e[0m"
|
166
|
-
elsif failure?
|
167
|
-
"\e[35m#{str}\e[0m"
|
168
|
-
else
|
169
|
-
"\e[31m#{str}\e[0m"
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|