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。

延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台