基于rails的schedule网站开发(15):学习如何测试
来源:互联网 发布:网络施工分成协议书 编辑:程序博客网 时间:2024/05/29 08:02
abstract:
登录-失败!:
1. <9.1.3>”编辑失败“测试
test "unsuccessful edit" do get edit_user_path(@user) patch user_path(@user), user: { name: '', email: '', password: 'foo', password_confirmation: 'bar' } assert_template 'users/edit' end
测试结果:
moses@moses-virtual-machine:~/projects/compass_v1.1$ bundle exec rake testStarted FAIL["test_unsuccessful_edit", UsersEditTest, 0.604847775] test_unsuccessful_edit#UsersEditTest (0.60s) expecting <"users/edit"> but rendering with <[]> test/integration/users_edit_test.rb:17:in `block in <class:UsersEditTest>' 14/14: [=================================] 100% Time: 00:00:00, Time: 00:00:00Finished in 0.70103s14 tests, 37 assertions, 1 failures, 0 errors, 0 skips
2. <9.1.4>”编辑成功“测试
test "successful edit" do get edit_user_path(@user) name = "Foo Bar" email = "foo@bar.com" patch user_path(@user), user: { name: name, email: email, password: "", password_confirmation: "" } assert_not flash.empty? assert_redirected_to @user @user.reload assert_equal @user.name, name assert_equal @user.email, email end
测试结果:
moses@moses-virtual-machine:~/projects/compass_v1.1$ bundle exec rake testStarted FAIL["test_successful_edit", UsersEditTest, 0.238506237] test_successful_edit#UsersEditTest (0.24s) Expected response to be a redirect to <http://www.example.com/users/762146111> but was a redirect to <http://www.example.com/login>. Expected "http://www.example.com/users/762146111" to be === "http://www.example.com/login". test/integration/users_edit_test.rb:19:in `block in <class:UsersEditTest>' 14/14: [=================================] 100% Time: 00:00:00, Time: 00:00:00Finished in 0.67668s14 tests, 39 assertions, 1 failures, 0 errors, 0 skips
错误1和错误2涉及到8.4.6节的log_in_as方法
注册信息有效性测试:
1. 邮件格式测试
test/models/user_test.rb
require 'test_helper'class UserTest < ActiveSupport::TestCase def setup @user = User.new(name: "Example User", email: "user@example.com") end . . . test "email validation should accept valid addresses" do valid_addresses = %w[user@example.com USER@foo.COM A_US-ER@foo.bar.org first.last@foo.jp alice+bob@baz.cn] valid_addresses.each do |valid_address| @user.email = valid_address assert @user.valid?, "#{valid_address.inspect} should be valid" end endend
使用%w[]创建“邮箱地址”的数组 assert @user.valid?, "#{valid_address.inspect} should be valid"
中inspect 方法,返回被调用对象的字符串字面量表现形式
例如:
>> puts (1..5).to_a # 把值域转换成数组12345>> puts (1..5).to_a.inspect # 输出数组的字面量形式[1, 2, 3, 4, 5]>> puts :name, :name.inspectname:name>> puts "It worked!", "It worked!".inspectIt worked!"It worked!"
2. 唯一性验证
拒绝重复电子邮件地址的测试 RED
test/models/user_test.rb
require 'test_helper'class UserTest < ActiveSupport::TestCase def setup @user = User.new(name: "Example User", email: "user@example.com") end . . . test "email addresses should be unique" do duplicate_user = @user.dup @user.save assert_not duplicate_user.valid? endend
这里使用@user.dup 方法创建一个和 @user 的电子邮件地址一样的用户对象,然后保存 @user,因为数据库中的 @user 已经占用了这个电子邮件地址,所有 duplicate_user 对象无效。
注册测试:
生成测试文件: $ rails generate integration_test users_signup
进行测试: $ bundle exec rake test
1. 注册失败的测试
第一个测试文件:
test/integration/users_signup_test.rb
require 'test_helper'class UsersSignupTest < ActionDispatch::IntegrationTest test "invalid signup information" do get signup_path assert_no_difference 'User.count' do post users_path, user: { name: "", email: "user@invalid", password: "foo", password_confirmation: "bar" } end assert_template 'users/new' endend
get 方法访问注册页面 get signup_path
用assert_no_difference方法判断提交的数据是否改变 assert_no_difference 'User.count'
即,User.count有没有增加,借此来反应用户注册有没有成功。
2. 注册成功的测试
第二个测试文件:
test/integration/users_signup_test.rb
require 'test_helper'class UsersSignupTest < ActionDispatch::IntegrationTest . . . test "valid signup information" do get signup_path name = "Example User" email = "user@example.com" password = "password" assert_difference 'User.count', 1 do post_via_redirect users_path, user: { name: name, email: email, password: password, password_confirmation: password } end assert_template 'users/show' endend
对比第一个测试文件
assert_no_difference 'User.count' do post users_path, ...end
第二个测试文件中的assert_difference方法
assert_difference 'User.count', 1 do post_via_redirect users_path, ...end
指的是观察“指定变化的数量”,第二个参数可选,这里是1。
post_via_redirect 方法,目的是提交数据后继续跟踪重定向
登录测试:
生成测试文件: $ rails generate integration_test users_login
测试指定文件:指定 TEST 参数和文件的完整路径,演示如何只运行一个测试文件 $ bundle exec rake test TEST=test/integration/users_login_test.rb
1. 注册失败的测试
捕获继续显示闪现消息的测试
test/integration/users_login_test.rb
require 'test_helper'class UsersLoginTest < ActionDispatch::IntegrationTest test "login with invalid information" do get login_path assert_template 'sessions/new' post login_path, session: { email: "", password: "" } assert_template 'sessions/new' assert_not flash.empty? get root_path assert flash.empty? endend
assert_template 方法检查首页是否使用正确的视图渲染
assert_not 方法确认得到的用户对象是无效的
2. 测试布局中的变化
测试步骤:
1. 访问登录页面;
2. 通过 post 请求发送有效的登录信息;
3. 确认登录链接消失了;
4. 确认出现了退出链接;
5. 确认出现了资料页面链接。
为了检查这些变化,在测试中要登入已经注册的用户,也就是说数据库中必须有一个用户。Rails 默认使用“固件”实现这种需求。固件是一种组织数据的方式,这些数据会载入测试数据库。
目前,我们只需要一个用户,它的名字和电子邮件地址应该是有效的。因为我们要登入这个用户,所以还要提供正确的密码,和提交给会话控制器中 create 动作的密码比较。
要先理解:
password_digest
密码摘要使用 bcrypt 生成(通过 has_secure_password 方法),所以固件中的密码摘要也要使用这种方法生成。查看安全密码的源码后,我们发现生成摘要的方法是:
BCrypt::Password.create(string, cost: cost)
其中,string 是要计算哈希值的字符串;cost 是“耗时因子”,决定计算哈希值时消耗的资源。耗时因子的值越大,由哈希值破解出原密码的难度越大。这个值对生产环境的安全防护很重要,但在测试中我们希望 digest 方法的执行速度越快越好。安全密码的源码中还有这么一行代码:
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
这行代码的作用是严格实现前面的分析:在测试中耗时因子使用最小值,在生产环境则使用普通(最大)值。
digest 方法可以放在几个不同的地方,这里放在 user.rb 中。
# 返回指定字符串的哈希摘要 def User.digest(string) cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost BCrypt::Password.create(string, cost: cost) end
定义好 digest 方法后,我们可以创建一个有效的用户固件了
测试用户登录所需的固件
test/fixtures/users.yml
michael: name: Michael Example email: michael@example.com password_digest: <%= User.digest('password') %>
使用 <%= User.digest('password') %>
创建密码摘要
我们虽然定义了 has_secure_password 所需的 password_digest 属性,但有时也需要使用密码的原始值。可是,在固件中无法实现,如果添加 password 属性,Rails 会提示数据库中没有这个列(确实没有)。所以,我们约定固件中所有用户的密码都一样,即 ‘password’。
创建了一个有效用户固件后,在测试中可以使用下面的方式获取这个用户:
user = users(:michael)
测试使用有效信息登录的情况
test/integration/users_login_test.rb
require 'test_helper'class UsersLoginTest < ActionDispatch::IntegrationTest def setup @user = users(:michael) end . . . test "login with valid information" do get login_path post login_path, session: { email: @user.email, password: 'password' } # assert_redirected_to @user 检查重定向的地址是否正确; assert_redirected_to @user # follow_redirect! 访问重定向的目标地址。 follow_redirect! assert_template 'users/show' # 测试login_path链接数为0 assert_select "a[href=?]", login_path, count: 0 # 测试logout_path链接数为1 assert_select "a[href=?]", logout_path assert_select "a[href=?]", user_path(@user) endend
- 基于rails的schedule网站开发(15):学习如何测试
- 基于rails的schedule网站开发(10):Rails 环境
- 基于rails的schedule网站开发(3):如何使用MySql开发(?)
- 基于rails的schedule网站开发(8):撤销操作
- 基于rails的schedule网站开发(9):一些疑惑
- 基于rails的schedule网站开发(11):记住我
- 基于rails的schedule网站开发(17):动态流
- 基于rails的schedule网站开发(1):安装git并用git管理Rails程序
- 基于rails的schedule网站开发(2):Rails and Git 常用命令
- 基于rails的schedule网站开发(6):我的博客模板
- 基于rails的schedule网站开发(12):index View页面的重构
- 基于rails的schedule网站开发(16):可以继续研究的内容
- 基于rails的schedule网站开发(4):git 存档记录
- 基于rails的schedule网站开发(5):使用password_digest设置密码
- 基于rails的schedule网站开发(7):部署到heroku
- 基于rails的schedule网站开发(13):用send 方法改写authenticated?(...)
- 基于rails的schedule网站开发(14):第一次使用git stash
- 基于rails的schedule网站开发(19):新的远程仓库,新的部署,远程分支使用
- AndroidStudio导出Jar包
- AdaGrad理解错误更正
- ps_3_0 does not allow textures or samplers to be members of compound types
- HDU 2870 Largest Submatrix (求最大子矩阵变形,可变值)枚举每种情况
- android 全屏对话框
- 基于rails的schedule网站开发(15):学习如何测试
- igs08核心站
- UCOS-II的动态内存管理
- 数字下变频的一种新型设计方法
- Android看门狗
- 浅谈Linux内存管理机制
- 蓝桥杯学习笔记——世纪末的星期
- Java课程设计-学籍信息管理系统
- eclipse 安装 markplace出现org.eclipse.equinox.p2.discovery.feature.feature.group错误