Rspec的数据库事务:如何清理陈旧数据?

数据库 其他数据库
测试用例之间的陈旧数据是RSpec中竞态条件的主要原因之一,包括数据库Redis、文件等。本文就将讨论如何清理数据库中的陈旧数据。

本文转载自公众号“读芯术”(ID:AI_Discovery)。

测试用例之间的陈旧数据是RSpec中竞态条件的主要原因之一,包括数据库Redis、文件等。本文就将讨论如何清理数据库中的陈旧数据。

Rails Rspec后台默认事务

如果使用rails-rspec,默认情况下,spec/rails_helper.rb中会启用以下配置:

  1. RSpec.configuredo |config| 
  2.                   config.use_transactional_fixtures=true 
  3.                 end 

这意味着“在事务内运行每个示例”,即在示例结束时,所有数据库的变更都将回滚。

如何让“事务装置”实现“在事务内运行每个示例”?

在深入研究Rails 4代码库,了解了它在后台的实际工作之后,我发现了以下内容。setup_fixtures函数中,Rails为每个数据库连接调用begin_transaction。

 

Rspec的数据库事务:如何清理陈旧数据?

 

 

Rails 4的setup_fixtures

 

在teardown_fixtures函数中,Rails为每个数据库连接调用rollback_transaction。

 

Rspec的数据库事务:如何清理陈旧数据?

 

 

Rails 4的teardown_fixtures

 

这也意味着,如果在应用程序中使用多个数据库,那么应用程序将为所有数据库创建事务。

在示例之外创建的数据库记录将不会回滚

由于数据库事务围绕着每个示例,因此在示例范围之外创建的任何数据库记录都不会回滚,也就是说,在before(:all)、before(:context)或before(:suite)代码块中创建的任何数据库记录都不会回滚。

这可能导致示例组之间而不是同一组的示例之间的竞态条件,因此处理hook问题时要十分小心。

  1. context'context 1'do 
  2.           before(:context) do 
  3.             create(:user) # WON'T BE ROLLED-BACK 
  4.           end 
  5.                beforedo 
  6.             create(:user) # will be rolled-back 
  7.           end 
  8.                # ... 
  9.         end 
  10.              context'context 2'do 
  11.           before(:context) do 
  12.             create(:user) # WON'T BE ROLLED-BACK 
  13.           end 
  14.                # ... 
  15.         end 
  16.              # BY NOW, THERE ARE 2 USER RECORDS COMMITED TO DATABASE 

手动设置数据库事务

你还可以选择使用hook手动设置数据库事务。

  1. RSpec.configuredo |config| 
  2.                   config.use_transactional_fixtures=false# DISABLE DEFAULT TRANSACTIONS 
  3.                 end 
  4.              before(:example) do 
  5.                   ActiveRecord::Base.connection.begin_transaction 
  6.                 end 
  7.              after(:example) do 
  8.                   conn =ActiveRecord::Base.connection 
  9.                   conn.rollback_transactionif conn.transaction_open? 
  10.                 end 
  11.              # OR 
  12.              around(:example) do |example| 
  13.                   ActiveRecord::Base.transactiondo 
  14.                     example.run 
  15.                            # ROLLBACK after the example finishes. 
  16.                     # This exception is silently swallowed by ActiveRecord. 
  17.                     raiseActiveRecord::Rollback 
  18.                   end 
  19.                 end 

[Rails 4 & Rails 5.0.x]数据库事务是按线程执行的

 

Rspec的数据库事务:如何清理陈旧数据?

 

 

Rails 4中的数据库连接

 

由上可知,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:

Rspec的数据库事务:如何清理陈旧数据?

[从Rails 5.1起]数据库事务在测试线程之间共享

线程之间的共享数据库事务由Rails团队的Eileen完成,并作为Rails 5.1的一部分内容发布。

 

 

Rspec的数据库事务:如何清理陈旧数据?

 

 

加入了lock_thread

 

Rspec的数据库事务:如何清理陈旧数据?
为测试启用了lock_thread

此更新允许将启用JS的验收测试封装在RSpec的默认事务中,这已经消除了对DatabaseCleaner的需求。

希望本文能帮助你更好地理解RSpec中的数据库事务。

 

责任编辑:赵宁宁 来源: 今日头条
相关推荐

2015-03-31 10:26:01

数据库数据库事务

2009-09-24 14:12:22

Hibernate数据

2010-10-08 09:38:55

Android数据库事

2024-01-18 09:43:11

MySQL数据库

2023-10-11 08:09:53

事务隔离级别

2018-07-20 11:10:21

数据库事务隔离性

2010-04-15 08:57:29

Oracle数据库

2010-07-05 17:41:37

SQL Server

2024-05-28 00:00:30

Golang数据库

2017-08-22 17:10:45

数据库MySQL事务模型

2024-04-08 10:11:15

MYSQL数据库事务

2010-09-08 15:55:20

SQL事务特性

2020-06-17 16:56:36

数据库MySQL跨行事务

2022-11-14 18:23:06

亚马逊

2011-08-12 13:33:31

Oracle数据库自治事务

2009-08-06 18:10:06

C#数据库事务

2010-05-31 15:12:44

MySQL数据库

2018-09-06 14:53:39

数据库事务隔离隔离级别

2018-07-17 10:58:45

数据库数据库事务隔离级别

2009-08-07 17:04:41

C#数据库
点赞
收藏

51CTO技术栈公众号