spectus 3.1.4 → 3.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 73306cc997a51543203fcfbec28fedae74de8ca9f382040db66d1c6aebbfc4bd
4
- data.tar.gz: c9d9365b33cc4cca9cb54630306f9320c254a42ad64161d8a609107eeb8f95e3
3
+ metadata.gz: 7979abd1117a7e7320e221ef8723e818f7e1b3f8f7ac05e8913f65fdb2a7c615
4
+ data.tar.gz: b163fee339e12eec5712802159f361558f596ffa720cc87ccb26822883c40c36
5
5
  SHA512:
6
- metadata.gz: 5cdfb58c6e5e3b748f8c5071f354793618a6e6e00053e3139175c5afde4cbc2fd39a419fbe516970354a6eaaee585637077d6dcc65b1d3ba7ae5412f26dcce60
7
- data.tar.gz: 8211f7d6955d70067071a691bfa80b1f640930c01db4cec6433534141c3f7c7a4e386ee82c80f00941b3c6a04426d2266be7cdb416960e04c5e8a36b0f35bc95
6
+ metadata.gz: d4970d21d63e784d7257472a9ccee1f3d33f31e61d79030239a620a5a2f8569d039672c35429aa42c8db4c55c184f3bd7512921fb08246ad03ceed9b48b53b71
7
+ data.tar.gz: a41655c8c03ed03650677d8eae4d1fc4bb412bf4a4a66bc5076950181a6f6c9d123cd74f5a90127299d835f9249d07343463804bdbf276b8ad854c14bf0539c5
data/README.md CHANGED
@@ -24,65 +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 assertion is `true`, a `Spectus::Result::Pass` instance is returned;
43
- * when an assertion is `false`, a `Spectus::Result::Fail` exception is raised.
44
-
45
- Both results share a common interface.
46
-
47
- Passed expectations can be classified as:
48
-
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
-
66
- Example of test without isolation:
67
-
68
- ```ruby
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)
73
- greeting # => "Hello, Alice!"
74
- ```
75
-
76
- Example of test in isolation:
77
-
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
- ```
85
-
86
27
  ## Usage
87
28
 
88
29
  To begin with, let's include __Spectus__:
@@ -97,7 +38,7 @@ Given the "`ルビー`" object, when it receives `valid_encoding?` method, then
97
38
 
98
39
  ```ruby
99
40
  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)
41
+ # => Expresenter::Pass(actual: true, error: nil, expected: nil, got: true, matcher: :be_true, negate: false, level: :MUST, valid: true)
101
42
  ```
102
43
 
103
44
  The result of the test shows that the spec passed.
@@ -108,7 +49,7 @@ Given the "`foo`" object, when it receives `length` method, then it **MUST NOT**
108
49
 
109
50
  ```ruby
110
51
  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)
52
+ # => Expresenter::Pass(actual: 3, error: nil, expected: NoMethodError, got: true, matcher: :raise_exception, negate: true, level: :MUST, valid: true)
112
53
  ```
113
54
 
114
55
  The result of the test shows that the spec passed.
@@ -119,7 +60,7 @@ Given the `BasicObject` object, when it receives `superclass` method, then it **
119
60
 
120
61
  ```ruby
121
62
  it { BasicObject.superclass }.SHOULD equal NilClass
122
- # => Spectus::Result::Pass(actual: nil, error: nil, expected: NilClass, got: false, matcher: :equal, negate: false, level: :SHOULD, valid: false)
63
+ # => Expresenter::Pass(actual: nil, error: nil, expected: NilClass, got: false, matcher: :equal, negate: false, level: :SHOULD, valid: false)
123
64
  ```
124
65
 
125
66
  Instead of the expected `NilClass` class, its sole instance (which is `nil`) was returned.
@@ -131,7 +72,7 @@ Given the "`1`" object, when it receives `+(1)` method, then it **SHOULD NOT** r
131
72
 
132
73
  ```ruby
133
74
  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)
75
+ # raise Expresenter::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
76
  ```
136
77
 
137
78
  There was a `TypeError` exception, the result of the test shows that the spec failed.
@@ -142,7 +83,7 @@ Given the "`foo`" object, when it receives `blank?` method, then it **MAY** be `
142
83
 
143
84
  ```ruby
144
85
  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)
86
+ # => Expresenter::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
87
  ```
147
88
 
148
89
  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.
@@ -152,6 +93,34 @@ The optional `blank?` method is not implemented (unlike in [Ruby on Rails](https
152
93
  A full list of unit tests can be viewed (and executed) here:
153
94
  [./test.rb](https://github.com/fixrb/spectus/blob/main/test.rb)
154
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
+ # => Expresenter::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
+ # => Expresenter::Pass(actual: "Hello, Alice!", error: nil, expected: "Hello, Alice!", got: true, matcher: :eql, negate: false, level: :MUST, valid: true)
121
+ greeting # => "Hello, world!"
122
+ ```
123
+
155
124
  ## Contact
156
125
 
157
126
  * Home page: https://github.com/fixrb/spectus
data/lib/spectus.rb CHANGED
@@ -6,14 +6,14 @@ require "matchi/helper"
6
6
  #
7
7
  # @example It MUST equal 42.
8
8
  # require 'spectus'
9
- # it { 42 }.MUST equal 42 # => #<Spectus::Result::Pass...>
9
+ # it { 42 }.MUST equal 42 # => #<Expresenter::Pass...>
10
10
  module Spectus
11
11
  include ::Matchi::Helper
12
12
 
13
13
  # Expectations are built with this method.
14
14
  #
15
15
  # @example An _absolute requirement_ definition.
16
- # it { 42 }.MUST equal 42 # => #<Spectus::Result::Pass...>
16
+ # it { 42 }.MUST equal 42 # => #<Expresenter::Pass...>
17
17
  #
18
18
  # @param input [Proc] The code to test.
19
19
  #
@@ -23,7 +23,7 @@ module Spectus
23
23
  #
24
24
  # @param matcher [#matches?] The matcher.
25
25
  #
26
- # @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
26
+ # @return [Expresenter::Fail, Expresenter::Pass] Report if the spec pass or fail.
27
27
  def MUST(matcher)
28
28
  RequirementLevel::Must.new(
29
29
  callable: callable,
@@ -54,7 +54,7 @@ module Spectus
54
54
  #
55
55
  # @param matcher [#matches?] The matcher.
56
56
  #
57
- # @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
57
+ # @return [Expresenter::Fail, Expresenter::Pass] Report if the spec pass or fail.
58
58
  def MUST_NOT(matcher)
59
59
  RequirementLevel::Must.new(
60
60
  callable: callable,
@@ -87,7 +87,7 @@ module Spectus
87
87
  #
88
88
  # @param matcher [#matches?] The matcher.
89
89
  #
90
- # @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
90
+ # @return [Expresenter::Fail, Expresenter::Pass] Report if the spec pass or fail.
91
91
  def SHOULD(matcher)
92
92
  RequirementLevel::Should.new(
93
93
  callable: callable,
@@ -121,7 +121,7 @@ module Spectus
121
121
  #
122
122
  # @param matcher [#matches?] The matcher.
123
123
  #
124
- # @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
124
+ # @return [Expresenter::Fail, Expresenter::Pass] Report if the spec pass or fail.
125
125
  def SHOULD_NOT(matcher)
126
126
  RequirementLevel::Should.new(
127
127
  callable: callable,
@@ -161,7 +161,7 @@ module Spectus
161
161
  #
162
162
  # @param matcher [#matches?] The matcher.
163
163
  #
164
- # @return [Result::Fail, Result::Pass] Report if the spec pass or fail.
164
+ # @return [Expresenter::Fail, Expresenter::Pass] Report if the spec pass or fail.
165
165
  def MAY(matcher)
166
166
  RequirementLevel::May.new(
167
167
  callable: callable,
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "expresenter"
4
+
3
5
  module Spectus
4
6
  # Namespace for the requirement levels.
5
7
  module RequirementLevel
@@ -32,18 +34,19 @@ module Spectus
32
34
 
33
35
  # The result of the expectation.
34
36
  #
35
- # @raise [Result::Fail] The expectation is `false`.
36
- # @return [Result::Pass] The expectation is `true`.
37
+ # @raise [Expresenter::Fail] The expectation is `false`.
38
+ # @return [Expresenter::Pass] The expectation is `true`.
37
39
  def call
38
- Result.call(pass?,
39
- actual: exam.actual,
40
- error: exam.exception,
41
- expected: matcher.expected,
42
- got: exam.got,
43
- negate: negate?,
44
- valid: exam.valid?,
45
- matcher: matcher.class.to_sym,
46
- level: level)
40
+ ::Expresenter.call(pass?).with(
41
+ actual: exam.actual,
42
+ error: exam.exception,
43
+ expected: matcher.expected,
44
+ got: exam.got,
45
+ negate: negate?,
46
+ valid: exam.valid?,
47
+ matcher: matcher.class.to_sym,
48
+ level: level
49
+ )
47
50
  end
48
51
 
49
52
  protected
@@ -64,5 +67,4 @@ module Spectus
64
67
  end
65
68
  end
66
69
 
67
- require_relative File.join("..", "result")
68
70
  require_relative File.join("..", "exam")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spectus
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.4
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyril Kato
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
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.0.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.0.1
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: matchi
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -179,10 +193,6 @@ files:
179
193
  - lib/spectus/requirement_level/may.rb
180
194
  - lib/spectus/requirement_level/must.rb
181
195
  - lib/spectus/requirement_level/should.rb
182
- - lib/spectus/result.rb
183
- - lib/spectus/result/common.rb
184
- - lib/spectus/result/fail.rb
185
- - lib/spectus/result/pass.rb
186
196
  homepage: https://github.com/fixrb/spectus
187
197
  licenses:
188
198
  - MIT
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Spectus
4
- # Namespace for the results.
5
- module Result
6
- # @raise [Fail] A failed spec result.
7
- # @return [Pass] A passed spec result.
8
- def self.call(is_passed, **details)
9
- (is_passed ? Pass : Fail).call(**details)
10
- end
11
- end
12
- end
13
-
14
- require_relative File.join("result", "fail")
15
- require_relative File.join("result", "pass")
@@ -1,180 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Spectus
4
- module Result
5
- # Common collection of methods for Result's classes.
6
- module Common
7
- # @return [#object_id] Returned value by the challenged subject.
8
- attr_reader :actual
9
-
10
- # @return [Exception, nil] Any possible raised exception.
11
- attr_reader :error
12
-
13
- # @return [#object_id] The expected value.
14
- attr_reader :expected
15
-
16
- # @return [#object_id] The result of the boolean comparison between the
17
- # actual value and the expected value through the matcher.
18
- attr_reader :got
19
-
20
- # @return [#object_id] The matcher.
21
- attr_reader :matcher
22
-
23
- # @return [:MUST, :SHOULD, :MAY] The requirement level of the expectation.
24
- attr_reader :level
25
-
26
- # Common initialize method.
27
- #
28
- # @param actual [#object_id] Returned value by the challenged subject.
29
- # @param error [Exception, nil] Any possible raised exception.
30
- # @param expected [#object_id] The expected value.
31
- # @param got [Boolean, nil] The result of the boolean comparison
32
- # between the actual value and the expected value through the matcher.
33
- # @param negate [Boolean] Evaluated to a negative assertion?
34
- # @param valid [Boolean] Report if the test was true or false?
35
- # @param matcher [Symbol] The matcher.
36
- # @param level [:MUST, :SHOULD, :MAY] The requirement level.
37
- def initialize(actual:, error:, expected:, got:, negate:, valid:,
38
- matcher:, level:)
39
-
40
- @actual = actual
41
- @error = error
42
- @expected = expected
43
- @got = got
44
- @negate = negate
45
- @valid = valid
46
- @matcher = matcher
47
- @level = level
48
-
49
- super(to_s) if failed?
50
- end
51
-
52
- # Did the test pass?
53
- #
54
- # @return [Boolean] The spec passed or failed?
55
- def passed?
56
- !failed?
57
- end
58
-
59
- # The value of the negate instance variable.
60
- #
61
- # @return [Boolean] Evaluated to a negative assertion?
62
- def negate?
63
- @negate
64
- end
65
-
66
- # The state of error.
67
- #
68
- # @return [Boolean] The test raised an error?
69
- def error?
70
- !error.nil?
71
- end
72
-
73
- # The state of success.
74
- #
75
- # @return [Boolean] The test was a success?
76
- def success?
77
- got.equal?(true)
78
- end
79
-
80
- # The value of the boolean comparison between the actual value and the
81
- # expected value.
82
- #
83
- # @return [Boolean] The test was true or false?
84
- def valid?
85
- @valid
86
- end
87
-
88
- # A string containing a human-readable representation of the result.
89
- #
90
- # @return [String] The human-readable representation of the result.
91
- def inspect
92
- "#{self.class}(actual: #{actual.inspect}, " \
93
- "error: #{error.inspect}, " \
94
- "expected: #{expected.inspect}, " \
95
- "got: #{got.inspect}, " \
96
- "matcher: #{matcher.inspect}, " \
97
- "negate: #{negate?.inspect}, " \
98
- "level: #{level.inspect}, " \
99
- "valid: #{valid?.inspect})" \
100
- end
101
-
102
- # The readable definition.
103
- #
104
- # @return [String] A readable string of the definition.
105
- def definition
106
- [matcher, expected&.inspect].compact.join(" ")
107
- end
108
-
109
- # The negation, if any.
110
- #
111
- # @return [String] The negation, or an empty string.
112
- def maybe_negate
113
- negate? ? " not" : ""
114
- end
115
-
116
- # The summary of the result.
117
- #
118
- # @return [String] A string representing the summary of the result.
119
- def summary
120
- if error?
121
- error.message
122
- elsif actual.is_a?(::Exception)
123
- actual.message
124
- elsif actual == expected
125
- "expected#{maybe_negate} to #{definition}"
126
- else
127
- "expected #{actual.inspect}#{maybe_negate} to #{definition}"
128
- end
129
- end
130
-
131
- # Express the result with one colored char.
132
- #
133
- # @return [String] The colored char that identify the result.
134
- def colored_char
135
- color(char)
136
- end
137
-
138
- # The colored string representation of the result.
139
- #
140
- # @return [String] A string representing the result.
141
- def colored_string
142
- color(to_s)
143
- end
144
-
145
- # The representation of the result.
146
- #
147
- # @return [String] A string representing the result.
148
- def to_s
149
- "#{titre}: #{summary}."
150
- end
151
-
152
- # Titre for the result.
153
- #
154
- # @return [String] A string representing the titre.
155
- def titre
156
- if error?
157
- error.class.name
158
- else
159
- to_sym.to_s.capitalize
160
- end
161
- end
162
-
163
- protected
164
-
165
- def color(str)
166
- if success?
167
- "\e[32m#{str}\e[0m"
168
- elsif info?
169
- "\e[36m#{str}\e[0m"
170
- elsif warning?
171
- "\e[33m#{str}\e[0m"
172
- elsif failure?
173
- "\e[35m#{str}\e[0m"
174
- else
175
- "\e[31m#{str}\e[0m"
176
- end
177
- end
178
- end
179
- end
180
- end
@@ -1,74 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "common"
4
-
5
- module Spectus
6
- module Result
7
- # The class that is responsible for reporting that the expectation is false.
8
- class Fail < ::StandardError
9
- include Common
10
-
11
- # @raise [Fail] A failed spec result.
12
- def self.call(**details)
13
- raise new(**details)
14
- end
15
-
16
- # Did the test fail?
17
- #
18
- # @return [Boolean] The spec passed or failed?
19
- def failed?
20
- true
21
- end
22
-
23
- # The state of failure.
24
- #
25
- # @return [Boolean] The test was a failure?
26
- def failure?
27
- !error?
28
- end
29
-
30
- # The state of info.
31
- #
32
- # @return [Boolean] The test was an info?
33
- def info?
34
- false
35
- end
36
-
37
- # The state of warning.
38
- #
39
- # @return [Boolean] The test was a warning?
40
- def warning?
41
- false
42
- end
43
-
44
- # Identify the state of the result.
45
- #
46
- # @return [Symbol] The identifier of the state.
47
- def to_sym
48
- failure? ? :failure : :error
49
- end
50
-
51
- # Express the result with one char.
52
- #
53
- # @return [String] The char that identify the result.
54
- def char
55
- if failure?
56
- "F"
57
- else
58
- "E"
59
- end
60
- end
61
-
62
- # Express the result with one emoji.
63
- #
64
- # @return [String] The emoji that identify the result.
65
- def emoji
66
- if failure?
67
- "❌"
68
- else
69
- "💥"
70
- end
71
- end
72
- end
73
- end
74
- end
@@ -1,83 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "common"
4
-
5
- module Spectus
6
- module Result
7
- # The class that is responsible for reporting that the expectation is true.
8
- class Pass
9
- include Common
10
-
11
- # @return [Pass] A passed spec result.
12
- def self.call(**details)
13
- new(**details)
14
- end
15
-
16
- alias message to_s
17
-
18
- # Did the test fail?
19
- #
20
- # @return [Boolean] The spec passed or failed?
21
- def failed?
22
- false
23
- end
24
-
25
- # The state of failure.
26
- #
27
- # @return [Boolean] The test was a failure?
28
- def failure?
29
- false
30
- end
31
-
32
- # The state of info.
33
- #
34
- # @return [Boolean] The test was an info?
35
- def info?
36
- !error.nil?
37
- end
38
-
39
- # The state of warning.
40
- #
41
- # @return [Boolean] The test was a warning?
42
- def warning?
43
- got.equal?(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
- return :success if success?
51
- return :warning if warning?
52
-
53
- :info
54
- end
55
-
56
- # Express the result with one char.
57
- #
58
- # @return [String] The char that identify the result.
59
- def char
60
- if success?
61
- "."
62
- elsif warning?
63
- "W"
64
- else
65
- "I"
66
- end
67
- end
68
-
69
- # Express the result with one emoji.
70
- #
71
- # @return [String] The emoji that identify the result.
72
- def emoji
73
- if success?
74
- "✅"
75
- elsif warning?
76
- "⚠️"
77
- else
78
- "💡"
79
- end
80
- end
81
- end
82
- end
83
- end