test_tube 2.0.0 → 2.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +33 -46
- data/lib/test_tube.rb +10 -10
- data/lib/test_tube/base.rb +9 -1
- data/lib/test_tube/invoker.rb +9 -8
- data/lib/test_tube/passer.rb +1 -1
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27985c322404e783924126aac5671af89d2852979dc9cf10deae5ca2821dada7
|
4
|
+
data.tar.gz: a383583d7360975bf5f1e98a0271a566be78f97a293bd8d4cec7437c6e315c4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e71d511063d6f166ddce31450773f149b679ba21f95a70ffad6f92e527c4819fe44d177d676e1b774d5478f71f31ac61cd6c971d4ad1445e89a3dcab2532d59e
|
7
|
+
data.tar.gz: bf01ae4ec42fdf5075663b61b91933456bbce5a572c5582faa7c06d35cb857a90a23e18cf8cd4cf3109d1c1e4dbf4b49cd420ec0dbcb92c3517c8c5feaa360a9
|
data/README.md
CHANGED
@@ -39,7 +39,7 @@ require "test_tube"
|
|
39
39
|
```
|
40
40
|
|
41
41
|
Assuming we'd like to experiment on the answer to the Ultimate Question of Life,
|
42
|
-
the Universe, and Everything with the following
|
42
|
+
the Universe, and Everything with the following matcher:
|
43
43
|
|
44
44
|
```ruby
|
45
45
|
class BeTheAnswer
|
@@ -49,21 +49,13 @@ class BeTheAnswer
|
|
49
49
|
end
|
50
50
|
```
|
51
51
|
|
52
|
-
|
53
|
-
parameter representing the _actual value_ to be compared.
|
54
|
-
|
55
|
-
Back to our Ruby experiments, one possibility would be to `invoke` a whole block
|
56
|
-
of code:
|
52
|
+
One possibility would be to `invoke` a whole block of code:
|
57
53
|
|
58
54
|
```ruby
|
59
55
|
block_of_code = -> { "101010".to_i(2) }
|
60
56
|
|
61
|
-
experiment = TestTube.invoke(
|
62
|
-
|
63
|
-
matcher: BeTheAnswer.new,
|
64
|
-
negate: false,
|
65
|
-
&block_of_code
|
66
|
-
)
|
57
|
+
experiment = TestTube.invoke(isolate: false, matcher: BeTheAnswer.new, negate: false, &block_of_code)
|
58
|
+
# => <TestTube actual=42 error=nil got=true>
|
67
59
|
|
68
60
|
experiment.actual # => 42
|
69
61
|
experiment.error # => nil
|
@@ -75,11 +67,8 @@ An alternative would be to `pass` directly the actual value as a parameter:
|
|
75
67
|
```ruby
|
76
68
|
actual_value = "101010".to_i(2)
|
77
69
|
|
78
|
-
experiment = TestTube.pass(
|
79
|
-
|
80
|
-
matcher: BeTheAnswer.new,
|
81
|
-
negate: false
|
82
|
-
)
|
70
|
+
experiment = TestTube.pass(actual_value, matcher: BeTheAnswer.new, negate: false)
|
71
|
+
# => <TestTube actual=42 error=nil got=true>
|
83
72
|
|
84
73
|
experiment.actual # => 42
|
85
74
|
experiment.error # => nil
|
@@ -105,12 +94,11 @@ An example of successful experience:
|
|
105
94
|
|
106
95
|
```ruby
|
107
96
|
experiment = TestTube.invoke(
|
108
|
-
|
109
|
-
matcher:
|
110
|
-
negate:
|
111
|
-
)
|
112
|
-
|
113
|
-
end
|
97
|
+
isolate: false,
|
98
|
+
matcher: Matchi::RaiseException.new(:NoMethodError),
|
99
|
+
negate: false
|
100
|
+
) { "foo".blank? }
|
101
|
+
# => <TestTube actual=#<NoMethodError: undefined method `blank?' for "foo":String> error=nil got=true>
|
114
102
|
|
115
103
|
experiment.actual # => #<NoMethodError: undefined method `blank?' for "foo":String>
|
116
104
|
experiment.error # => nil
|
@@ -121,11 +109,11 @@ Another example of an experiment that fails:
|
|
121
109
|
|
122
110
|
```ruby
|
123
111
|
experiment = TestTube.invoke(
|
124
|
-
|
125
|
-
matcher:
|
126
|
-
negate:
|
112
|
+
isolate: false,
|
113
|
+
matcher: Matchi::Be.new(0.3),
|
114
|
+
negate: false,
|
127
115
|
&-> { 0.1 + 0.2 }
|
128
|
-
)
|
116
|
+
) # => <TestTube actual=0.30000000000000004 error=nil got=false>
|
129
117
|
|
130
118
|
experiment.actual # => 0.30000000000000004
|
131
119
|
experiment.error # => nil
|
@@ -136,10 +124,11 @@ Finally, an experiment which causes an error:
|
|
136
124
|
|
137
125
|
```ruby
|
138
126
|
experiment = TestTube.invoke(
|
139
|
-
|
140
|
-
matcher:
|
141
|
-
negate:
|
127
|
+
isolate: false,
|
128
|
+
matcher: Matchi::Match.new(/^foo$/),
|
129
|
+
negate: false
|
142
130
|
) { BOOM }
|
131
|
+
# => <TestTube actual=nil error=#<NameError: uninitialized constant BOOM> got=nil>
|
143
132
|
|
144
133
|
experiment.actual # => nil
|
145
134
|
experiment.error # => #<NameError: uninitialized constant BOOM>
|
@@ -149,27 +138,25 @@ experiment.got # => nil
|
|
149
138
|
### Code isolation
|
150
139
|
|
151
140
|
When experimenting tests, side-effects may occur. Because they may or may not be
|
152
|
-
desired, an `
|
141
|
+
desired, an `isolate` option is available.
|
153
142
|
|
154
143
|
Let's for instance consider this block of code:
|
155
144
|
|
156
145
|
```ruby
|
157
146
|
greeting = "Hello, world!"
|
158
|
-
block_of_code = -> { greeting.gsub!("world", "Alice") }
|
147
|
+
block_of_code = -> { greeting.gsub!("world", "Alice") } # => #<Proc:0x00007f87f71b9690 (irb):42 (lambda)>
|
159
148
|
```
|
160
149
|
|
161
|
-
By setting the `
|
150
|
+
By setting the `isolate` option to `true`, we can experiment while avoiding
|
162
151
|
side effects:
|
163
152
|
|
164
153
|
```ruby
|
165
154
|
experiment = TestTube.invoke(
|
166
|
-
|
167
|
-
matcher:
|
168
|
-
negate:
|
155
|
+
isolate: true,
|
156
|
+
matcher: Matchi::Eq.new("Hello, Alice!"),
|
157
|
+
negate: false,
|
169
158
|
&block_of_code
|
170
|
-
)
|
171
|
-
|
172
|
-
experiment.inspect # => <TestTube actual="Hello, Alice!" error=nil got=true>
|
159
|
+
) # => <TestTube actual="Hello, Alice!" error=nil got=true>
|
173
160
|
|
174
161
|
greeting # => "Hello, world!"
|
175
162
|
```
|
@@ -178,13 +165,11 @@ Otherwise, we can experiment without any code isolation:
|
|
178
165
|
|
179
166
|
```ruby
|
180
167
|
experiment = TestTube.invoke(
|
181
|
-
|
182
|
-
matcher:
|
183
|
-
negate:
|
168
|
+
isolate: false,
|
169
|
+
matcher: Matchi::Eq.new("Hello, Alice!"),
|
170
|
+
negate: false,
|
184
171
|
&block_of_code
|
185
|
-
)
|
186
|
-
|
187
|
-
experiment.inspect # => <TestTube actual="Hello, Alice!" error=nil got=true>
|
172
|
+
) # => <TestTube actual="Hello, Alice!" error=nil got=true>
|
188
173
|
|
189
174
|
greeting # => "Hello, Alice!"
|
190
175
|
```
|
@@ -192,6 +177,8 @@ greeting # => "Hello, Alice!"
|
|
192
177
|
## Contact
|
193
178
|
|
194
179
|
* Source code: https://github.com/fixrb/test_tube
|
180
|
+
* Chinese blog post: https://ruby-china.org/topics/41390
|
181
|
+
* Japanese blog post: https://qiita.com/cyril/items/36174b619ff1852c80ec
|
195
182
|
|
196
183
|
## Versioning
|
197
184
|
|
@@ -199,7 +186,7 @@ __Test Tube__ follows [Semantic Versioning 2.0](https://semver.org/).
|
|
199
186
|
|
200
187
|
## License
|
201
188
|
|
202
|
-
The [gem](https://rubygems.org/gems/test_tube) is available as open source under the terms of the [MIT License](https://
|
189
|
+
The [gem](https://rubygems.org/gems/test_tube) is available as open source under the terms of the [MIT License](https://github.com/fixrb/test_tube/raw/main/LICENSE.md).
|
203
190
|
|
204
191
|
***
|
205
192
|
|
data/lib/test_tube.rb
CHANGED
@@ -7,10 +7,10 @@ require_relative File.join("test_tube", "passer")
|
|
7
7
|
#
|
8
8
|
# @api public
|
9
9
|
module TestTube
|
10
|
-
# @param
|
11
|
-
# @param matcher
|
12
|
-
# @param negate
|
13
|
-
# @param input
|
10
|
+
# @param isolate [Boolean] Compute in a subprocess.
|
11
|
+
# @param matcher [#matches?] A matcher.
|
12
|
+
# @param negate [Boolean] Invert the matcher or not.
|
13
|
+
# @param input [Proc] The callable object to test.
|
14
14
|
#
|
15
15
|
# @example
|
16
16
|
# require "test_tube"
|
@@ -21,18 +21,18 @@ module TestTube
|
|
21
21
|
# end
|
22
22
|
# end
|
23
23
|
#
|
24
|
-
# TestTube.invoke(
|
24
|
+
# TestTube.invoke(isolate: false, matcher: BeTheAnswer.new, negate: false) do
|
25
25
|
# "101010".to_i(2)
|
26
26
|
# end
|
27
27
|
#
|
28
28
|
# @return [Invoker] A software experiment.
|
29
|
-
def self.invoke(
|
30
|
-
Invoker.new(
|
29
|
+
def self.invoke(isolate:, matcher:, negate:, &input)
|
30
|
+
Invoker.new(isolate: isolate, matcher: matcher, negate: negate, &input)
|
31
31
|
end
|
32
32
|
|
33
|
-
# @param input
|
34
|
-
# @param matcher
|
35
|
-
# @param negate
|
33
|
+
# @param input [#object_id] The actual value to test.
|
34
|
+
# @param matcher [#matches?] A matcher.
|
35
|
+
# @param negate [Boolean] Invert the matcher or not.
|
36
36
|
#
|
37
37
|
# @example
|
38
38
|
# require "test_tube"
|
data/lib/test_tube/base.rb
CHANGED
@@ -4,25 +4,33 @@ module TestTube
|
|
4
4
|
# Abstract class representing the state of an experiment.
|
5
5
|
#
|
6
6
|
# @api private
|
7
|
-
class Base
|
7
|
+
class Base < ::BasicObject
|
8
8
|
# Expectation's actual value.
|
9
9
|
#
|
10
10
|
# @return [#object_id] The actual value.
|
11
|
+
#
|
12
|
+
# @api public
|
11
13
|
attr_reader :actual
|
12
14
|
|
13
15
|
# Expectation's raised error.
|
14
16
|
#
|
15
17
|
# @return [Exception, nil] The raised error.
|
18
|
+
#
|
19
|
+
# @api public
|
16
20
|
attr_reader :error
|
17
21
|
|
18
22
|
# Expectation's returned boolean value.
|
19
23
|
#
|
20
24
|
# @return [Boolean, nil] The returned boolean value.
|
25
|
+
#
|
26
|
+
# @api public
|
21
27
|
attr_reader :got
|
22
28
|
|
23
29
|
# A string containing a human-readable representation of the experiment.
|
24
30
|
#
|
25
31
|
# @return [String] The human-readable representation of the experiment.
|
32
|
+
#
|
33
|
+
# @api public
|
26
34
|
def inspect
|
27
35
|
"<TestTube actual=#{actual.inspect} error=#{error.inspect} got=#{got.inspect}>"
|
28
36
|
end
|
data/lib/test_tube/invoker.rb
CHANGED
@@ -9,19 +9,19 @@ module TestTube
|
|
9
9
|
#
|
10
10
|
# @api private
|
11
11
|
class Invoker < Base
|
12
|
-
# Class initializer.
|
13
|
-
#
|
14
12
|
# rubocop:disable Lint/RescueException, Metrics/MethodLength
|
13
|
+
|
14
|
+
# Class initializer.
|
15
15
|
#
|
16
|
-
# @param
|
17
|
-
# @param matcher
|
18
|
-
# @param negate
|
19
|
-
# @param input
|
20
|
-
def initialize(
|
16
|
+
# @param isolate [Boolean] Compute in a subprocess.
|
17
|
+
# @param matcher [#matches?] A matcher.
|
18
|
+
# @param negate [Boolean] Invert the matcher or not.
|
19
|
+
# @param input [Proc] The callable object to test.
|
20
|
+
def initialize(isolate:, matcher:, negate:, &input)
|
21
21
|
super()
|
22
22
|
|
23
23
|
@got = negate ^ matcher.matches? do
|
24
|
-
value = if
|
24
|
+
value = if isolate
|
25
25
|
send_call.to!(input)
|
26
26
|
else
|
27
27
|
send_call.to(input)
|
@@ -34,6 +34,7 @@ module TestTube
|
|
34
34
|
@actual = nil
|
35
35
|
@error = e
|
36
36
|
end
|
37
|
+
|
37
38
|
# rubocop:enable Lint/RescueException, Metrics/MethodLength
|
38
39
|
|
39
40
|
private
|
data/lib/test_tube/passer.rb
CHANGED
@@ -9,7 +9,7 @@ module TestTube
|
|
9
9
|
class Passer < Base
|
10
10
|
# Class initializer.
|
11
11
|
#
|
12
|
-
# @param input [#object_id]
|
12
|
+
# @param input [#object_id] The actual value to test.
|
13
13
|
# @param matcher [#matches?] A matcher.
|
14
14
|
# @param negate [Boolean] Invert the matcher or not.
|
15
15
|
def initialize(input, matcher:, negate:)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: test_tube
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cyril Kato
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: defi
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.0.
|
19
|
+
version: 2.0.6
|
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.6
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: brutal
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: matchi
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|