要帮朋友的项目搭一套测试环境,选用了 rspec 作为测试环境,在搭建的过程中记录整个过程,以后让这种重复的工作简单点,不想又造轮子。
由于guard
的安装需要高版本的 ruby 支持,建议使用 ruby 2.3.0 以上。
首先安装rspec
这个 gem,我们选用的是适合 rails 项目的rspec-rails这个 gem。
在 Gemfile 文件里加入下面这几行:
group :development, :test do
gem 'rspec-rails', '~> 3.4'
end
执行bundle install
安装。
装好之后,执行下面的两行命令,生成必要的配置文件。
rails generate rspec:install
bundle binstubs rspec-core
factory_girl_rails是一个代替测试夹具 (Fixtures) 的工具,用它可以在测试的时候造一些实例。
group :development, :test do
gem 'factory_girl_rails'
end
执行bundle install
安装。
接下来找到spec/rails_helper.rb
文件的下面一行,把其删除或注释掉。
config.use_transactional_fixtures = true
并且增加下面一行。
config.include FactoryGirl::Syntax::Methods
再到config/application.rb
文件中,添加下面几行:
config.generators do |g|
g.test_framework :rspec,
fixtures: true,
view_specs: false,
helper_specs: false,
routing_specs: false,
request_specs: false
g.fixture_replacement :factory_girl, dir: 'spec/factories'
end
为了方便后绪的 demo 测试,现在我们都可以生成一个夹具文件,名字叫users.rb
,位于spec/factories
。
FactoryGirl.define do
factory :user do
email '[email protected]'
username 'name'
password 'password'
end
end
database_cleaner是一个自动清除数据库数据的工具,每次运行完测试用例它就会自动清除数据库。
在Gemfile
中添加下面几行。
group :test do
gem 'database_cleaner'
end
执行bundle install
安装。
然后在spec/rails_helper.rb
文件中添加下面几行:
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
config.around(:each) do |example|
DatabaseCleaner.cleaning do
example.run
end
end
到现在为止,已经能够正常跑测试了,我们来写一个测试案例,让它跑起来。
新建文件spec/models/user_spec.rb
,内容如下:
require 'rails_helper'
RSpec.describe User, type: :model do
let(:user) { create :user }
describe '#email' do
context '有效的邮箱' do
addresses = %w( [email protected] [email protected] [email protected] [email protected] )
addresses.each do |valid_address|
let(:user) { build(:user, email: valid_address) }
it { expect(user.valid?).to eq true }
end
end
context '空' do
let(:user) { build(:user, email: '') }
it { expect(user.valid?).to eq false }
end
context '错误邮箱格式' do
addresses = %w{ invalid_email_format 123 $$$ () ☃ bla@bla. }
addresses.each do |invalid_address|
let(:user) { build(:user, email: invalid_address) }
it { expect(user.valid?).to eq false }
end
end
context '重复' do
let(:user_with_same_username) { build :user, username: user.username }
it { expect(user_with_same_username.valid?).to eq false }
end
end
end
可以使用bundle exec rspec spec/models/user_spec.rb
来测试这个刚才写的测试案例。
你会发现运行起来还是比较慢的。
接下来我们使用spring
来加速测试的运行。
spring
是 rails 默认就有的,而spring-commands-rspec是让spring
和rspec
结合起来。
在Gemfile
中添加下面这行:
gem 'spring-commands-rspec', group: :development
接着执行bundle exec spring binstub rspec
这条指令。
现在我们就可以使用bundle exec spring rspec
来加速测试的运行了。
guard是一个让你一修改测试文件,就自动跑测试的工具。
需要注意的是guard
需要高版本的 ruby 支持,目前为止,它官方写的是至少需要 ruby 2.2.5 以上
在Gemfile
中添加下面几行:
group :development do
gem 'guard'
gem 'guard-rspec', require: false
gem 'guard-bundler', require: false
end
至于guard-rspec
和guard-bundler
是guard
的两个插件,是分别让guard
和rspec
还有bundler
结合。
分别执行下面几行指令。
bundle exec guard init
bundle exec guard init rspec
bundle exec guard init bundler
接着找到Guardfile
文件,找到第一行未注释的代码,修改成类似下面这样。
guard :rspec, cmd: 'spring rspec', all_on_start: true do
现在可以运行bundle exec guard
执行测试了,也能监控文件的更改,测试文件一旦有修改,也会马上运行测试。
让spring
和guard
结合之后,运行测试是很快的。
capybara是一个可以编写 feature 测试的工具,它可以编写 BDD 测试、模拟浏览器点击,填充表单的测试功能。
在Gemfile
中添加下面一行:
group :development, :test do
gem 'capybara'
end
执行bundle install
安装。
安装完之后,找到spec/rails_helper.rb
文件添加下面一行:
require 'capybara/rails'
现在我们可以编写一个 feature 测试案例。
文件名为spec/features/login_spec.rb
。
require 'rails_helper'
describe '登录功能', type: :feature do
let(:user) { create(:user) }
before { visit new_user_session_path }
it { expect(page).to have_selector('h1', text: '登录') }
it '没有填任何信息就点登录' do
click_button '登录'
expect(page).to have_content('登录账号或密码错误')
end
it '输入邮箱成功登录' do
within('#new_user') do
fill_in 'user_login', with: user.email
fill_in 'user_password', with: user.password
end
click_button '登录'
expect(page).to have_content '登录成功'
expect(page).to have_current_path(root_path)
end
it '输入用户名成功登录' do
within('#new_user') do
fill_in 'user_login', with: user.username
fill_in 'user_password', with: user.password
end
click_button '登录'
expect(page).to have_content '登录成功'
expect(page).to have_link('注销')
expect(page).to have_current_path(root_path)
end
it '密码错误的失败登录' do
within('#new_user') do
fill_in 'user_login', with: user.email
fill_in 'user_password', with: 'wrong_password'
end
click_button '登录'
expect(page).to have_content '登录账号或密码错误'
expect(page).to have_current_path(user_session_path)
end
end
现在整个测试环境都搭建好了,接下来就是尽情地写测试就可以了。
本篇完结。