Spectus
Expectation library with RFC 2119's requirement levels 🚥
Installation
Add this line to your application's Gemfile:
gem 'spectus'
And then execute:
$ bundle
Or install it yourself as:
$ gem install spectus
Expectation
An expectation is an assertion that is either true or false.
There are several scenarios:
| Requirement levels | MUST | SHOULD | MAY |
|---|---|---|---|
| Implemented & Matched | true |
true |
true |
| Implemented & Not matched | false |
true |
false |
| Implemented & Exception | false |
false |
false |
| Not implemented | false |
false |
true |
Thus,
- when an expectation is
true, aSpectus::Result::Passinstance is returned; - when an expectation is
false, aSpectus::Result::Failexception is raised.
Both results share a common interface, and can be classified respectively as:
- ✅ a success, ⚠️ a warning or 💡 an info;
- ❌ a failure or 💥 an error.
Code Isolation
When executing expectations, side-effects may occur. Because they may or may not be desired, each requirement level has 2 versions:
- if it does not end with
!, its test is performed without isolation; - if it ends with
!, its test is performed in isolation.
Example of test without isolation:
include Spectus
greeting = 'Hello, world!'
it { greeting.gsub!('world', 'Alice') }.MUST eql 'Hello, Alice!'
# => Spectus::Result::Pass(actual: "Hello, Alice!", error: nil, expected: "Hello, Alice!", got: true, matcher: :eql, negate: false, level: :MUST, valid: true)
greeting # => "Hello, Alice!"
Example of test in isolation:
include Spectus
greeting = 'Hello, world!'
it { greeting.gsub!('world', 'Alice') }.MUST! eql 'Hello, Alice!'
# => Spectus::Result::Pass(actual: "Hello, Alice!", error: nil, expected: "Hello, Alice!", got: true, matcher: :eql, negate: false, level: :MUST, valid: true)
greeting # => "Hello, world!"
Usage
To begin with, let's include Spectus:
include Spectus
Absolute Requirement
Given the "ルビー" object, when it receives valid_encoding? method, then it MUST be true:
it { 'ルビー'.valid_encoding? }.MUST be_true
# => Spectus::Result::Pass(actual: true, error: nil, expected: nil, got: true, matcher: :be_true, negate: false, level: :MUST, valid: true)
The result of the test shows that the spec passed.
Absolute Prohibition
Given the "foo" object, when it receives length method, then it MUST NOT raise the NoMethodError exception:
it { 'foo'.length }.MUST_NOT raise_exception NoMethodError
# => Spectus::Result::Pass(actual: 3, error: nil, expected: NoMethodError, got: true, matcher: :raise_exception, negate: true, level: :MUST, valid: true)
The result of the test shows that the spec passed.
Recommended
Given the BasicObject object, when it receives superclass method, then it SHOULD return the explicit blank class NilClass:
it { BasicObject.superclass }.SHOULD equal NilClass
# => Spectus::Result::Pass(actual: nil, error: nil, expected: NilClass, got: false, matcher: :equal, negate: false, level: :SHOULD, valid: false)
Instead of the expected NilClass class, its sole instance (which is nil) was returned.
However, because there isn't any exception, the result of the test shows that the spec passed.
Not Recommended
Given the "1" object, when it receives +(1) method, then it SHOULD NOT return the "11" value:
it { '1' + 1 }.SHOULD_NOT eql '11'
# 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)
There was a TypeError exception, the result of the test shows that the spec failed.
Optional
Given the "foo" object, when it receives blank? method, then it MAY be false:
it { 'foo'.blank? }.MAY be_false
# => 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)
The optional blank? method is not implemented (unlike in Ruby on Rails, for instance), so the result of the test shows that the spec passed.
More Examples
A full list of unit tests can be viewed here: test.rb
Contact
- Home page: https://github.com/fixrb/spectus
- Bugs/issues: https://github.com/fixrb/spectus/issues
Versioning
Spectus follows Semantic Versioning 2.0.
License
The gem is available as open source under the terms of the MIT License.
