Test Tube
A test tube to conduct software experiments safely 🧪
TestTube is a Ruby library designed to safely execute and evaluate code experiments. It provides:
- Complete exception handling (including SystemExit and other system-level exceptions)
- A flexible matcher-based testing approach
- Two distinct testing methods: code execution (
invoke
) and value testing (pass
) - Clear experiment results with actual values, errors, and matcher results
Installation
Add this line to your application's Gemfile:
gem "test_tube"
And then execute:
bundle install
Or install it yourself as:
gem install test_tube
Usage
Basic Usage
First, make TestTube available:
require "test_tube"
TestTube provides two main ways to conduct experiments:
-
Execute and test code with
invoke
:- Safely executes blocks of code
- Catches ALL exceptions, including system-level ones
- Perfect for testing potentially dangerous operations
-
Test direct values with
pass
:- Tests pre-computed values
- Simpler and more direct approach
- Ideal when you already have the value to test
Simple Example
Let's test if a value equals 42 using a custom matcher:
class BeTheAnswer
def match?
42.equal?(yield)
end
end
# Using invoke to execute code
experiment = TestTube.invoke(matcher: BeTheAnswer.new, negate: false) do
"101010".to_i(2) # Converting binary to decimal
end
experiment.got # => true
experiment.actual # => 42
experiment.error # => nil
# Or using pass with a direct value
experiment = TestTube.pass(42, matcher: BeTheAnswer.new, negate: false)
experiment.got # => true
experiment.actual # => 42
experiment.error # => nil
Integration with Matchi
TestTube works seamlessly with the Matchi matcher library:
gem install matchi
require "matchi"
# Testing for exceptions
experiment = TestTube.invoke(
matcher: Matchi::RaiseException.new(:NoMethodError),
negate: false
) { "foo".blank? }
experiment.got # => true
experiment.actual # => #<NoMethodError: undefined method `blank?' for "foo":String>
# Testing floating-point arithmetic
experiment = TestTube.invoke(
matcher: Matchi::Be.new(0.3),
negate: false
) { 0.1 + 0.2 }
experiment.got # => false
experiment.actual # => 0.30000000000000004
# Handling errors gracefully
experiment = TestTube.invoke(
matcher: Matchi::Match.new(/^foo$/),
negate: false
) { BOOM }
experiment.got # => nil
experiment.error # => #<NameError: uninitialized constant BOOM>
experiment.actual # => nil
Key Features
- Safe Execution: Catches all exceptions, including system-level ones
- Flexible Testing: Support for custom matchers and the Matchi library
- Clear Results: Easy access to actual values, errors, and test results
- Two Testing Modes: Choose between code execution and direct value testing
- Framework Friendly: Perfect for building testing frameworks and tools
Contact
- Source code: https://github.com/fixrb/test_tube
- Chinese blog post: https://ruby-china.org/topics/41390
- Japanese blog post: https://qiita.com/cyril/items/36174b619ff1852c80ec
Versioning
Test Tube follows Semantic Versioning 2.0.
License
The gem is available as open source under the terms of the MIT License.
Sponsors
This project is sponsored by Sashité