本文转载自公众号“读芯术”(ID:AI_Discovery)。
测试用例之间的陈旧数据是RSpec中竞态条件的主要原因之一,包括数据库Redis、文件等。本文就将讨论如何清理数据库中的陈旧数据。
Rails Rspec后台默认事务
如果使用rails-rspec,默认情况下,spec/rails_helper.rb中会启用以下配置:
- RSpec.configuredo |config|
- config.use_transactional_fixtures=true
- end
这意味着“在事务内运行每个示例”,即在示例结束时,所有数据库的变更都将回滚。
如何让“事务装置”实现“在事务内运行每个示例”?
在深入研究Rails 4代码库,了解了它在后台的实际工作之后,我发现了以下内容。setup_fixtures函数中,Rails为每个数据库连接调用begin_transaction。
在teardown_fixtures函数中,Rails为每个数据库连接调用rollback_transaction。
这也意味着,如果在应用程序中使用多个数据库,那么应用程序将为所有数据库创建事务。
在示例之外创建的数据库记录将不会回滚
由于数据库事务围绕着每个示例,因此在示例范围之外创建的任何数据库记录都不会回滚,也就是说,在before(:all)、before(:context)或before(:suite)代码块中创建的任何数据库记录都不会回滚。
这可能导致示例组之间而不是同一组的示例之间的竞态条件,因此处理hook问题时要十分小心。
- context'context 1'do
- before(:context) do
- create(:user) # WON'T BE ROLLED-BACK
- end
- beforedo
- create(:user) # will be rolled-back
- end
- # ...
- end
- context'context 2'do
- before(:context) do
- create(:user) # WON'T BE ROLLED-BACK
- end
- # ...
- end
- # BY NOW, THERE ARE 2 USER RECORDS COMMITED TO DATABASE
手动设置数据库事务
你还可以选择使用hook手动设置数据库事务。
- RSpec.configuredo |config|
- config.use_transactional_fixtures=false# DISABLE DEFAULT TRANSACTIONS
- end
- before(:example) do
- ActiveRecord::Base.connection.begin_transaction
- end
- after(:example) do
- conn =ActiveRecord::Base.connection
- conn.rollback_transactionif conn.transaction_open?
- end
- # OR
- around(:example) do |example|
- ActiveRecord::Base.transactiondo
- example.run
- # ROLLBACK after the example finishes.
- # This exception is silently swallowed by ActiveRecord.
- raiseActiveRecord::Rollback
- end
- end
[Rails 4 & Rails 5.0.x]数据库事务是按线程执行的
由上可知,ActiveRecord数据库连接是按线程执行的。因此,Rails通过use_transactional_fixtures管理的默认数据库事务只在主线程中可用。
从技术上说,根据事务回滚策略,一个线程的数据库记录将独立于其他线程。需要访问其他线程中的某个线程的数据库数据时请注意这一点,例如Selenium。
[Rails 4 & Rails 5.0.x]JavaScript驱动程序(Selenium)和Capybara Webkit的验收测试问题。
Selenium在另一个线程上运行,因此它不能与运行RSpec的主线程共享事务。为了让客户端应用程序访问数据库中的数据,RSpec需要将改动提交。这类情况下可以允许提交数据,然后手动清理数据。
[Rails 4 & Rails 5.0.x]DatabaseCleaner——回滚策略
要解决上述问题,首先需要禁用Rails派生的事务,将config.use_transactional_fixtures设置为false,或干脆删除它。DatabaseCleaner是一个gem,它提供了清理数据库的高级策略,例如删节、事务处理或删除。
下面是利用DatabaseCleaner处理上述JS驱动程序问题的著名gist:
[从Rails 5.1起]数据库事务在测试线程之间共享
线程之间的共享数据库事务由Rails团队的Eileen完成,并作为Rails 5.1的一部分内容发布。
此更新允许将启用JS的验收测试封装在RSpec的默认事务中,这已经消除了对DatabaseCleaner的需求。
希望本文能帮助你更好地理解RSpec中的数据库事务。
【六】漏洞检测 1.Nessus 1.1 启动Nessus 2. Nmap 脚本引擎(NSE 2.1 Nmap 脚本存...
HTTP 协议是互联网的基础协议,也是网页开发的必备知识,最新版本 HTTP/2 更是让...
本文实例为大家分享了vue验证用户名是否可用的具体代码,供大家参考,具体内容如...
Sub CheckCanSubmit(str) Dim connt,connts connt="六合彩,免费电影,安利,http,w...
前言 前段时间在本地写的一个WebSocket程序部署到服务器上时出错,通过一段时间...
一名双非本科学生的逆袭计划 一、自我介绍 我是一名来至湖北双非本科的大一计算...
随着国际环境日趋复杂,数据安全与信息技术发展成为发展首要任务。目前,随着信...
在jstl里面有fn:contains(str,str)这样的方法来判断字符串是否包含另一个字符串...
本文实例为大家分享了jquery点击左右按钮切换图片的具体代码,供大家参考,具体...
在新的MySQL 8.0.23中,引入了新的有趣功能:不可见列。 这是第一篇关于这个新功...