1.为什么写测试
rails使得我们很容易就可以写测试。在创建model和controller的时候,rails帮助我们创建了测试的骨架代码。
通过简单的运行你的测试代码,你可以确保你的代码在重构之后任然满足需求的功能。
rails测试可以模拟浏览器请求,这样你就可以在不适用浏览器的情况下测试应用的响应情况。

2.测试简介
因为每一个rails应用都会和数据库有大量的交互,因此你的测试也需要一个数据库来进行交互。为了更好的写测试,你需要知道如何建立数据库,以及加载样本数据。

2.1.三个环境
每个rails应用都有三个环境:生产,开发,测试。

在config/database.yml文件中包含这三个环境的数据库设置。

如果你想要在测试数据库中进行数据操作,你需要将开发环境的数据库结构映射到测试环境。你可以执行下面的命令。
 

 
  
  1. rake db:test:prepare 




2.2.测试文件夹结构
在你使用rails new命令创建应用的时候,rails会帮你创建一个test文件夹,文件夹包含下面的内容。

 

 
  
  1. root@web:/home/railsapp/login# ls -F test/ 
  2. fixtures/  functional/  integration/  performance/  test_helper.rb  unit/ 



unit文件夹存放针对model的测试,functional文件夹存放针对controller的测试,integration文件夹存放针对controller之间交互的测试,fixtures文件夹用来组织测试数据。test_helper.rb保存测试环境的配置信息。

2.3.Fixtures的内幕
一个好的测试,你需要建立一些测试数据。在rails中,你可以通过自定义fixtures来实现。

2.3.1.什么是fixtures
fixtures允许你在测试运行之前,使用预定义的数据填充测试数据库。fixtures是数据库无关的,它是一种yaml格式。

当你使用rails g model创建新model的时候,就会在fixtures文件夹自动创建一个fixtures。

2.3.2.YAML
yaml对人是一种非常友好的描述数据的格式。这些fixtures的后缀是.yml。例如,users.yml。


 

 
  
  1. # lo & behold!  I am a YAML comment! 
  2. david: 
  3.  name: David Heinemeier Hansson 
  4.  birthday: 1979-10-15 
  5.  profession: Systems development 
  6.   
  7. steve: 
  8.  name: Steve Ross Kellock 
  9.  birthday: 1974-09-27 
  10.  profession: guy with keyboard 



2.3.3.内嵌erb
在yml中也可以内嵌ruby代码,在加载fixtures之前会进行预处理。

下面的yml中就定义了一个变量earch_size。

 
  
  1. <earth_size = 20 %> 
  2. mercury: 
  3.   size: <%= earth_size / 50 %> 
  4.   brightest_on: <%= 113.days.ago.to_s(:db) %> 
  5.   
  6. venus: 
  7.   size: <%= earth_size / 2 %> 
  8.   brightest_on: <%= 67.days.ago.to_s(:db) %> 
  9.   
  10. mars: 
  11.   size: <%= earth_size - 69 %> 
  12.   brightest_on: <%= 13.days.from_now.to_s(:db) %> 



ruby代码包含在<% %>中。

2.3.4.fixtures实践
rails会自动加载fixtures文件夹中的所有fixtures。加载的步骤包括:

  • 首先删除表中已经存在的fixtures中的数据。
  • 将fixtures中的数据加载到table中。
  • 当fixtures数据加载到变量,你可以直接通过变量来访问数据。

加入你有一个前面写的uses.yml文件,就可以通过hash的形式来获取用户信息。

 
  
  1. user = users(:david

进而获取user的各种信息。

 
  
  1. user.name 
  2. user.birthday 
  3. user.profession 



3.针对model的单元测试
在rails中,单元测试就是用来测试model的。

当你使用rails g model或者rails g scaffod命令的时候,会自动在test/unit中生成对应的单元测试。

 

 
  
  1. # test/unit/post_test.rb 
  2. require 'test_helper' 
  3.   
  4. class PostTest < ActiveSupport::TestCase 
  5.   # Replace this with your real tests. 
  6.   test "the truth" do 
  7.     assert true 
  8.   end 
  9. end 



请注意测试类继承ActiveSuppoort::TestCase。

 

 
  
  1. def test_the_truth 
  2.  
  3.   assert true 
  4.  
  5. end 



所有test开头的方法都会被认为是一个测试,也就是说所有的测试方法都必须以test开头。test_password,test_valid_password,testpa***od都是合法的测试名称,都会在测试的时候自动运行。

3.1.做好测试准备
在运行测试之前,你需要确保测试数据库的结构和开发环境一致。
 

 
  
  1. rake db:migrate 
  2. rake db:test:load 



rake db:migrate用来生成开发环境的数据库,并且更新db/schema.rb文件。rake db:test:load会根据db/schema.rb重新创建测试数据库。你也可以执行rake db:test:prepare。

3.2.运行测试
 

 
  
  1. $ ruby -Itest test/unit/post_test.rb 
  2.  
  3. Loaded suite unit/post_test 
  4. Started 
  5. Finished in 0.023513 seconds. 
  6.   
  7. 1 tests, 1 assertions, 0 failures, 0 errors 



你也可以通过-n参数来制定运行的测试。

 

 

 
  
  1. rake test TEST = test/unit/user_test.rb 
 
  
  1. ruby -Itest test/unit/post_test.rb -n test_the_truth 



4.测试controller的功能测试

4.1功能测试包含的内容

  • web请求成功了吗?
  • user被转到正确的页面了吗?
  • 用户是否authenticate成功?
  • 响应中包含的对象是否正确?
  • 是否在view中给用户显示了正确的内容?

 

4.2在功能测试中可以用到的请求类型

get
post
put
delete
head

4.3可以使用的四个哈希


assign
cookies
flash
session

4.4可以使用的实例

@controller,处理请求的controller。
@request,请求。
@response,响应。

5.集成测试
集成测试用来测试多个controller之间的交互。

 
  
  1. rails g integration_test user_flows 


 

 
  
  1. # test/integration/user_flows_test.rb 
  2. require 'test_helper' 
  3.   
  4. class UserFlowsTest < ActionDispatch::IntegrationTest 
  5.   fixtures :all 
  6.   
  7.   # Replace this with your real tests. 
  8.   test "the truth" do 
  9.     assert true 
  10.   end 
  11. end