使用 RSpec 测试 Rails 应用

Introduction

RSpec 是 Ruby 中的一个测试框架,相比默认的测试框架 Test::Unit 而言,代码读起来更 Humanize

Install

在 Gemfile 中添加

group :development, :test do  # rspec-rails 依赖 rspec,因此会自动安装 rspec  # gem 'rspec'  gem 'rspec-rails'end

然后运行 bundle install ,最后使用 rails g rspec:install 初始化。

Run

# 运行所有测试文件bundle exec rspec# 运行目录下的所有测试文件bundle exec rspec spec/routing# 运行单个测试文件bundle exec rspec spec/routing/root_routing_spec.rb

也可以使用 Guard 自动运行测试文件

Routing Specs

Routing Spec 用来测试 config/routes.rb 的编写是否符合预期:

通过访问 URL 能否抵达期望的 controlleraction ,参数是否被正确的解析,通常使用 route_to(controller: '#', action: '#', param1: '#', param2: '#') 来测试。 测试某条路由是否能访问,通常使用 be_routable 来测试。

相关的测试文件放在 spec/routing 下。

Tips :

指定 URL 时可以直接指定路径 /sign_in ,也可以使用命名路由 sign_in_path 指定预期时可以使用 Hash { controller: '#', action: '#' } ,也可使用简写 controller#action代码示例

sessions_spec.rb

require 'rails_helper'RSpec.describe 'sessions#new' do    path = get sign_in_path    expect(path).to route_to(controller: 'sessions', action: 'new')  end  it 'routes /sign_in via post to sessions#create' do    path = post sign_in_path    expect(path).to route_to(controller: 'sessions', action: 'create')  end  it 'routes /sign_out via delete to sessions#destroy' do      path = delete sign_out_path      expect(path).to route_to(controller: 'sessions', action: 'destroy')  end  it 'cannot routes /sign_out via get' do      expect(get: sign_out_path).not_to be_routable  endend

Model Specs

相关测试文件放在 spec/models

user_spec.rb

require 'rails_helper'RSpec.describe User, type: :model do  it 'generate a name if no name provided' do      user = User.create!(        account: 'user1', password: 'user1', password_confirmation: 'user1'      )      expect(user.name).to eq(user.account)  endend

post_spec.rb

require 'rails_helper'RSpec.describe Post, type: :model do  it 'has correct relationship' do      post1 = Post.create!(title: 'Post 1', slug: 'post-1', body: 'Post 1')      post2 = Post.create!(title: 'Post 2', slug: 'post-2', body: 'Post 2')      post3 = Post.create!(title: 'Post 3', slug: 'post-3', body: 'Post 3')      expect(post1.prev).to be_nil      expect(post1.next).to eq(post2)      expect(post2.prev).to eq(post1)      expect(post2.next).to eq(post3)      expect(post3.prev).to eq(post2)      expect(post3.next).to be_nil      expect(Post.recent).to eq([post3, post2, post1])  end  it 'is replyable' do    post = Post.create!(title: 'Replyable post', slug: 'replyable-post', body: 'Replyable post')    reply1 = post.replies.create(author: 'reply1', email: 'reply1@reply.com', body: 'Reply 1')    reply2 = post.replies.create(author: 'reply2', email: 'reply2@reply.com', body: 'Reply 2')    expect(post.replies).to eq([reply1, reply2])  endend

Controller Specs

用来测试 controller 的行为是否符合预期,比如:

是否按照预期进行了 redirect_to=,使用 =redirect_to 测试 是否 render 了预期的 template=,使用 =render_template 测试 是否设置了预期的 cookie=,使用 =resonse.cookie 是否返回了预期的 http 状态码,使用 response.status 或者 has_http_status 测试

相关的测试文件放在 spec/controllers

posts_controller_spec

require 'rails_helper'RSpec.describe PostsController, type: :controller do  describe 'Get #index' do    it 'return success' do        get :index        expect(response).to be_success        expect(response).to have_http_status(200)    end    it 'render the index template' do        get :index        expect(response).to render_template(:index)    end  endend

匿名 Controller

使用 controller 创建一个继承自当前所 describecontroller 的匿名 controller=,使用 =controller(BaseController) 可指定父类,通常用来测试异常。

require 'rails_helper'RSpec.describe ApplicationController, type: :controller do  describe 'Get #index' do    it 'return a 202 status code' do      expect(get :index).to have_http_status(202)    end    it 'return text' do      get :index      expect(response.body).to eq('application#index')    end  endend

Helper Specs

使用 helper 来访问定义在 helper 中的方法,比如:

module ApplicationHelper  def gravatar_url_for(email, size = 30, options = {})    digest = Digest::MD5.hexdigest(email.downcase)      "http://gravatar.com/avatar/#{digest}.png?s=#{size}"  endend
require 'rails_helper'RSpec.describe ApplicationHelper, type: :helper do  describe '#gravatar_url_for' do    it 'return an gravatar image url for given email' do        email = 'test@example.com'        size = 40        expect(helper.gravatar_for(email, 40)).to eq(          "http://gravatar.com/avatar/#{Digest::MD5.hexdigest(email)}.png?s=40"        )    end  endend
使用 RSpec 测试 Rails 应用

相关文章:

你感兴趣的文章:

标签云: