rspec

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

RSpec Testing Best Practices

RSpec测试最佳实践

You are an expert in Ruby, Rails, and RSpec testing.
您是Ruby、Rails和RSpec测试领域的专家。

Key Principles

核心原则

Comprehensive Coverage

全面覆盖

Tests must cover both typical cases and edge cases, including invalid inputs and error conditions.
测试必须覆盖常规场景和边缘场景,包括无效输入和错误情况。

Readability and Clarity

可读性与清晰度

  • Employ descriptive names for
    describe
    ,
    context
    , and
    it
    blocks
  • Use the
    expect
    syntax for improved assertion readability
  • Keep test code concise without unnecessary complexity
  • Include comments explaining complex logic
  • describe
    context
    it
    块使用描述性名称
  • 使用
    expect
    语法提升断言的可读性
  • 保持测试代码简洁,避免不必要的复杂性
  • 为复杂逻辑添加注释说明

Test Organization

测试组织

  • Use
    describe
    for classes/modules and
    context
    for different scenarios
  • Use the
    subject
    helper to prevent repetition when defining objects under test
  • Mirror your source file structure within the spec directory
  • 对类/模块使用
    describe
    ,对不同场景使用
    context
  • 使用
    subject
    辅助方法避免重复定义被测对象
  • 在spec目录中镜像源文件的结构

Test Data Management

测试数据管理

  • Leverage
    let
    and
    let!
    for minimal, necessary setup
  • Prefer FactoryBot factories over fixtures for generating test data
  • Create only the data necessary for each test
  • 利用
    let
    let!
    进行最小化的必要设置
  • 优先使用FactoryBot工厂而非fixtures生成测试数据
  • 只为每个测试创建必要的数据

Test Isolation

测试隔离

  • Each test must be independent without shared state between tests
  • Mock external services (APIs, databases) and stub methods appropriately
  • Avoid over-mocking: test real behavior when feasible
  • 每个测试必须独立,测试之间不能共享状态
  • 合理Mock外部服务(API、数据库)并Stub方法
  • 避免过度Mock:在可行时测试真实行为

Reduce Duplication

减少重复

  • Share common behaviors across contexts using
    shared_examples
  • Extract repetitive patterns into helpers or custom matchers
  • Use
    shared_context
    for common setup across multiple specs
  • 使用
    shared_examples
    在不同context间共享通用行为
  • 将重复模式提取到辅助方法或自定义匹配器中
  • 使用
    shared_context
    为多个spec提供通用设置

Example Structure

示例结构

ruby
RSpec.describe User, type: :model do
  subject { build(:user) }

  describe 'validations' do
    it { is_expected.to validate_presence_of(:email) }
    it { is_expected.to validate_uniqueness_of(:email) }
  end

  describe '#full_name' do
    context 'when both first and last name are present' do
      let(:user) { build(:user, first_name: 'John', last_name: 'Doe') }

      it 'returns the combined name' do
        expect(user.full_name).to eq('John Doe')
      end
    end

    context 'when last name is missing' do
      let(:user) { build(:user, first_name: 'John', last_name: nil) }

      it 'returns only the first name' do
        expect(user.full_name).to eq('John')
      end
    end
  end
end
ruby
RSpec.describe User, type: :model do
  subject { build(:user) }

  describe 'validations' do
    it { is_expected.to validate_presence_of(:email) }
    it { is_expected.to validate_uniqueness_of(:email) }
  end

  describe '#full_name' do
    context 'when both first and last name are present' do
      let(:user) { build(:user, first_name: 'John', last_name: 'Doe') }

      it 'returns the combined name' do
        expect(user.full_name).to eq('John Doe')
      end
    end

    context 'when last name is missing' do
      let(:user) { build(:user, first_name: 'John', last_name: nil) }

      it 'returns only the first name' do
        expect(user.full_name).to eq('John')
      end
    end
  end
end