Rspec: everyday-rspec实操。FactoryBot预构件 (rspec-expectations gem 查看匹配器) 1-4章
RSpec.info/documentation/
包括core, expectiation,rails , mock, 点击最新版本,然后右上角搜索class, method.
第3章:
rspec-expectations gem: RSpec匹配器
第4章:
预构件gem: factory_bot
git checkout -b my-02-setup origin/01-untested
解释:从已经克隆后的远程,下载分支到本地。
Switched to a new branch 'my-02-setup'
第二章 开始
1.
Gemfile group :development, :test do
gem 'rspec-rails', '~> 3.6.0' # 省略了 Rails 提供的其他 gem
end
2. 测试数据库。
3. 配置RSpec:
$ bin/rails generate rspec:install
打开.rspec文件,增加:
作者强烈建议看spec/spec_helper.rb和spec/rails_helper.rb的设置,理解各项设置的作用。
3.1 使用 rspec binstub 提升测试组件的启动速度
group :development do
# 这一分组中的其他 gem ...
gem 'spring-commands-rspec'
end
然后 bundle exec spring binstub rspec, 如果不想用这个,直接bundle exec rspec.
然后bin/rspec试一试。
4 controller(可选)
可以使用 rspec-rails 提供的默认设置;不过这样会生成额外的样板代码,你可以自己动手删 除,也可以放着不管。
打开 config/application.rb 文件,在 Application 类中加入下面的代码:
5,附加:(Rails指南有一整章节。)
如果经常新建Rails, 可以创建一个Rails 应用模板,自动把 RSpec 和相关的配置添加到应用 的 Gemfile 和配置文件中,而且还可以自动创建测试数据库。Daniel Kehoe 开发的 Rails Composer 是个 不错的工具。
第 3 章 模型测试
git checkout -b my-03-models origin/02-setup
复制前一章分支,增加了user, project, note, task.4个models. 添加了5个gem。
1.2编写模型测试。
bin/rails g rspec:model user
模型测试应该包含:
• 使用有效属性实例化的模型应该是有效的;
• 无法通过数据验证的数据,测试应该失败;
• 类方法和实例方法应按预期可正常使用。
2.2编写模型测试
bin/rspec
首先,确定要验证的example。模型验证User
pending在之后章节学习。
2.3 RSpec句法:新:expect().to eq()
然后bin/rspec,通过验证。
2.4 测试数据验证
include匹配器检验一个可以枚举的value中是否包括指定的值。 to_not和to匹配器。
然后bin/rspec通过验证。
另外,可以修改应用代码,看看对测试有什么影响。如果测试代码的输出没有变化,可能是测试没有与代码对接上,或者代码的行为与预期不同。
关联模型的数据验证:
bin/rails g rspec:model project
这会生成models/project_spec.rb文件。也可以手动添加,但通过控制器添加文件,能防止打错字。
加2个example.
it "does not allow duplicate project names per user"
it "allows two users to share a project name"
因为在app/models/project.rb中,增加了作用域验证,这里每个project的name只有一个用户,name不是唯一的但它对应的user_id,在Project中是唯一的。
validates :name, presence: true, uniqueness: { scope: :user_id }
我们应当养成数据验证的习惯,通过和不通过都要验证。
比如:把验证代码临时注释掉,或者把测试的预期改成其他值,看看测试结果是否失败?
3.5 测试实例方法
在User model中编写一个实例方法name。可以在测试文件user_spec.rb中使用,例子:
expect(user.name).to eq("Dave Bot")
3.6测试类方法和作用域
在Note model中编写一个类方法search,它是一个作用域 :
- #A scope是狭义的data 查询。用于检索和查询类的实例对象
- #scope()是类方法:scope(name, body, &body), 等同于:
- #返回的是一个相关的记录数据集合对象,ActiveRecord::Relation,类似Array
- #箭头函数是lambda表达式,->(){return},这里成为块参数。
WHERE .. LIKE.. 模糊对比:SELECT * FROM events WHERE name LIKE '%Ruby%';
这里where()是rails语法糖。返回一个relation对象。
具体看query guide. 或者自己的博客activerecord:query
expect(Note.search("first")).to include(note1)
3.7 测试失败情况
使用be_empty匹配器,检查Note.search("something")的返回值是否为空。
空的话:expected `#<ActiveRecord::Relation []>.empty?` to return true.
3.8 匹配器
be_valid, eq, include , be_empty。 be_valid由rspec-rails gem提供。
其他的由一起安装的rspec-expectations gem提供 :https://github.com/rspec/rspec-expectations
第8章 ,自定义匹配器
3.9 refactor重构: describe, context, before, after.
describe 用来表示 需要实现的功能
context 针对该功能不同的情况
it : 返回什么结果。 使用动词说明希望得到的结果。
before: 设定测试数据。消除重复。这是简写,全的是before(:each),在块内的每个example之前运行一次,有几个example就运行几次。
before(:all):在块内的all examples之前运行一次,之后不再运行。
before(:suit):) 在整个测试组件之前运行。
after: 假如测试在用例执行后需要做些清理工作,例如中断与外部服务的连接, after 块也有 each、all 和 suite 三个选项。因为 RSpec 会自行清理数据库,所以我很 少使用 after。
3.10小结:
- 明确指定希望得到的结果:使用动词说明希望得到的结果。每个测试用例只测试一种情况。
- 测试希望看到的结果和不希望看到的结果
- 测试极端情况
- • 测试要良好地组织,保证可读性:使用 describe 和 context 组织测试,形成一个清晰的大纲;使用 before 和 after 块消除代码重复。
第 4 章 创建有意义的测试数据
用预构件代替固件fixture
4.1安装
Gemfile
group :development, :test do
gem "rspec-rails", "~> 3.6.0"
gem "factory_bot_rails" # 改名了,以前叫factory_girl
end
config/application.rb 把fixture: false去掉了。
4.2 开始用
bin/rails generate factory_bot:model usercreate spec/factories/users.rbFactoryBot.define dofactory :user do first_name "Aaron" last_name "Sumner" email "tester@example.com" password "dottle-nouveau-pavilion-tights-furze" end # 现在,在测试中可以调用 FactoryBot.create(:user) end
spec/models/user_spec.rb
require 'rails_helper'
describe User do
it "has a valid factory" do
expect(FactoryBot.build(:user)).to be_valid
end
## 其他测试用例 ...
end
记住:FactoryBot.build 的作用是在内存中创建一个新测试对象;
FactoryBot.create 的作用
是把对象持久存储到应用的测试数据库中。
4.3 使用序列生成唯一的数据
it "does something with multiple users" do
user1 = FactoryGirl.create(:user)
user2 = FactoryGirl.create(:user)
expect(true).to be_true
end
希望user1,和user2,都可以创建出来,对于唯一属性,可以使用secquence方法来设置,每创建一个对象,唯一属性自动加1.
sequence(:email) { |n| "tester#{n}@example.com" }
4.4 Factory中的 Association
FactoryBod比纯粹的fixtures功能强大的多,可以处理models之间的Association.
bin/rails generate factory_bot:model note
bin/rails g factory_bot:model project
FactoryBot.define do
factory :project d
sequenct(:name) {|n| "Project #{n}"} #因为为name设置 uniqueness: {scope: :user_id}
description "A test project"
due_on 1.week.from_now
association :owner #关联到user,因为在模型project.rb中设置了别名
end
end
在用户预构件factories/users.rb中,在第二行,就是为预构件起名的那一行,加上别名
owner。 原因见后面2段文字。
factory :user, aliases:[:owner] do
因为预构件已经定义:user, :project 和:note,并建立了Association。所以在:
models/note_spec.rb中,只创建了note记录用,同时note.project就创建了project记录并关联上了。
inspect()方法检查是否关联。
inspect方法 返回所关联的对象。
不过注意⚠️ 预构件可能会骗人,因为它会先创建一个关联的用户(项目的属主),再创建一个用户(记录的属主),因此note.user.inspect返回的对象的email属性将是test2@example.com, 而不是预想的text1@example.com
为了避免这种问题,我们可以修改记录预构件,把两个用户统一:
回头看一下app/models/project.rb:Project模型关联的user的别名叫"owner"
belongs_to :owner, class_name: User, foreign_key: :user_id
这就是前面在users.rb加上aliases:[:owner]代码的原因: 让F a c to r y B o t知道可以通过别名"owner"引用预构件user.
4.6 避免预构件中出现重复
同种类型的数据可以定义多个预构件。例如,为了测试项目是按期完成的还是延期了,可以为预构件设定不同的名称,指定不同的属性 .
⚠️需要
Rspec: everyday-rspec实操。FactoryBot预构件 (rspec-expectations gem 查看匹配器) 1-4章的更多相关文章
- Rspec: everyday-rspec实操。5:controller test(了解基础)
第 5 章 控制器测试 5.1基础 rails generate rspec:controller home RSpec.describe HomeController, type: :control ...
- Rspec: everyday-rspec实操: 第8章DRY. (6个方法,其中3个方法好上手)
Don't Repeat Yourself. • 把操作步骤提取到辅助模块中;✅ • 通过let复用测试中的实例变量;✅ • 把通用的设置移到共享的情景中;⚠️(不喜欢) • 在RSpec和rspec ...
- Rspec: everyday-rspec实操: 第9章 快速编写测试,编写快速的测试。
Make it work, make it right, make it fast. 测试运行的时间.应用和测试组件的增长,速度会越来越慢,目标是保持代码的readable, maintainable ...
- 百度NLP预训练模型ERNIE2.0最强实操课程来袭!【附教程】
2019年3月,百度正式发布NLP模型ERNIE,其在中文任务中全面超越BERT一度引发业界广泛关注和探讨.经过短短几个月时间,百度ERNIE再升级,发布持续学习的语义理解框架ERNIE 2.0,及基 ...
- .net基础学java系列(四)Console实操
上一篇文章 .net基础学java系列(三)徘徊反思 本章节没啥营养,请绕路! 看视频,不实操,对于上了年龄的人来说,是记不住的!我已经看了几遍IDEA的教学视频: https://edu.51cto ...
- 动手实操(一):如何用七牛云 API 实现相片地图?
实操玩家: 在苹果手机上,我们只要打开定位服务,拍照后便能在相簿中找到地图,地图上显示着在各地拍摄的相片.网站上这种显示方式也并不少见,例如 Flickr.即将关闭的 Panoramio 等. 作为地 ...
- 决策树算法的Python实现—基于金融场景实操
决策树是最经常使用的数据挖掘算法,本次分享jacky带你深入浅出,走进决策树的世界 基本概念 决策树(Decision Tree) 它通过对训练样本的学习,并建立分类规则,然后依据分类规则,对新样本数 ...
- Istio的流量管理(实操三)
Istio的流量管理(实操三) 涵盖官方文档Traffic Management章节中的egress部分.其中有一小部分问题(已在下文标注)待官方解决. 目录 Istio的流量管理(实操三) 访问外部 ...
- 72 个网络应用安全实操要点,全方位保护 Web 应用的安全
原文地址:Web Application Security Checklist 原文作者:Teo Selenius(已授权) 译者 & 校正:HelloGitHub-小熊熊 & 卤蛋 ...
随机推荐
- 20155333 2016-2017-2 《Java程序设计》第九周学习总结
20155333 2016-2017-2 <Java程序设计>第九周学习总结 教材学习内容总结 JDBC(Java DataBase Connectivity) 驱动的四种类型 JDBC- ...
- 519. Random Flip Matrix(Fisher-Yates洗牌算法)
1. 问题 给定一个全零矩阵的行和列,实现flip函数随机把一个0变成1并返回索引,实现rest函数将所有数归零. 2. 思路 拒绝采样 (1)先计算矩阵的元素个数(行乘以列),记作n,那么[0, n ...
- python xml childNodes,childNodes[1].childNodes[0].data例子
xml: <?xml version='1.0' encoding='utf-8'?><!--this is a test about xml--><booklist t ...
- linux基础命令---chattr
chattr 改变文件的属性,这个命令只有超级用户才能使用.这个指令适用于ext2.ext3.ext4.xfs.ubifs.reiserfs.jfs系统. 此命令的适用范围:RedHat.RHEL.U ...
- Jquery图片上传组件,支持多文件上传
Jquery图片上传组件,支持多文件上传http://www.jq22.com/jquery-info230jQuery File Upload 是一个Jquery图片上传组件,支持多文件上传.取消. ...
- Advapi32.dll--介绍
https://blog.csdn.net/zhoujielun123456/article/details/50338147 使用方法详见:OpsTotalService
- IOS学习基础
http://www.jikexueyuan.com/path/ios/ 界面优化 iOS界面绘图API.控件等知识. 1,绘制图片 2,画板实例 3, 1,UIView的setNeedsDispla ...
- 安装PyInstaller打包python
安装PyInstaller 对于那些网络比较稳定,能够流畅使用pip源地址的用户,直接下面的命令就可以搞定: pip install pyinstaller 通常我们会下载源码包,然后进入包目录,执行 ...
- linux下获取本机的获取内网和外网地址
1.获取内网地址(私有地址) ifconfig -a 2.获取外网地址(公网地址) curl members.3322.org/dyndns/getip
- Java ArrayDeque源码剖析
ArrayDeque 本文github地址 前言 Java里有一个叫做Stack的类,却没有叫做Queue的类(它是个接口名字).当需要使用栈时,Java已不推荐使用Stack,而是推荐使用更高效的A ...