Rails4新项目的测试:minitest + capybara测试基于devise的用户注册
23 Nov 2015没有测试就会让写程序的开发者没有自信
这次的新项目没有想当然的选择之前一直在用Rspec测试框架,主要是我感觉Rspec里面有太多的magic,在helper文件中很多tricks, 很快相关的配置文件就非常大。这篇Blog说的跟我的体会很像 7 REASONS I’M STICKING WITH MINITEST AND FIXTURES IN RAILS
minitest是Rails4后默认支持的测试框架,另外rails也提供了很多方便和强大的assert方法。可以参考官方文档
下面我就总结和分享一下,Rails4新项目中minitest和capybara的集成和配置:
Gemfile
group :test do
gem "minitest-reporters"
gem 'capybara'
gem "connection_pool"
gem "launchy"
gem "selenium-webdriver"
gem "mocha"
gem "poltergeist"
gem 'phantomjs', :require => 'phantomjs/poltergeist'
end
minitest-reporters
是为了美化minitest的测试结果输出地,有颜色,有百分比。mocha
是一个方便进行mock和stub的工具- 其他几个都是跟capybara相关的工具,具体会在配置中看到。
test_helper中添加的配置内容
在这里创建一个继承自新ActionDispatch::IntegrationTest的FeatureTest类,然后引入Capybara::DSL,作为Feature测试的父类。
require "mocha/mini_test"
require "capybara/rails"
require "capybara/poltergeist"
# 注释掉默认的driver,打开后方便切换driver测试,也可以在代码中指定current_driver
# Capybara.default_driver = :selenium
# Capybara.default_driver = :poltergeist
Capybara.javascript_driver = :poltergeist
class FeatureTest < ActionDispatch::IntegrationTest
# 可以在功能测试中使用capybara的DSL
include Capybara::DSL
# 默认的失败测试提示不是很有用,扩展后方便调试
def assert_content(content)
assert page.has_content?(content), %Q{Expected to found "#{content}" in: "#{page.text}"}
end
def refute_content(content)
refute page.has_content?(content), %Q{Expected not to found "#{content}" in: "#{page.text}"}
end
end
# See: https://gist.github.com/mperham/3049152
class ActiveRecord::Base
mattr_accessor :shared_connection
@@shared_connection = nil
def self.connection
@@shared_connection || ConnectionPool::Wrapper.new(:size => 1) { retrieve_connection }
end
end
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
测试确认邮件
如果要测试邮件的内容,内容中一般都会有链接,所以需要在config/environments/test.rb中加上:
config.action_mailer.default_url_options = { host: '127.0.0.1', port: 3000 }
如果使用了delayed_job可以在其配置中加上:
Delayed::Worker.delay_jobs = !Rails.env.test?
表明测试环境下,邮件任务都是直接发送出去的
用户注册和确认邮件测试的样例代码
在test目录下面,新建features目录,专门存放网站功能测试代码
test/features/user_authentication_test.rb
require 'test_helper'
class UserAuthenticationTest < FeatureTest
setup do
ActionMailer::Base.deliveries.clear
end
test 'user can sign up with email and password' do
visit new_user_registration_path
assert_content "注册帐号"
within '#new_user' do
fill_in 'user[email]', with: 'test_user@gmail.com'
fill_in 'user[password]', with: 'abcd1234'
click_button '创建新帐号'
end
assert_equal sign_up_success_path, page.current_path
assert_content "test_user@gmail.com"
test_confirm_email
end
private
def test_confirm_email
assert_not ActionMailer::Base.deliveries.empty?
cf_email = ActionMailer::Base.deliveries.last
assert_equal ["support@guangchuan.com"], cf_email.from
assert_equal ['test_user@gmail.com'], cf_email.to
assert_equal '确认信息', cf_email.subject
assert_match /Confirm my account/, cf_email.body.to_s
end
end
所以可以看到用minitest写的代码都非常直接,都是纯ruby代码。等代码增多后,可以按照ruby的方式来组织,重用和重构。