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,如需转载请自行联系原作者

目录
相关文章
|
15天前
|
存储 关系型数据库 测试技术
玩转n8n测试自动化:核心节点详解与测试实战指南
n8n中节点是自动化测试的核心,涵盖触发器、数据操作、逻辑控制和工具节点。通过组合节点,测试工程师可构建高效、智能的测试流程,提升测试自动化能力。
|
2月前
|
Web App开发 人工智能 JavaScript
主流自动化测试框架的技术解析与实战指南
本内容深入解析主流测试框架Playwright、Selenium与Cypress的核心架构与适用场景,对比其在SPA测试、CI/CD、跨浏览器兼容性等方面的表现。同时探讨Playwright在AI增强测试、录制回放、企业部署等领域的实战优势,以及Selenium在老旧系统和IE兼容性中的坚守场景。结合六大典型场景,提供技术选型决策指南,并展望AI赋能下的未来测试体系。
|
2月前
|
存储 人工智能 算法
AI测试平台实战:深入解析自动化评分和多模型对比评测
在AI技术迅猛发展的今天,测试工程师面临着如何高效评估大模型性能的全新挑战。本文将深入探讨AI测试平台中自动化评分与多模型对比评测的关键技术与实践方法,为测试工程师提供可落地的解决方案。
|
2月前
|
人工智能 缓存 测试技术
Playwright进阶指南 (6) | 自动化测试实战
2025企业级测试解决方案全面解析:从单元测试到千级并发,构建高可用测试体系。结合Playwright智能工具,解决传统测试维护成本高、环境依赖强、执行效率低等痛点,提升测试成功率,内容从测试架构设计、电商系统实战框架、高级测试策略、Docker化部署、CI/CD集成及AI测试应用,助力测试工程师掌握前沿技术,打造高效稳定的测试流程。
Playwright进阶指南 (6) | 自动化测试实战
|
20天前
|
人工智能 数据可视化 测试技术
AI 时代 API 自动化测试实战:Postman 断言的核心技巧与实战应用
AI 时代 API 自动化测试实战:Postman 断言的核心技巧与实战应用
264 11
|
2月前
|
资源调度 前端开发 JavaScript
Jest 测试实战指南
本文系统讲解如何使用 Jest 进行高效的 JavaScript 函数测试,涵盖环境搭建、测试用例编写、模拟函数与快照测试等内容,帮助开发者提升代码质量与测试效率。
|
2月前
|
人工智能 缓存 监控
大模型性能测试实战指南:从原理到落地的全链路解析
本文系统解析大模型性能测试的核心方法,涵盖流式响应原理、五大关键指标(首Token延迟、吐字率等)及测试策略,提供基于Locust的压测实战方案,并深入性能瓶颈分析与优化技巧。针对多模态新挑战,探讨混合输入测试与资源优化
|
4月前
|
Java 测试技术 容器
Jmeter工具使用:HTTP接口性能测试实战
希望这篇文章能够帮助你初步理解如何使用JMeter进行HTTP接口性能测试,有兴趣的话,你可以研究更多关于JMeter的内容。记住,只有理解并掌握了这些工具,你才能充分利用它们发挥其应有的价值。+
747 23
|
9月前
|
数据可视化 前端开发 测试技术
接口测试新选择:Postman替代方案全解析
在软件开发中,接口测试工具至关重要。Postman长期占据主导地位,但随着国产工具的崛起,越来越多开发者转向更适合中国市场的替代方案——Apifox。它不仅支持中英文切换、完全免费不限人数,还具备强大的可视化操作、自动生成文档和API调试功能,极大简化了开发流程。
|
6月前
|
SQL 安全 测试技术
2025接口测试全攻略:高并发、安全防护与六大工具实战指南
本文探讨高并发稳定性验证、安全防护实战及六大工具(Postman、RunnerGo、Apipost、JMeter、SoapUI、Fiddler)选型指南,助力构建未来接口测试体系。接口测试旨在验证数据传输、参数合法性、错误处理能力及性能安全性,其重要性体现在早期发现问题、保障系统稳定和支撑持续集成。常用方法包括功能、性能、安全性及兼容性测试,典型场景涵盖前后端分离开发、第三方服务集成与数据一致性检查。选择合适的工具需综合考虑需求与团队协作等因素。
705 24