Rails测试《五》实战单元测试-用factory-girl替换fixtures来创建模拟数据

简介:

fixtures

在前面我们介绍了,rails的测试系统默认使用fixtures来创建模拟数据,这些数据以yaml的格式书写,放在db/fixtures文件夹中,每个model都有一个对应的文件,test/fixtures/users.yml。

在测试启动的时候这些fixtures中的数据会加载到测试数据库,并且加载到变量中,供单元测试和功能测试使用。

使用fixtures有几个不利的因素,使得他们处于不利的位置。

最主要的一个因素是,这些fixtures描述的数据和测试他们的行为是分开的,在不同的文件中。使用这些模拟数据,我们需要依赖于fixtures文件,这些文件很难阅读,维护不便。

假设我们需要两个user对象,用来测试我们的User.authenticate是否工作正常,我们需要编写下面的内容。

 
  1. bob: 
  2.   username: bob 
  3.   email: bob@example.com 
  4.   password_digest: 3488f5f7efecab14b91eb96169e5e1ee518a569f 
  5.   password_salt: bef65e058905c379436d80d1a32e7374b139e7b0 
  6.  
  7. admin: 
  8.   username: admin 
  9.   email: admin@example.com 
  10.   password_digest: 3488f5f7efecab14b91eb96169e5e1ee518a569f 
  11.   password_salt: bef65e058905c379436d80d1a32e7374b139e7b0 
  12.    

因为这两个数据需要存储到数据库中,我们的password_digest和password_salt需要是上面的样子,我们无法知道这两个属性的值具体代表什么意义,它们的内容到底是什么呢?

 

http://guides.rubyonrails.org/testing.html的最后面的部分,推荐了一个fixtures的替代品,那就是factory girl,它还有一个rails版本factory girl rails,专门用于rails的测试。

 

如何在rails中使用factory girl rails

https://github.com/thoughtbot/factory_girl/wiki有关于factory-girl使用的详细教程,基本上也适用于factory-girl-rails。

下面我们介绍一下基本的使用方法。

 

首先在gemfile文件中加入

 

 

 
  1. gem 'factory_girl_rails' 
然后执行
 
 
  1. bundle install 
然后再test目录创建factories.rb文件。这个文件的作用有点像我们使用fixtures的时候的yml文件,里面用来创建模拟数据。但是不同的是fixtures中的数据会被自动加入数据库,所以创建的时候声明的属性要和数据库匹配,是一种从数据库出发的模拟数据。但是factory-girl创建的模拟数据不会被自动加入数据库,是一种从model出发的模拟数据,所以声明的属性是和model对应的,所以不会出现使用fixtures的时候的哪种看不懂的password_digest属性值。
 
 
  1. FactoryGirl.define do 
  2.   factory :user do 
  3.     nickname "nickname" 
  4.     email "ee@123.com" 
  5.     password "123" 
  6.     password_confirmation "123" 
  7.   end 
  8. end 

 

上面factory-girl创建了一个user对象,这个对象也同样可以在测试用使用。请注意factory :后满的内容,这样要对应于一个model的类名,第一个字母最好小写,当然大写也是可以的。

还需要在使用这些数据的地方引入一个module。假如我们想要在user的单元测试中使用factory-girl的模拟数据,可以向下面这样添加这个module。

 
  1. class UserTest < ActiveSupport::TestCase 
  2.   include FactoryGirl::Syntax::Methods 
  3. end 

这样的话,我们就可以在user的单元测试中像下面这样使用这些模拟数据。

 
  1. # 保存user数据到数据库
  2. user = create(:user
  3.  
  4. # 不保存user数据,只是把它保存到user变量 
  5. user = build(:user
  6.  
  7. # 获取factory-girl中定义的user属性的键值对hash 
  8. user_attributes = attributes_for(:user
  9.  
  10. # 创建一个user的stub对象 
  11. user_stub = build_stubbed(:user
  12.  
  13. # 覆盖factory-girl中user对象的部分属性
  14. user = create(:user, first_name: 'Joe'

 

但是,如果我们有很多的model,都需要模拟数据,都写在factories.rb文件中,好像不太好,越写越长,而且内容混杂,也不好维护,也不利于阅读。

我们可以在创建test/factories文件夹,然后再test/factories文件夹中创建users.rb,在users.rb中写user的模拟数据。同样可以在factories文件夹中创建模拟其他model用的文件。

 

但是上面的factory-girl只是创建了一个user对象,如果需要多个模拟的user对象呢?可以像下面这样写,用:class => :User,来指定当前这个对象使用user的model为模板。

 
  1. FactoryGirl.define do 
  2.   factory :user1:class => :User do 
  3.     nickname "nickname" 
  4.     email "ee@123.com" 
  5.     password "123" 
  6.     password_confirmation "123" 
  7.   end 
  8.   factory :user2:class => :User do 
  9.     nickname "nickname2" 
  10.     email "ee2@123.com" 
  11.     password "1232" 
  12.     password_confirmation "123" 
  13.   end 
  14. end 

上面创建了两个user对象。可以像下面这样使用它们。

 
  1. def test_use_valid_user_from_factory_girl 
  2.    user = build(:user1
  3.    assert user.valid? 
  4.  end 
  5.  
  6.  def test_use_invalid_user_from_factory_girl 
  7.    user = build(:user2
  8.    assert user.invalid? 
  9.  end 

我已经在https://github.com/woaigithub/blog中加入了大量的unit test,大家可以参考,也可以提出意见,欢迎大家提意见!

 




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

目录
相关文章
|
26天前
|
测试技术 持续交付 UED
软件测试的艺术:确保质量的实战策略
在软件开发的舞台上,测试是那把确保每个功能如交响乐般和谐奏响的指挥棒。本文将深入探讨软件测试的重要性、基本类型以及如何设计高效的测试策略。我们将通过一个实际的代码示例,展示如何运用这些策略来提升软件质量和用户体验。
|
1月前
|
JSON Java 测试技术
SpringCloud2023实战之接口服务测试工具SpringBootTest
SpringBootTest同时集成了JUnit Jupiter、AssertJ、Hamcrest测试辅助库,使得更容易编写但愿测试代码。
60 3
|
1月前
|
测试技术 开发者 UED
探索软件测试的深度:从单元测试到自动化测试
【10月更文挑战第30天】在软件开发的世界中,测试是确保产品质量和用户满意度的关键步骤。本文将深入探讨软件测试的不同层次,从基本的单元测试到复杂的自动化测试,揭示它们如何共同构建一个坚实的质量保证体系。我们将通过实际代码示例,展示如何在开发过程中实施有效的测试策略,以确保软件的稳定性和可靠性。无论你是新手还是经验丰富的开发者,这篇文章都将为你提供宝贵的见解和实用技巧。
|
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协议的接口测试方法