你知道当你使用你喜欢的测试框架的DSL时,会产生什么样的代码吗?
作为一个开发者,你可能有兴趣知道。也许直接写出来太吓人了。或者它可能比 minitest 测试集更轻。
总之,为了尝试回答这个问题,同时避免 RSpec 和 minitest 之间无休止的争论,我将在本文中使用RSpec clone 项目。
这个项目是对 RSpec 的一个最小化的重新实现,强调正确性、安全性和标准化。
RSpec clone 试图实现社区RSpec 风格指南中列出的准则和最佳实践。大多数 RSpec 的 DSL 的实现是为了表达所需的结果。没有什么神奇的力量。
为了快速了解该框架是如何构建和执行测试的,我将向你展示 DSL 语法和生成的 Ruby 代码之间的对应关系。为了便于阅读,这些对应关系是按方法分组的。
describe
该方法当我写:
RSpec.describe String do
end
我希望能产生这样的代码:
Class.new do
private
def described_class
String
end
end
context
该方法当我写:
RSpec.context "when in a context" do
end
我希望能产生这样的代码:
Class.new do
end
subject
该方法当我写:
RSpec.describe ".subject" do
subject do
"foo"
end
end
我希望能产生这样的代码:
Class.new do
private
def subject
"foo"
end
end
describe
该方法当我写:
RSpec.describe ".describe" do
describe "embedded describe" do
end
end
我希望能产生这样的代码:
base = Class.new do
end
Class.new(base) do
end
let
该方法当我写:
RSpec.describe ".let" do
let(:answer_to_everything) { 41 + one }
let(:one) { 1 }
end
我希望能产生这样的代码:
Class.new do
private
def answer_to_everything
41 + one
end
def one
1
end
end
before
该方法当我写:
RSpec.describe ".before" do
before do
puts "hello"
end
end
我希望能产生这样的代码:
Class.new do
private
def initialize
puts "hello"
end
end
expect
该方法当我写:
RSpec.describe "#expect" do
it { expect(41.next).to be(42) }
end
我希望能产生这样的代码:
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) }
而且我希望看到这种信息:
Success: expected to be 42.
除非你不写测试,使用这样一个 DSL 接口的好处是,它限制了在规范中引入可能导致错误的额外逻辑,鼓励使用算法复杂度较低的良好的 Ruby 模式,并使 Ruby 代码更短,更(机器)可读。
RSpec 是一种特定领域的测试语言,而 minitest 是 Ruby。
我希望你喜欢RSpec clone,就像我喜欢这两样。谢谢你。