基于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
0 0
原创粉丝点击