Rails测试《八》实战功能测试functional test2

简介:

今天继续我们的功能测试实战。

项目还是:blog,大家可以从github或者gitcafe中获取项目源码。

 

先来介绍一个断言

assert_difference(expression, difference = 1, message = nil, &block)

http://api.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html中比较详细的介绍。

 

 再一次强烈推荐http://api.rubyonrails.org/,还有http://ruby-doc.org/,还有http://apidock.com/,还有http://guides.rubyonrails.org/。这四个工具网站,真是好啊,谁用谁知道。

 

assert_difference的英文解释是

Test numeric difference between the return value of an expression as a result of what is evaluated in the yielded block.

 

直译的话就是

测试两个数值的区别。

哪两个数值呢,就是expression的数值。怎么变成一个了?不要着急,一个是block执行之前,一个是block执行之后。

 

意译一下就是

比较expression的数值在block执行前后的差,看这个差是否是difference 参数指定的值,这个参数是个可选参数,默认值是1。

也可以理解为,block执行之后的expression值 - block执行之前的expression值,看这个差值是否等于difference 指定的值,默认差值为1。

 

我们先来个简单例子说明一下。

就拿项目中的添加post来举例,对应的controller的代码如下:

 
  1. def create 
  2.     @category = Category.find(params[:post][:category_id]) 
  3.   
  4.     params[:post].delete(:category_id
  5.     @post = @category.posts.build(params[:post]) 
  6.     @post.user = current_user 
  7.     @post.tag_ids = params[:tag_ids
  8.     if @post.save! 
  9.       flash[:notice] = "post was created successfully" 
  10.       redirect_to admin_posts_path 
  11.     else 
  12.       flash.now[:notice] = "create post failed" 
  13.       render :new 
  14.     end 
  15.   end 

添加成功之后会跳转到posts列表,失败的话,就保留在new这个页面。

当然了,测试添加可以有很多方法。比如说添加之后,查询一下,看看是否存在。如果有标题唯一之类的验证,也可以再次添加相同的post,然后看看是否会提示已经存在。或者验证添加之后是否跳转到posts列表,是否输出正确添加的flash信息。

今天我们就是为了讲解assert_difference这个断言,前面说过了,这个断言用来判断block前后的expression的差。再添加一篇post之后,post的个数会增加一,我们就用这个断言来验证添加是否成功。

在test/functional/admin/posts_controller_test.rb文件中敲入下面的代码。

 
  1. require 'test_helper' 
  2.  
  3. class Admin::PostsControllerTest < ActionController::TestCase 
  4.  
  5.   include FactoryGirl::Syntax::Methods 
  6.   def test_should_create_post_successfully 
  7.     user = FactoryGirl.create(:user_valid) 
  8.     category = FactoryGirl.create(:category_valid) 
  9.   
  10.     article = FactoryGirl.build(:post_valid) 
  11.     tag = FactoryGirl.build(:tag_valid) 
  12.      
  13.  
  14.     assert_difference('Post.count') do    
  15.       post :create, {:post=>{:category_id=>category.id, 
  16.                              :title=>article.title, 
  17.                              :slug=>article.slug, 
  18.                              :summary=>article.summary, 
  19.                              :content=>article.content}, 
  20.                      :tag_ids => [tag.id]}, 
  21.                     {:user_id => user.id} 
  22.     end 
  23.  
  24.     assert_redirected_to admin_posts_path(assigns(:posts)) 
  25.  
  26.   end 
  27.  
  28. end 

在代码中我们使用了factory-girl模拟的数据。然后用功能测试提供的post方法想postscontroller的create方法提交了数据,因为我们添加post的过程需要用到当前用户的信息,当前用户的信息又是从session中获取的,所以在post方法中需要给session参数指定信息,使得session[:user_id]有值。

当然了,还有一种办法可以指定session的值。那就是通过@request这个变量,前面介绍functional test的时候讲过,我们有三个变量可以在功能测试中使用。

  • @controller
  • @request
  • @response

@response.session[:user_id]=user.id也可以实现设置session的作用,这样的话,就可以省略掉post方法中的session参数部分。

变成下面的样子。

 
  1. def test_should_create_post_successfully 
  2.     user = FactoryGirl.create(:user_valid
  3.     category = FactoryGirl.create(:category_valid
  4.     @request.session[:user_id] = user.id 
  5.     article = FactoryGirl.build(:post_valid
  6.     tag = FactoryGirl.build(:tag_valid
  7.      
  8.  
  9.     assert_difference('Post.count'do    
  10.       post :create, {:post=>{:category_id=>category.id, 
  11.                              :title=>article.title, 
  12.                              :slug=>article.slug, 
  13.                              :summary=>article.summary, 
  14.                              :content=>article.content}, 
  15.                      :tag_ids => [tag.id]} 
  16.     end 
  17.  
  18.     assert_redirected_to admin_posts_path(assigns(:posts)) 
  19.  
  20.   end 

具体哪个好,这个需要大家在使用的过程中慢慢揣摩吧。其实都不错,我觉得在不同的场景,使用不同的方式。

这个测试有两个断言,一个就是assert_difference,一个是assert_redirected_to。断言是否跳转的posts列表,并且传递了posts变量。

在功能测试中可以访问的四个hash分别是:

 
  1. flash["gordon"]               flash[:gordon
  2. session["shmession"]          session[:shmession
  3. cookies["are_good_for_u"]     cookies[:are_good_for_u
  4.   
  5. # Because you can't use assigns[:something] for historical reasons: 
  6. assigns["something"]          assigns(:something

在下面这个场景,我觉得使用@request.session来设置session,就要比写在post的参数中好。

 
  1. require 'test_helper' 
  2.  
  3. class Admin::CategoriesControllerTest < ActionController::TestCase 
  4.   include FactoryGirl::Syntax::Methods 
  5.  
  6.   def test_should_create_category_successfully 
  7.  
  8.     user = FactoryGirl.create(:user_valid
  9.     @request.session[:user_id] = user.id 
  10.  
  11.     category1 = build(:category_valid
  12.     category1.title = FactoryGirl.generate(:category_title
  13.  
  14.     category2 = build(:category_valid
  15.     category2.title = FactoryGirl.generate(:category_title
  16.  
  17.     assert_difference "Category.count", 2 do 
  18.       post :create, {:category => {:title => category1.title}} 
  19.       post :create, {:category => {:title => category2.title}} 
  20.  
  21.     end 
  22.   end 
  23. end 

好处就是只需要设置一次,如果是写在参数中,那么就需要写两次相同的代码,维护与修改就集中了。

其实还可以用它来测试delete方法,还是测试差值,删除前后的差值,只是这个值是否是-1。

和assert_difference对应的还有一个no_difference。

assert_no_difference(expression, message = nil, &block)

用来测试block前后,expression的数值是否没有发生变化。

比如说测试一下,当post的属性中有违反validates的,这时候添加肯定会失败,block前后的Post.count应该是没有变化的。

 

下面就是测试添加tag失败的例子,tag的title长度要大于3,空的title自然就是无效的tag。

 
  1. def test_should_create_tag_fail 
  2.    user = create(:user_valid
  3.    @request.session[:user_id] = user.id  
  4.  
  5.    assert_no_difference "Tag.count" do  
  6.      post :create, {:tag => { :title => ""}} 
  7.    end 
  8.  end 

 




本文转自 virusswb 51CTO博客,原文链接:http://blog.51cto.com/virusswb/1078404,如需转载请自行联系原作者

目录
相关文章
|
26天前
|
测试技术 持续交付 UED
软件测试的艺术:确保质量的实战策略
在软件开发的舞台上,测试是那把确保每个功能如交响乐般和谐奏响的指挥棒。本文将深入探讨软件测试的重要性、基本类型以及如何设计高效的测试策略。我们将通过一个实际的代码示例,展示如何运用这些策略来提升软件质量和用户体验。
|
1月前
|
JSON Java 测试技术
SpringCloud2023实战之接口服务测试工具SpringBootTest
SpringBootTest同时集成了JUnit Jupiter、AssertJ、Hamcrest测试辅助库,使得更容易编写但愿测试代码。
60 3
|
1月前
|
缓存 测试技术 Apache
告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
52 1
|
1月前
|
前端开发 数据管理 测试技术
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第27天】本文介绍了前端自动化测试中Jest和Cypress的实战应用与最佳实践。Jest适合React应用的单元测试和快照测试,Cypress则擅长端到端测试,模拟用户交互。通过结合使用这两种工具,可以有效提升代码质量和开发效率。最佳实践包括单元测试与集成测试结合、快照测试、并行执行、代码覆盖率分析、测试环境管理和测试数据管理。
57 2
|
1月前
|
前端开发 JavaScript 数据可视化
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第26天】前端自动化测试在现代软件开发中至关重要,Jest和Cypress分别是单元测试和端到端测试的流行工具。本文通过解答一系列问题,介绍Jest与Cypress的实战应用与最佳实践,帮助开发者提高测试效率和代码质量。
40 2
|
2月前
|
机器学习/深度学习 监控 计算机视觉
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
本文介绍了如何使用YOLOv7进行目标检测,包括环境搭建、数据集准备、模型训练、验证、测试以及常见错误的解决方法。YOLOv7以其高效性能和准确率在目标检测领域受到关注,适用于自动驾驶、安防监控等场景。文中提供了源码和论文链接,以及详细的步骤说明,适合深度学习实践者参考。
510 0
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
2月前
|
机器学习/深度学习 XML 并行计算
目标检测实战(七): 使用YOLOX完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
这篇文章介绍了如何使用YOLOX完成图像目标检测任务的完整流程,包括数据准备、模型训练、验证和测试。
223 0
目标检测实战(七): 使用YOLOX完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
2月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
73 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
3月前
|
移动开发 JSON Java
Jmeter实现WebSocket协议的接口测试方法
WebSocket协议是HTML5的一种新协议,实现了浏览器与服务器之间的全双工通信。通过简单的握手动作,双方可直接传输数据。其优势包括极小的头部开销和服务器推送功能。使用JMeter进行WebSocket接口和性能测试时,需安装特定插件并配置相关参数,如服务器地址、端口号等,还可通过CSV文件实现参数化,以满足不同测试需求。
259 7
Jmeter实现WebSocket协议的接口测试方法
|
3月前
|
JSON 移动开发 监控
快速上手|HTTP 接口功能自动化测试
HTTP接口功能测试对于确保Web应用和H5应用的数据正确性至关重要。这类测试主要针对后台HTTP接口,通过构造不同参数输入值并获取JSON格式的输出结果来进行验证。HTTP协议基于TCP连接,包括请求与响应模式。请求由请求行、消息报头和请求正文组成,响应则包含状态行、消息报头及响应正文。常用的请求方法有GET、POST等,而响应状态码如2xx代表成功。测试过程使用Python语言和pycurl模块调用接口,并通过断言机制比对实际与预期结果,确保功能正确性。
271 3
快速上手|HTTP 接口功能自动化测试