Have you ever wondered what the Ruby code generated by your test DSL might look like?
As a developer, it might be interesting to know. Maybe it's so horrible that it's impossible to write directly. Or maybe it's even lighter than a minitest test set. Who knows?
To try to answer this question while avoiding the endless debate between RSpec and minitest, I will use the RSpec clone project for the purpose of this post.
What is RSpec clone?
It is a minimalist reimplementation of RSpec that emphasizes correctness, security and standardization.
Driven by the desire to enforce the guidelines and best practices outlined in the community RSpec style guide, this RSpec clone includes most of RSpec’s DSL to express expected outcomes with no magical powers.
Without further ado, here are some correspondences between the DSL syntax and the generated Ruby code to understand how the framework builds and executes tests. For ease of reading, these mappings are grouped by method.
From DSL to Ruby
describe
method
When I write this,
RSpec.describe String do
end
I expect this code to be generated:
Class.new do
private
def described_class
String
end
end
context
method
When I write this,
RSpec.context "when in a context" do
end
I expect this code to be generated:
Class.new do
end
subject
method
When I write this,
RSpec.describe ".subject" do
subject do
"foo"
end
end
I expect this code to be generated:
Class.new do
private
def subject
"foo"
end
end
Embedded describe
method
When I write this,
RSpec.describe ".describe" do
describe "embedded describe" do
end
end
I expect this code to be generated:
base = Class.new do
end
Class.new(base) do
end
let
method
When I write this,
RSpec.describe ".let" do
let(:answer_to_everything) { 41 + one }
let(:one) { 1 }
end
I expect this code to be generated:
Class.new do
private
def answer_to_everything
41 + one
end
def one
1
end
end
before
method
When I write this,
RSpec.describe ".before" do
before do
puts "hello"
end
end
I expect this code to be generated:
Class.new do
private
def initialize
puts "hello"
end
end
expect
method
When I write this,
RSpec.describe "#expect" do
it { expect(41.next).to be(42) }
end
I expect this code to be generated:
description = Class.new do
end
require "matchi/rspec"
require "r_spec/clone/expectation_target"
example = Class.new(description) { include Matchi::Helper }
sandbox = example.new
sandbox.instance_eval { ExpectationTarget::Value.new(41.next).to be(42) }
And I expect to see this result in console:
Success: expected to be 42.
Happy testing with Ruby
Unless you don't write tests, the advantage of using such DSL interface is to limit the introduction of additional logic in to the specification document with potential errors, to encourage the use of good Ruby patterns with low algorithmic complexity, and to make Ruby code shorter and more (machine) readable.
Rspec is a testing DSL. MiniTest is ruby.
I love both, and I hope you'll like RSpec clone too.
Top comments (0)