spectus 3.1.4 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
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