test_tube 3.0.0 → 4.0.1
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 +56 -66
- data/lib/test_tube/experiment.rb +91 -0
- data/lib/test_tube/invoker.rb +53 -15
- data/lib/test_tube/passer.rb +20 -7
- data/lib/test_tube.rb +49 -18
- metadata +10 -10
- data/lib/test_tube/base.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62d9c394fa982a2c1465cfb2300ae0c00064abcd81a7fab01cc01997042bedfa
|
4
|
+
data.tar.gz: 21b3fa066f82dc567aace21b80a90d84cff94811db6cc81a56036ad3aa3b832b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d2a2e6a4fdef3582048f3b864f7ea07463dbc62c16be1bc4d686a4ca959196137a07a4fd7180c413e60b6411970d931f96dab3de8653f82aec88825de02cc4e
|
7
|
+
data.tar.gz: a732a5e445fc21525dc230b6ed190c12d27bfd7df1e80a3a7022326f18382ae82e9e308c251826193874402d5c729711ff2492cb9c501fbec02cc3b1586c02cf
|
data/LICENSE.md
CHANGED
data/README.md
CHANGED
@@ -2,11 +2,15 @@
|
|
2
2
|
|
3
3
|
[](https://github.com/fixrb/test_tube/tags)
|
4
4
|
[](https://rubydoc.info/github/fixrb/test_tube/main)
|
5
|
-
[](https://github.com/fixrb/test_tube/actions?query=workflow%3Aruby+branch%3Amain)
|
6
|
-
[](https://github.com/fixrb/test_tube/actions?query=workflow%3Arubocop+branch%3Amain)
|
7
5
|
[](https://github.com/fixrb/test_tube/raw/main/LICENSE.md)
|
8
6
|
|
9
|
-
> A test tube to conduct software experiments 🧪
|
7
|
+
> A test tube to conduct software experiments safely 🧪
|
8
|
+
|
9
|
+
TestTube is a Ruby library designed to safely execute and evaluate code experiments. It provides:
|
10
|
+
- Complete exception handling (including SystemExit and other system-level exceptions)
|
11
|
+
- A flexible matcher-based testing approach
|
12
|
+
- Two distinct testing methods: code execution (`invoke`) and value testing (`pass`)
|
13
|
+
- Clear experiment results with actual values, errors, and matcher results
|
10
14
|
|
11
15
|

|
12
16
|
|
@@ -32,55 +36,55 @@ gem install test_tube
|
|
32
36
|
|
33
37
|
## Usage
|
34
38
|
|
35
|
-
|
39
|
+
### Basic Usage
|
40
|
+
|
41
|
+
First, make TestTube available:
|
36
42
|
|
37
43
|
```ruby
|
38
44
|
require "test_tube"
|
39
45
|
```
|
40
46
|
|
41
|
-
|
42
|
-
|
47
|
+
TestTube provides two main ways to conduct experiments:
|
48
|
+
|
49
|
+
1. **Execute and test code** with `invoke`:
|
50
|
+
- Safely executes blocks of code
|
51
|
+
- Catches ALL exceptions, including system-level ones
|
52
|
+
- Perfect for testing potentially dangerous operations
|
53
|
+
|
54
|
+
2. **Test direct values** with `pass`:
|
55
|
+
- Tests pre-computed values
|
56
|
+
- Simpler and more direct approach
|
57
|
+
- Ideal when you already have the value to test
|
58
|
+
|
59
|
+
### Simple Example
|
60
|
+
|
61
|
+
Let's test if a value equals 42 using a custom matcher:
|
43
62
|
|
44
63
|
```ruby
|
45
64
|
class BeTheAnswer
|
46
|
-
def
|
65
|
+
def match?
|
47
66
|
42.equal?(yield)
|
48
67
|
end
|
49
68
|
end
|
50
|
-
```
|
51
|
-
|
52
|
-
One possibility would be to `invoke` a whole block of code:
|
53
|
-
|
54
|
-
```ruby
|
55
|
-
block_of_code = -> { "101010".to_i(2) }
|
56
|
-
|
57
|
-
experiment = TestTube.invoke(matcher: BeTheAnswer.new, negate: false, &block_of_code)
|
58
|
-
# => <TestTube actual=42 error=nil got=true>
|
59
69
|
|
70
|
+
# Using invoke to execute code
|
71
|
+
experiment = TestTube.invoke(matcher: BeTheAnswer.new, negate: false) do
|
72
|
+
"101010".to_i(2) # Converting binary to decimal
|
73
|
+
end
|
74
|
+
experiment.got # => true
|
60
75
|
experiment.actual # => 42
|
61
76
|
experiment.error # => nil
|
62
|
-
experiment.got # => true
|
63
|
-
```
|
64
|
-
|
65
|
-
An alternative would be to `pass` directly the actual value as a parameter:
|
66
|
-
|
67
|
-
```ruby
|
68
|
-
actual_value = "101010".to_i(2)
|
69
|
-
|
70
|
-
experiment = TestTube.pass(actual_value, matcher: BeTheAnswer.new, negate: false)
|
71
|
-
# => <TestTube actual=42 error=nil got=true>
|
72
77
|
|
78
|
+
# Or using pass with a direct value
|
79
|
+
experiment = TestTube.pass(42, matcher: BeTheAnswer.new, negate: false)
|
80
|
+
experiment.got # => true
|
73
81
|
experiment.actual # => 42
|
74
82
|
experiment.error # => nil
|
75
|
-
experiment.got # => true
|
76
83
|
```
|
77
84
|
|
78
|
-
###
|
85
|
+
### Integration with Matchi
|
79
86
|
|
80
|
-
|
81
|
-
[__Matchi__ project](https://github.com/fixrb/matchi/).
|
82
|
-
|
83
|
-
Let's use a built-in __Matchi__ matcher:
|
87
|
+
TestTube works seamlessly with the [Matchi](https://github.com/fixrb/matchi/) matcher library:
|
84
88
|
|
85
89
|
```sh
|
86
90
|
gem install matchi
|
@@ -88,50 +92,41 @@ gem install matchi
|
|
88
92
|
|
89
93
|
```ruby
|
90
94
|
require "matchi"
|
91
|
-
```
|
92
|
-
|
93
|
-
An example of successful experience:
|
94
95
|
|
95
|
-
|
96
|
+
# Testing for exceptions
|
96
97
|
experiment = TestTube.invoke(
|
97
98
|
matcher: Matchi::RaiseException.new(:NoMethodError),
|
98
99
|
negate: false
|
99
100
|
) { "foo".blank? }
|
100
|
-
# => <TestTube actual=#<NoMethodError: undefined method `blank?' for "foo":String> error=nil got=true>
|
101
|
-
|
102
|
-
experiment.actual # => #<NoMethodError: undefined method `blank?' for "foo":String>
|
103
|
-
experiment.error # => nil
|
104
101
|
experiment.got # => true
|
105
|
-
|
106
|
-
|
107
|
-
Another example of an experiment that fails:
|
102
|
+
experiment.actual # => #<NoMethodError: undefined method `blank?' for "foo":String>
|
108
103
|
|
109
|
-
|
104
|
+
# Testing floating-point arithmetic
|
110
105
|
experiment = TestTube.invoke(
|
111
106
|
matcher: Matchi::Be.new(0.3),
|
112
|
-
negate: false
|
113
|
-
|
114
|
-
) # => <TestTube actual=0.30000000000000004 error=nil got=false>
|
115
|
-
|
116
|
-
experiment.actual # => 0.30000000000000004
|
117
|
-
experiment.error # => nil
|
107
|
+
negate: false
|
108
|
+
) { 0.1 + 0.2 }
|
118
109
|
experiment.got # => false
|
119
|
-
|
120
|
-
|
121
|
-
Finally, an experiment which causes an error:
|
110
|
+
experiment.actual # => 0.30000000000000004
|
122
111
|
|
123
|
-
|
112
|
+
# Handling errors gracefully
|
124
113
|
experiment = TestTube.invoke(
|
125
114
|
matcher: Matchi::Match.new(/^foo$/),
|
126
115
|
negate: false
|
127
116
|
) { BOOM }
|
128
|
-
# => <TestTube actual=nil error=#<NameError: uninitialized constant BOOM> got=nil>
|
129
|
-
|
130
|
-
experiment.actual # => nil
|
131
|
-
experiment.error # => #<NameError: uninitialized constant BOOM>
|
132
117
|
experiment.got # => nil
|
118
|
+
experiment.error # => #<NameError: uninitialized constant BOOM>
|
119
|
+
experiment.actual # => nil
|
133
120
|
```
|
134
121
|
|
122
|
+
## Key Features
|
123
|
+
|
124
|
+
- **Safe Execution**: Catches all exceptions, including system-level ones
|
125
|
+
- **Flexible Testing**: Support for custom matchers and the Matchi library
|
126
|
+
- **Clear Results**: Easy access to actual values, errors, and test results
|
127
|
+
- **Two Testing Modes**: Choose between code execution and direct value testing
|
128
|
+
- **Framework Friendly**: Perfect for building testing frameworks and tools
|
129
|
+
|
135
130
|
## Contact
|
136
131
|
|
137
132
|
* Source code: https://github.com/fixrb/test_tube
|
@@ -140,17 +135,12 @@ experiment.got # => nil
|
|
140
135
|
|
141
136
|
## Versioning
|
142
137
|
|
143
|
-
|
138
|
+
Test Tube follows [Semantic Versioning 2.0](https://semver.org/).
|
144
139
|
|
145
140
|
## License
|
146
141
|
|
147
142
|
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).
|
148
143
|
|
149
|
-
|
144
|
+
## Sponsors
|
150
145
|
|
151
|
-
|
152
|
-
This project is sponsored by:<br />
|
153
|
-
<a href="https://sashite.com/"><img
|
154
|
-
src="https://github.com/fixrb/test_tube/raw/main/img/sashite.png"
|
155
|
-
alt="Sashité" /></a>
|
156
|
-
</p>
|
146
|
+
This project is sponsored by [Sashité](https://sashite.com/)
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TestTube
|
4
|
+
# Abstract class representing the state and result of a test experiment.
|
5
|
+
# This class inherits from BasicObject to provide a minimal interface
|
6
|
+
# and avoid any method conflicts with the objects being tested.
|
7
|
+
#
|
8
|
+
# It provides three main attributes:
|
9
|
+
# - actual: The value being tested
|
10
|
+
# - error: Any error that occurred during the test
|
11
|
+
# - got: The boolean result of the matcher
|
12
|
+
#
|
13
|
+
# @example Examining a test result
|
14
|
+
# experiment = TestTube.invoke(matcher: SomeMatcher.new, negate: false) { 42 }
|
15
|
+
# experiment.actual # => 42
|
16
|
+
# experiment.error # => nil
|
17
|
+
# experiment.got # => true
|
18
|
+
#
|
19
|
+
# @api private
|
20
|
+
class Experiment < ::BasicObject
|
21
|
+
# Expectation's actual value.
|
22
|
+
# This represents the value that was actually produced during the test,
|
23
|
+
# whether it came from a direct value (Passer) or a block execution (Invoker).
|
24
|
+
#
|
25
|
+
# @return [Object] The actual value being tested
|
26
|
+
# @return [nil] If an error occurred during the test
|
27
|
+
#
|
28
|
+
# @api public
|
29
|
+
attr_reader :actual
|
30
|
+
|
31
|
+
# Expectation's raised error.
|
32
|
+
# Stores any exception that occurred during the test execution,
|
33
|
+
# including system-level exceptions (SystemExit, SignalException, etc.)
|
34
|
+
# when using Invoker.
|
35
|
+
#
|
36
|
+
# @return [Exception, nil] Any error that occurred during the test
|
37
|
+
#
|
38
|
+
# @api public
|
39
|
+
attr_reader :error
|
40
|
+
|
41
|
+
# Expectation's returned boolean value.
|
42
|
+
# The result of applying the matcher to the actual value.
|
43
|
+
# Will be nil if an error occurred during the test.
|
44
|
+
#
|
45
|
+
# @return [Boolean] true if the matcher matched (considering negate)
|
46
|
+
# @return [nil] if an error occurred during the test
|
47
|
+
#
|
48
|
+
# @api public
|
49
|
+
attr_reader :got
|
50
|
+
|
51
|
+
# A string containing a human-readable representation of the experiment.
|
52
|
+
# Useful for debugging and logging test results.
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
# experiment.inspect
|
56
|
+
# # => "<TestTube actual=42 error=nil got=true>"
|
57
|
+
#
|
58
|
+
# @return [String] Human-readable representation of the experiment
|
59
|
+
#
|
60
|
+
# @api public
|
61
|
+
def inspect
|
62
|
+
"<TestTube actual=#{actual.inspect} error=#{error.inspect} got=#{got.inspect}>"
|
63
|
+
end
|
64
|
+
|
65
|
+
alias to_s inspect
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# Validates that the provided matcher responds to match?.
|
70
|
+
# This is crucial as the matcher is the core of the testing mechanism.
|
71
|
+
#
|
72
|
+
# @param matcher [Object] The matcher to validate
|
73
|
+
# @raise [ArgumentError] If the matcher doesn't respond to match?
|
74
|
+
#
|
75
|
+
# @api private
|
76
|
+
def validate_matcher(matcher)
|
77
|
+
raise ::ArgumentError, "Matcher must respond to match?" unless matcher.respond_to?(:match?)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Validates that the negate parameter is strictly boolean.
|
81
|
+
# This ensures predictable test behavior.
|
82
|
+
#
|
83
|
+
# @param negate [Object] The value to validate
|
84
|
+
# @raise [ArgumentError] If the value isn't true or false
|
85
|
+
#
|
86
|
+
# @api private
|
87
|
+
def validate_negate(negate)
|
88
|
+
raise ::ArgumentError, "negate must be boolean" unless [true, false].include?(negate)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/test_tube/invoker.rb
CHANGED
@@ -2,40 +2,78 @@
|
|
2
2
|
|
3
3
|
require "defi/method"
|
4
4
|
|
5
|
-
require_relative "
|
5
|
+
require_relative "experiment"
|
6
6
|
|
7
7
|
module TestTube
|
8
8
|
# Evaluate an actual value invoking it with #call method.
|
9
|
+
# This class is designed to handle ALL possible exceptions during test execution,
|
10
|
+
# including system-level exceptions. This is crucial for testing frameworks to:
|
11
|
+
# - Capture system exceptions (SystemExit, SignalException, etc.)
|
12
|
+
# - Prevent test suite interruption through exit calls
|
13
|
+
# - Ensure complete control over the test execution flow
|
14
|
+
# - Allow proper reporting of all types of failures
|
15
|
+
#
|
16
|
+
# @example Handling a system exit
|
17
|
+
# TestTube.invoke(matcher: SomeExitMatcher.new, negate: false) do
|
18
|
+
# exit(true) # Will be caught and handled properly
|
19
|
+
# end
|
9
20
|
#
|
10
21
|
# @api private
|
11
|
-
class Invoker <
|
12
|
-
# rubocop:disable Lint/RescueException
|
13
|
-
|
22
|
+
class Invoker < Experiment
|
14
23
|
# Class initializer.
|
15
24
|
#
|
16
|
-
# @param matcher [#
|
17
|
-
# @param negate [Boolean]
|
18
|
-
# @param input [Proc]
|
25
|
+
# @param matcher [#match?] The matcher to evaluate the result
|
26
|
+
# @param negate [Boolean] Whether to invert the matcher result
|
27
|
+
# @param input [Proc] The callable object to test
|
28
|
+
# @raise [ArgumentError] If the matcher doesn't respond to match?
|
19
29
|
def initialize(matcher:, negate:, &input)
|
30
|
+
validate_matcher(matcher)
|
31
|
+
validate_negate(negate)
|
20
32
|
super()
|
33
|
+
perform_experiment(matcher, negate, input)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Executes the experiment and handles any exceptions.
|
39
|
+
# Deliberately catches ALL exceptions (including system exceptions) to ensure
|
40
|
+
# complete control over the test execution flow.
|
41
|
+
#
|
42
|
+
# @param matcher [#match?] The matcher to evaluate the result
|
43
|
+
# @param negate [Boolean] Whether to invert the matcher result
|
44
|
+
# @param input [Proc] The code block to execute
|
45
|
+
def perform_experiment(matcher, negate, input)
|
46
|
+
@got = evaluate_match(matcher, negate, input)
|
47
|
+
rescue ::Exception => e # rubocop:disable Lint/RescueException
|
48
|
+
handle_exception(e)
|
49
|
+
end
|
21
50
|
|
22
|
-
|
51
|
+
# Evaluates the match result and handles the actual execution of the test code.
|
52
|
+
#
|
53
|
+
# @param matcher [#match?] The matcher to evaluate the result
|
54
|
+
# @param negate [Boolean] Whether to invert the matcher result
|
55
|
+
# @param input [Proc] The code block to execute
|
56
|
+
# @return [Boolean] The result of the matcher evaluation
|
57
|
+
def evaluate_match(matcher, negate, input)
|
58
|
+
negate ^ matcher.match? do
|
23
59
|
value = send_call.to(input)
|
24
60
|
@actual = value.object
|
25
61
|
value.call
|
26
62
|
end
|
27
|
-
rescue ::Exception => e
|
28
|
-
@actual = nil
|
29
|
-
@error = e
|
30
63
|
end
|
31
64
|
|
32
|
-
#
|
33
|
-
|
34
|
-
|
65
|
+
# Handles any exception that occurs during the experiment execution.
|
66
|
+
# Sets the actual value to nil and stores the exception.
|
67
|
+
#
|
68
|
+
# @param error [Exception] The exception that was raised
|
69
|
+
def handle_exception(error)
|
70
|
+
@actual = nil
|
71
|
+
@error = error
|
72
|
+
end
|
35
73
|
|
36
74
|
# @return [::Defi::Method] The challenge for the callable object.
|
37
75
|
#
|
38
|
-
# @see https://github.com/fixrb/defi/blob/v3.0.
|
76
|
+
# @see https://github.com/fixrb/defi/blob/v3.0.1/lib/defi/method.rb
|
39
77
|
def send_call
|
40
78
|
::Defi::Method.new(:call)
|
41
79
|
end
|
data/lib/test_tube/passer.rb
CHANGED
@@ -1,22 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "
|
3
|
+
require_relative "experiment"
|
4
4
|
|
5
5
|
module TestTube
|
6
6
|
# Evaluate an actual value passed in parameter.
|
7
|
+
# Unlike Invoker, this class handles direct value testing without executing a block,
|
8
|
+
# making it safer when you already have the value to test.
|
9
|
+
#
|
10
|
+
# @example Testing a direct value
|
11
|
+
# TestTube.pass("101010".to_i(2),
|
12
|
+
# matcher: BeTheAnswer.new,
|
13
|
+
# negate: false
|
14
|
+
# )
|
7
15
|
#
|
8
16
|
# @api private
|
9
|
-
class Passer <
|
17
|
+
class Passer < Experiment
|
10
18
|
# Class initializer.
|
19
|
+
# Validates the matcher and negate parameter before performing the test.
|
20
|
+
# Since no code block is executed, this approach is immune to system-level
|
21
|
+
# exceptions that might occur during value computation.
|
11
22
|
#
|
12
|
-
# @param input [
|
13
|
-
# @param matcher [#
|
14
|
-
# @param negate [Boolean]
|
23
|
+
# @param input [Object] The actual value to test
|
24
|
+
# @param matcher [#match?] The matcher to evaluate the result
|
25
|
+
# @param negate [Boolean] Whether to invert the matcher result
|
26
|
+
# @raise [ArgumentError] If the matcher doesn't respond to match?
|
15
27
|
def initialize(input, matcher:, negate:)
|
28
|
+
validate_matcher(matcher)
|
29
|
+
validate_negate(negate)
|
16
30
|
super()
|
17
|
-
|
18
31
|
@actual = input
|
19
|
-
@got = negate ^ matcher.
|
32
|
+
@got = negate ^ matcher.match? { input }
|
20
33
|
end
|
21
34
|
end
|
22
35
|
end
|
data/lib/test_tube.rb
CHANGED
@@ -4,51 +4,82 @@ require_relative File.join("test_tube", "invoker")
|
|
4
4
|
require_relative File.join("test_tube", "passer")
|
5
5
|
|
6
6
|
# Namespace for the TestTube library.
|
7
|
+
# This library provides two main methods for conducting software experiments:
|
8
|
+
# - invoke: For testing blocks of code, with full exception handling
|
9
|
+
# - pass: For testing direct values, with a simpler and safer approach
|
10
|
+
#
|
11
|
+
# @example Using with a testing framework
|
12
|
+
# require "test_tube"
|
13
|
+
# require "matchi"
|
14
|
+
#
|
15
|
+
# # Testing for exceptions
|
16
|
+
# TestTube.invoke(matcher: Matchi::RaiseException.new(SystemExit), negate: false) do
|
17
|
+
# exit(true) # Safely catches the SystemExit
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# # Testing direct values
|
21
|
+
# TestTube.pass(42, matcher: Matchi::EqualTo.new(42), negate: false)
|
7
22
|
#
|
8
23
|
# @api public
|
9
24
|
module TestTube
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
25
|
+
# Invokes a block for testing.
|
26
|
+
# This method should be used when you need to:
|
27
|
+
# - Execute and test a block of code
|
28
|
+
# - Catch all possible exceptions (including SystemExit)
|
29
|
+
# - Handle potentially dangerous operations safely
|
30
|
+
#
|
31
|
+
# @see TestTube::Invoker#initialize for parameter details
|
13
32
|
#
|
14
|
-
# @example
|
33
|
+
# @example Testing computation result
|
15
34
|
# require "test_tube"
|
16
35
|
#
|
17
36
|
# class BeTheAnswer
|
18
|
-
# def
|
37
|
+
# def match?
|
19
38
|
# 42.equal?(yield)
|
20
39
|
# end
|
21
40
|
# end
|
22
41
|
#
|
23
|
-
# TestTube.invoke(matcher: BeTheAnswer.new, negate: false) do
|
42
|
+
# experiment = TestTube.invoke(matcher: BeTheAnswer.new, negate: false) do
|
24
43
|
# "101010".to_i(2)
|
25
44
|
# end
|
26
45
|
#
|
27
|
-
#
|
28
|
-
|
29
|
-
|
46
|
+
# experiment.actual # => 42
|
47
|
+
# experiment.error # => nil
|
48
|
+
# experiment.got # => true
|
49
|
+
#
|
50
|
+
# @return [TestTube::Invoker] A software experiment capturing execution results and any errors
|
51
|
+
def self.invoke(...)
|
52
|
+
Invoker.new(...)
|
30
53
|
end
|
31
54
|
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
55
|
+
# Tests a value directly.
|
56
|
+
# This method should be used when you:
|
57
|
+
# - Already have the value to test
|
58
|
+
# - Don't need to execute potentially dangerous code
|
59
|
+
# - Want a simpler and more direct testing approach
|
60
|
+
#
|
61
|
+
# @see TestTube::Passer#initialize for parameter details
|
35
62
|
#
|
36
|
-
# @example
|
63
|
+
# @example Testing a direct value
|
37
64
|
# require "test_tube"
|
38
65
|
#
|
39
66
|
# class BeTheAnswer
|
40
|
-
# def
|
67
|
+
# def match?
|
41
68
|
# 42.equal?(yield)
|
42
69
|
# end
|
43
70
|
# end
|
44
71
|
#
|
45
|
-
# TestTube.pass("101010".to_i(2),
|
72
|
+
# experiment = TestTube.pass("101010".to_i(2),
|
46
73
|
# matcher: BeTheAnswer.new,
|
47
74
|
# negate: false
|
48
75
|
# )
|
49
76
|
#
|
50
|
-
#
|
51
|
-
|
52
|
-
|
77
|
+
# experiment.actual # => 42
|
78
|
+
# experiment.error # => nil
|
79
|
+
# experiment.got # => true
|
80
|
+
#
|
81
|
+
# @return [TestTube::Passer] A software experiment representing the test result
|
82
|
+
def self.pass(...)
|
83
|
+
Passer.new(...)
|
53
84
|
end
|
54
85
|
end
|
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:
|
4
|
+
version: 4.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cyril Kato
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-31 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: 3.0.
|
19
|
+
version: 3.0.1
|
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: 3.0.
|
26
|
+
version: 3.0.1
|
27
27
|
description: "A test tube to conduct software experiments \U0001F9EA"
|
28
28
|
email: contact@cyril.email
|
29
29
|
executables: []
|
@@ -33,7 +33,7 @@ files:
|
|
33
33
|
- LICENSE.md
|
34
34
|
- README.md
|
35
35
|
- lib/test_tube.rb
|
36
|
-
- lib/test_tube/
|
36
|
+
- lib/test_tube/experiment.rb
|
37
37
|
- lib/test_tube/invoker.rb
|
38
38
|
- lib/test_tube/passer.rb
|
39
39
|
homepage: https://github.com/fixrb/test_tube
|
@@ -41,7 +41,7 @@ licenses:
|
|
41
41
|
- MIT
|
42
42
|
metadata:
|
43
43
|
rubygems_mfa_required: 'true'
|
44
|
-
post_install_message:
|
44
|
+
post_install_message:
|
45
45
|
rdoc_options: []
|
46
46
|
require_paths:
|
47
47
|
- lib
|
@@ -49,15 +49,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
49
49
|
requirements:
|
50
50
|
- - ">="
|
51
51
|
- !ruby/object:Gem::Version
|
52
|
-
version: 3.
|
52
|
+
version: 3.1.0
|
53
53
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
54
|
requirements:
|
55
55
|
- - ">="
|
56
56
|
- !ruby/object:Gem::Version
|
57
57
|
version: '0'
|
58
58
|
requirements: []
|
59
|
-
rubygems_version: 3.
|
60
|
-
signing_key:
|
59
|
+
rubygems_version: 3.3.27
|
60
|
+
signing_key:
|
61
61
|
specification_version: 4
|
62
62
|
summary: "A test tube to conduct software experiments \U0001F9EA"
|
63
63
|
test_files: []
|
data/lib/test_tube/base.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module TestTube
|
4
|
-
# Abstract class representing the state of an experiment.
|
5
|
-
#
|
6
|
-
# @api private
|
7
|
-
class Base < ::BasicObject
|
8
|
-
# Expectation's actual value.
|
9
|
-
#
|
10
|
-
# @return [#object_id] The actual value.
|
11
|
-
#
|
12
|
-
# @api public
|
13
|
-
attr_reader :actual
|
14
|
-
|
15
|
-
# Expectation's raised error.
|
16
|
-
#
|
17
|
-
# @return [Exception, nil] The raised error.
|
18
|
-
#
|
19
|
-
# @api public
|
20
|
-
attr_reader :error
|
21
|
-
|
22
|
-
# Expectation's returned boolean value.
|
23
|
-
#
|
24
|
-
# @return [Boolean, nil] The returned boolean value.
|
25
|
-
#
|
26
|
-
# @api public
|
27
|
-
attr_reader :got
|
28
|
-
|
29
|
-
# A string containing a human-readable representation of the experiment.
|
30
|
-
#
|
31
|
-
# @return [String] The human-readable representation of the experiment.
|
32
|
-
#
|
33
|
-
# @api public
|
34
|
-
def inspect
|
35
|
-
"<TestTube actual=#{actual.inspect} error=#{error.inspect} got=#{got.inspect}>"
|
36
|
-
end
|
37
|
-
|
38
|
-
alias to_s inspect
|
39
|
-
end
|
40
|
-
end
|