RSpec 入门指南(Ruby)
RSpec 是 Ruby 生态常用的 BDD 测试框架,以"读起来像英语"的语法著称。本文讲解 RSpec 环境搭建、编写第一个测试、多用例扩展、用例过滤,以及 setup 与测试数据管理。
本文依据官方文档整理,未执行运行验证或性能基准。代码片段展示局部用法,业务函数、数据和环境需按项目补齐;版本与配置以所引文档为准。
直接回答:RSpec 是 Ruby 社区常用的测试框架,采用行为驱动(BDD)风格:describe/context/it 的自然语言式结构让测试读起来像需求文档,既是验证工具,也是设计工具——先想清"代码应该如何表现",再动手实现。
RSpec 的哲学
RSpec 把测试写成可执行的规格说明:
RSpec.describe Calculator do
it "两数相加返回和" do
expect(Calculator.new.add(1, 2)).to eq(3)
end
end
describe 圈定被测对象,it 描述一条行为期望,expect(...).to eq(...) 完成断言。测试失败时输出读起来像句子,这也是它深受团队喜爱的原因——测试即文档。
项目搭建
mkdir rspec-demo && cd rspec-demo
gem install rspec
rspec --init # 生成 spec/spec_helper.rb 与 .rspec
目录约定:被测代码放 lib/,测试放 spec/ 并以 _spec.rb 结尾。
第一个完整测试
lib/calculator.rb:
class Calculator
def add(a, b)
a + b
end
def divide(a, b)
raise ArgumentError, "除数不能为零" if b.zero?
a.to_f / b
end
end
spec/calculator_spec.rb:
require_relative "../lib/calculator"
RSpec.describe Calculator do
subject(:calc) { described_class.new }
it "正确相加" do
expect(calc.add(1, 2)).to eq(3)
end
it "除以零时抛出异常" do
expect { calc.divide(1, 0) }.to raise_error(ArgumentError, /不能为零/)
end
end
rspec 运行全部;rspec spec/calculator_spec.rb 指定文件。
扩展覆盖:组织多场景
用 context 区分前提条件,用 let 惰性准备数据:
RSpec.describe ShoppingCart do
let(:cart) { ShoppingCart.new }
context "空购物车" do
it "总额为 0" do
expect(cart.total).to eq(0)
end
end
context "加入两件商品" do
before { cart.add(100); cart.add(200) }
it "总额为 300" do
expect(cart.total).to eq(300)
end
end
end
let 是惰性求值(首次引用才执行),before(:each) 在每个用例前执行——区分求值时机有助于排查准备数据未创建的问题。
过滤与聚焦运行
rspec -e "两数相加" # 按描述过滤
rspec spec/x_spec.rb:12 # 精确到行号
代码里给用例加 fit(或 :focus 标签)临时聚焦,配 .rspec 里的 --tag focus 使用;提交前记得改回 it。
setup 与测试数据
before(:each):每条用例前执行,重建干净状态;before(:all):整组一次,只用于只读的重资源;let/let!:声明式数据准备,优先于 before 块散写变量;- 工厂数据推荐 FactoryBot,假数据推荐 Faker。
常见问题(FAQ)
Q:RSpec 和 Minitest 怎么选?
A:RSpec 表达力强、测试即文档,适合业务复杂、协作人多的项目;Minitest 使用普通Ruby类组织测试。Rails 默认 Minitest,但社区项目 RSpec 占比很高——看团队偏好,选定就保持一致。
Q:let 和实例变量有什么区别?
A:let 惰性、有缓存、语义清晰,是 RSpec 推荐方式;@ivar 在 before 里立即创建,用例没用上就是浪费。统一用 let。
Q:should 语法还能用吗?
A:旧式 obj.should 仍有可启用的兼容语法;默认未显式配置时可能提示弃用警告,不应说它完全移除。新代码建议 expect(obj).to eq(3)。存量项目可以配置 syntax = :expect 强制统一。
官方参考
资料核对日期:2026-09-29。