should_just_work
should_just_work
Classic RSpec-like .should / .should_not comparisons for Crystal's spec.
book.title.should == "Revolution"
The shard adds a should and should_not without arguments to Object. The operator that follows turns into the matching spec expectation. The standard value.should eq(x) form keeps working next to it.
This is the Crystal version of the Ruby gem minitest-should_just_work.
Installation
Add it to your shard.yml:
development_dependencies:
should_just_work:
github: domify/should_just_work
$ shards install
Usage
Require it after spec, for example in spec/spec_helper.cr:
require "spec"
require "should_just_work"
describe "Books" do
it "has a title" do
book = Book.new title: "Revolution"
book.title.should == "Revolution"
end
end
Comparisons
| should_just_work | Crystal spec |
|---|---|
x.should == y |
x.should eq(y) |
x.should == nil |
x.should be_nil |
x.should != y |
x.should_not eq(y) |
x.should != nil |
x.should_not be_nil |
x.should =~ /y/ |
x.should match(/y/) |
x.should > y |
x.should be > y |
x.should < y |
x.should be < y |
x.should >= y |
x.should be >= y |
x.should <= y |
x.should be <= y |
A failure is reported at the line of the .should, with the same message the standard expectation gives.
For expectations without an operator, use the standard form: x.should be_empty, x.should contain(y), x.should be_a(Y), and so on.
Negating
Use should_not to negate any comparison:
obj.should_not == 3 # => obj.should_not eq(3)
obj.should_not =~ /regex/ # => obj.should_not match(/regex/)
obj.should_not == nil # => obj.should_not be_nil
Exceptions
should.raise DivisionByZeroError do
2 // 0
end
should_not.raise DivisionByZeroError do
2 // 1
end
should.raise(ArgumentError, "bad") { raise ArgumentError.new("bad") }
should.raise(ArgumentError, /ba/) { raise ArgumentError.new("bad") }
should.raise with no argument catches any Exception. It uses expect_raises, so a message string must be contained in the exception's message and a regex must match it. It returns the exception:
ex = should.raise(KeyError) { hash["missing"] }
ex.message.should =~ /missing/
should_not.raise matches the message the same way. Exceptions of other types, or with a message that does not match, pass through, and so does a failed should inside the block.
Crystal has no throw/catch, so the Ruby gem's should.throw has no counterpart here.
Ameba
obj.should == 2 is a comparison whose result is not used, which ameba reports as Lint/UnusedExpression. Switch the rule off for specs in .ameba.yml:
Lint/UnusedExpression:
Excluded:
- "spec/**/*.cr"
Development
$ shards install
$ crystal spec
$ shards build ameba && bin/ameba
Sponsor
If should_just_work has made your specs a little nicer to read and you feel like saying thanks, you can do so through GitHub Sponsors.
License
(c) 2026 Priit Tark, MIT license
should_just_work
- 0
- 0
- 0
- 0
- 1
- about 4 hours ago
- September 29, 2026
MIT License
Tue, 29 Sep 2026 15:01:43 GMT