test_tube 4.0.0 → 4.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.md +1 -1
- data/README.md +53 -58
- data/lib/test_tube/experiment.rb +91 -0
- data/lib/test_tube/invoker.rb +53 -15
- data/lib/test_tube/passer.rb +19 -6
- data/lib/test_tube.rb +37 -6
- metadata +10 -7
- 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
|
[![Version](https://img.shields.io/github/v/tag/fixrb/test_tube?label=Version&logo=github)](https://github.com/fixrb/test_tube/tags)
|
4
4
|
[![Yard documentation](https://img.shields.io/badge/Yard-documentation-blue.svg?logo=github)](https://rubydoc.info/github/fixrb/test_tube/main)
|
5
|
-
[![Ruby](https://github.com/fixrb/test_tube/workflows/Ruby/badge.svg?branch=main)](https://github.com/fixrb/test_tube/actions?query=workflow%3Aruby+branch%3Amain)
|
6
|
-
[![RuboCop](https://github.com/fixrb/test_tube/workflows/RuboCop/badge.svg?branch=main)](https://github.com/fixrb/test_tube/actions?query=workflow%3Arubocop+branch%3Amain)
|
7
5
|
[![License](https://img.shields.io/github/license/fixrb/test_tube?label=License&logo=github)](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
|
![A researcher experimenting with Ruby code](https://github.com/fixrb/test_tube/raw/main/img/social-media-preview.png)
|
12
16
|
|
@@ -32,14 +36,29 @@ 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
|
@@ -47,40 +66,25 @@ class BeTheAnswer
|
|
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,7 +135,7 @@ 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
|
|
@@ -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 [#match?]
|
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,20 +1,33 @@
|
|
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 [#match?]
|
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
32
|
@got = negate ^ matcher.match? { input }
|
20
33
|
end
|
data/lib/test_tube.rb
CHANGED
@@ -4,14 +4,33 @@ 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
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
|
11
30
|
#
|
12
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
|
@@ -20,20 +39,28 @@ module TestTube
|
|
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
|
-
#
|
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
|
28
51
|
def self.invoke(...)
|
29
52
|
Invoker.new(...)
|
30
53
|
end
|
31
54
|
|
32
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
|
33
60
|
#
|
34
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
|
@@ -42,12 +69,16 @@ module TestTube
|
|
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
|
-
#
|
77
|
+
# experiment.actual # => 42
|
78
|
+
# experiment.error # => nil
|
79
|
+
# experiment.got # => true
|
80
|
+
#
|
81
|
+
# @return [TestTube::Passer] A software experiment representing the test result
|
51
82
|
def self.pass(...)
|
52
83
|
Passer.new(...)
|
53
84
|
end
|
metadata
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: test_tube
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.
|
4
|
+
version: 4.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cyril Kato
|
8
|
+
autorequire:
|
8
9
|
bindir: bin
|
9
10
|
cert_chain: []
|
10
|
-
date: 2024-12-
|
11
|
+
date: 2024-12-31 00:00:00.000000000 Z
|
11
12
|
dependencies:
|
12
13
|
- !ruby/object:Gem::Dependency
|
13
14
|
name: defi
|
@@ -15,14 +16,14 @@ dependencies:
|
|
15
16
|
requirements:
|
16
17
|
- - "~>"
|
17
18
|
- !ruby/object:Gem::Version
|
18
|
-
version: 3.0.
|
19
|
+
version: 3.0.1
|
19
20
|
type: :runtime
|
20
21
|
prerelease: false
|
21
22
|
version_requirements: !ruby/object:Gem::Requirement
|
22
23
|
requirements:
|
23
24
|
- - "~>"
|
24
25
|
- !ruby/object:Gem::Version
|
25
|
-
version: 3.0.
|
26
|
+
version: 3.0.1
|
26
27
|
description: "A test tube to conduct software experiments \U0001F9EA"
|
27
28
|
email: contact@cyril.email
|
28
29
|
executables: []
|
@@ -32,7 +33,7 @@ files:
|
|
32
33
|
- LICENSE.md
|
33
34
|
- README.md
|
34
35
|
- lib/test_tube.rb
|
35
|
-
- lib/test_tube/
|
36
|
+
- lib/test_tube/experiment.rb
|
36
37
|
- lib/test_tube/invoker.rb
|
37
38
|
- lib/test_tube/passer.rb
|
38
39
|
homepage: https://github.com/fixrb/test_tube
|
@@ -40,6 +41,7 @@ licenses:
|
|
40
41
|
- MIT
|
41
42
|
metadata:
|
42
43
|
rubygems_mfa_required: 'true'
|
44
|
+
post_install_message:
|
43
45
|
rdoc_options: []
|
44
46
|
require_paths:
|
45
47
|
- lib
|
@@ -47,14 +49,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
47
49
|
requirements:
|
48
50
|
- - ">="
|
49
51
|
- !ruby/object:Gem::Version
|
50
|
-
version: 3.
|
52
|
+
version: 3.1.0
|
51
53
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
54
|
requirements:
|
53
55
|
- - ">="
|
54
56
|
- !ruby/object:Gem::Version
|
55
57
|
version: '0'
|
56
58
|
requirements: []
|
57
|
-
rubygems_version: 3.
|
59
|
+
rubygems_version: 3.3.27
|
60
|
+
signing_key:
|
58
61
|
specification_version: 4
|
59
62
|
summary: "A test tube to conduct software experiments \U0001F9EA"
|
60
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
|