mirror of
https://github.com/DatabaseCleaner/database_cleaner
synced 2023-03-27 23:22:03 -04:00
Merge branch 'master' of github.com:bmabey/database_cleaner
This commit is contained in:
commit
ee5cd622d0
33 changed files with 802 additions and 79 deletions
2
Gemfile
2
Gemfile
|
@ -26,6 +26,8 @@ group :development do
|
||||||
gem 'mysql', '~> 2.8.1'
|
gem 'mysql', '~> 2.8.1'
|
||||||
gem 'mysql2'
|
gem 'mysql2'
|
||||||
gem 'pg'
|
gem 'pg'
|
||||||
|
gem 'sqlite3'
|
||||||
|
gem 'ohm', '~> 0.1.3'
|
||||||
|
|
||||||
gem 'guard-rspec'
|
gem 'guard-rspec'
|
||||||
end
|
end
|
||||||
|
|
|
@ -135,6 +135,10 @@ GEM
|
||||||
multi_json (1.5.0)
|
multi_json (1.5.0)
|
||||||
mysql (2.8.1)
|
mysql (2.8.1)
|
||||||
mysql2 (0.3.11)
|
mysql2 (0.3.11)
|
||||||
|
nest (1.1.2)
|
||||||
|
redis
|
||||||
|
ohm (0.1.5)
|
||||||
|
nest (~> 1.0)
|
||||||
origin (1.0.11)
|
origin (1.0.11)
|
||||||
pg (0.14.1)
|
pg (0.14.1)
|
||||||
plucky (0.5.2)
|
plucky (0.5.2)
|
||||||
|
@ -160,6 +164,7 @@ GEM
|
||||||
rake (10.0.3)
|
rake (10.0.3)
|
||||||
rdoc (3.12)
|
rdoc (3.12)
|
||||||
json (~> 1.4)
|
json (~> 1.4)
|
||||||
|
redis (3.0.4)
|
||||||
rest-client (1.6.7)
|
rest-client (1.6.7)
|
||||||
mime-types (>= 1.16)
|
mime-types (>= 1.16)
|
||||||
rspec (2.12.0)
|
rspec (2.12.0)
|
||||||
|
@ -213,6 +218,7 @@ DEPENDENCIES
|
||||||
mongoid
|
mongoid
|
||||||
mysql (~> 2.8.1)
|
mysql (~> 2.8.1)
|
||||||
mysql2
|
mysql2
|
||||||
|
ohm (~> 0.1.3)
|
||||||
pg
|
pg
|
||||||
rake
|
rake
|
||||||
rspec-rails
|
rspec-rails
|
||||||
|
|
|
@ -5,7 +5,7 @@ Database Cleaner is a set of strategies for cleaning your database in Ruby.
|
||||||
The original use case was to ensure a clean state during tests.
|
The original use case was to ensure a clean state during tests.
|
||||||
Each strategy is a small amount of code but is code that is usually needed in any ruby app that is testing with a database.
|
Each strategy is a small amount of code but is code that is usually needed in any ruby app that is testing with a database.
|
||||||
|
|
||||||
ActiveRecord, DataMapper, Sequel, MongoMapper, Mongoid, and CouchPotato are supported.
|
ActiveRecord, DataMapper, Sequel, MongoMapper, Mongoid, CouchPotato, Ohm and Redis are supported.
|
||||||
|
|
||||||
[![Build Status](https://secure.travis-ci.org/bmabey/database_cleaner.png)](http://travis-ci.org/bmabey/database_cleaner)
|
[![Build Status](https://secure.travis-ci.org/bmabey/database_cleaner.png)](http://travis-ci.org/bmabey/database_cleaner)
|
||||||
|
|
||||||
|
@ -55,6 +55,18 @@ Here is an overview of the strategies supported for each library:
|
||||||
<td> Yes</td>
|
<td> Yes</td>
|
||||||
<td> No</td>
|
<td> No</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Redis</td>
|
||||||
|
<td><b>Yes</b></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>No</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Ohm</td>
|
||||||
|
<td><b>Yes</b></td>
|
||||||
|
<td>No</td>
|
||||||
|
<td>No</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -72,6 +84,12 @@ Here is an overview of the strategies supported for each library:
|
||||||
<td> No</td>
|
<td> No</td>
|
||||||
<td> No</td>
|
<td> No</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> Moped</td>
|
||||||
|
<td> Yes</td>
|
||||||
|
<td> No</td>
|
||||||
|
<td> No</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -88,11 +106,11 @@ For the SQL libraries the fastest option will be to use `:transaction` as transa
|
||||||
|
|
||||||
One common approach is to force all processes to use the same database connection ([common ActiveRecord hack](http://blog.plataformatec.com.br/2011/12/three-tips-to-improve-the-performance-of-your-test-suite/)) however this approach has been reported to result in non-deterministic failures.
|
One common approach is to force all processes to use the same database connection ([common ActiveRecord hack](http://blog.plataformatec.com.br/2011/12/three-tips-to-improve-the-performance-of-your-test-suite/)) however this approach has been reported to result in non-deterministic failures.
|
||||||
|
|
||||||
Another approach is to have the transactions rolled back in the application's process and relax the isolation level of the database (so the tests can read the uncommited transactions).
|
Another approach is to have the transactions rolled back in the application's process and relax the isolation level of the database (so the tests can read the uncommitted transactions).
|
||||||
|
|
||||||
An easier, but slower, solution is to use the `:truncation` or `:deletion` strategy.
|
An easier, but slower, solution is to use the `:truncation` or `:deletion` strategy.
|
||||||
|
|
||||||
So what is fastest out of `:deletion` and `:truncation`? Well, it depends on your table structure and what percentage of tables you populate in an average test. The reasoning is out the the scope of this README but here is a [good SO answer on this topic for Postgres](http://stackoverflow.com/questions/11419536/postgresql-truncation-speed/11423886#11423886).
|
So what is fastest out of `:deletion` and `:truncation`? Well, it depends on your table structure and what percentage of tables you populate in an average test. The reasoning is out of the scope of this README but here is a [good SO answer on this topic for Postgres](http://stackoverflow.com/questions/11419536/postgresql-truncation-speed/11423886#11423886).
|
||||||
|
|
||||||
Some people report much faster speeds with `:deletion` while others say `:truncation` is faster for them. The best approach therefore is it try all options on your test suite and see what is faster.
|
Some people report much faster speeds with `:deletion` while others say `:truncation` is faster for them. The best approach therefore is it try all options on your test suite and see what is faster.
|
||||||
|
|
||||||
|
@ -123,6 +141,9 @@ DatabaseCleaner.strategy = :truncation, {:only => %w[widgets dogs some_other_tab
|
||||||
DatabaseCleaner.strategy = :truncation, {:except => %w[widgets]}
|
DatabaseCleaner.strategy = :truncation, {:except => %w[widgets]}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
With Ohm and Redis, `:only` and `:except` take a list of strings to be
|
||||||
|
passed to [`keys`](http://redis.io/commands/keys)).
|
||||||
|
|
||||||
(I should point out the truncation strategy will never truncate your schema_migrations table.)
|
(I should point out the truncation strategy will never truncate your schema_migrations table.)
|
||||||
|
|
||||||
Some strategies require that you call `DatabaseCleaner.start` before calling `clean` (for example the `:transaction` one needs to know to open up a transaction). So you would have:
|
Some strategies require that you call `DatabaseCleaner.start` before calling `clean` (for example the `:transaction` one needs to know to open up a transaction). So you would have:
|
||||||
|
@ -276,6 +297,11 @@ Usage beyond that remains the same with `DatabaseCleaner.start` calling any setu
|
||||||
<td> <code>DatabaseCleaner[:mongoid]</code></td>
|
<td> <code>DatabaseCleaner[:mongoid]</code></td>
|
||||||
<td> Multiple databases supported for Mongoid 3. Specify <code>DatabaseCleaner[:mongoid, {:connection => :db_name}]</code> </td>
|
<td> Multiple databases supported for Mongoid 3. Specify <code>DatabaseCleaner[:mongoid, {:connection => :db_name}]</code> </td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> Moped</td>
|
||||||
|
<td> <code>DatabaseCleaner[:moped]</code></td>
|
||||||
|
<td> It is necessary to configure database name with <code>DatabaseCleaner[:moped].db = db_name</code> otherwise name `default` will be used.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td> Couch Potato</td>
|
<td> Couch Potato</td>
|
||||||
<td> <code>DatabaseCleaner[:couch_potato]</code></td>
|
<td> <code>DatabaseCleaner[:couch_potato]</code></td>
|
||||||
|
@ -286,6 +312,16 @@ Usage beyond that remains the same with `DatabaseCleaner.start` calling any setu
|
||||||
<td> <code>DatabaseCleaner[:sequel]</code></td>
|
<td> <code>DatabaseCleaner[:sequel]</code></td>
|
||||||
<td> Multiple databases supported; specify <code>Databasecleaner[:sequel, {:connection => Sequel.connect(uri)}]</code></td>
|
<td> Multiple databases supported; specify <code>Databasecleaner[:sequel, {:connection => Sequel.connect(uri)}]</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Redis</td>
|
||||||
|
<td><code>DatabaseCleaner[:redis]</code></td>
|
||||||
|
<td>Connection specified as Redis URI</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Ohm</td>
|
||||||
|
<td><code>DatabaseCleaner[:ohm]</code></td>
|
||||||
|
<td>Connection specified as Redis URI</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
8
examples/config/redis.yml
Normal file
8
examples/config/redis.yml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
test:
|
||||||
|
url: 'redis://localhost:6379/0'
|
||||||
|
|
||||||
|
one:
|
||||||
|
url: 'redis://localhost:6379/1'
|
||||||
|
|
||||||
|
two:
|
||||||
|
url: 'redis://localhost:6379/2'
|
|
@ -15,6 +15,10 @@ another_orm = ENV['ANOTHER_ORM']
|
||||||
strategy = ENV['STRATEGY']
|
strategy = ENV['STRATEGY']
|
||||||
multiple_db = ENV['MULTIPLE_DBS']
|
multiple_db = ENV['MULTIPLE_DBS']
|
||||||
|
|
||||||
|
config = YAML::load(File.open("#{File.dirname(__FILE__)}/../../config/redis.yml"))
|
||||||
|
ENV['REDIS_URL'] = config['test']['url']
|
||||||
|
ENV['REDIS_URL_ONE'] = config['one']['url']
|
||||||
|
ENV['REDIS_URL_TWO'] = config['two']['url']
|
||||||
|
|
||||||
if orm && strategy
|
if orm && strategy
|
||||||
$:.unshift(File.dirname(__FILE__) + '/../../../lib')
|
$:.unshift(File.dirname(__FILE__) + '/../../../lib')
|
||||||
|
@ -37,6 +41,9 @@ if orm && strategy
|
||||||
when :mongo_mapper
|
when :mongo_mapper
|
||||||
DatabaseCleaner[ orm_sym, {:connection => 'database_cleaner_test_one'} ].strategy = strategy.to_sym
|
DatabaseCleaner[ orm_sym, {:connection => 'database_cleaner_test_one'} ].strategy = strategy.to_sym
|
||||||
DatabaseCleaner[ orm_sym, {:connection => 'database_cleaner_test_two'} ].strategy = strategy.to_sym
|
DatabaseCleaner[ orm_sym, {:connection => 'database_cleaner_test_two'} ].strategy = strategy.to_sym
|
||||||
|
when :redis, :ohm
|
||||||
|
DatabaseCleaner[ orm_sym, {:connection => ENV['REDIS_URL_ONE']} ].strategy = strategy.to_sym
|
||||||
|
DatabaseCleaner[ orm_sym, {:connection => ENV['REDIS_URL_TWO']} ].strategy = strategy.to_sym
|
||||||
when :active_record
|
when :active_record
|
||||||
DatabaseCleaner[:active_record, {:model => ActiveRecordWidgetUsingDatabaseOne} ].strategy = strategy.to_sym
|
DatabaseCleaner[:active_record, {:model => ActiveRecordWidgetUsingDatabaseOne} ].strategy = strategy.to_sym
|
||||||
DatabaseCleaner[:active_record, {:model => ActiveRecordWidgetUsingDatabaseTwo} ].strategy = strategy.to_sym
|
DatabaseCleaner[:active_record, {:model => ActiveRecordWidgetUsingDatabaseTwo} ].strategy = strategy.to_sym
|
||||||
|
@ -53,5 +60,5 @@ if orm && strategy
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
raise "Run 'ORM=ActiveRecord|DataMapper|MongoMapper|CouchPotato [ANOTHER_ORM=...] [MULTIPLE_DBS=true] STRATEGY=transaction|truncation|default cucumber examples/features'"
|
raise "Run 'ORM=ActiveRecord|DataMapper|MongoMapper|CouchPotato|Ohm|Redis [ANOTHER_ORM=...] [MULTIPLE_DBS=true] STRATEGY=transaction|truncation|default cucumber examples/features'"
|
||||||
end
|
end
|
||||||
|
|
43
examples/lib/ohm_models.rb
Normal file
43
examples/lib/ohm_models.rb
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
require 'ohm'
|
||||||
|
|
||||||
|
Ohm.connect :url => ENV['REDIS_URL']
|
||||||
|
|
||||||
|
class OhmWidget < Ohm::Model
|
||||||
|
attribute :name
|
||||||
|
|
||||||
|
def self.create!(attrs = {})
|
||||||
|
new({:name => 'some widget'}.merge(attrs)).save
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.count
|
||||||
|
all.count
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
class OhmWidgetUsingDatabaseOne < Ohm::Model
|
||||||
|
connect :url => ENV['REDIS_URL_ONE']
|
||||||
|
attribute :name
|
||||||
|
|
||||||
|
def self.create!(attrs = {})
|
||||||
|
new({:name => 'a widget using database one'}.merge(attrs)).save
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.count
|
||||||
|
all.count
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
class OhmWidgetUsingDatabaseTwo < Ohm::Model
|
||||||
|
connect :url => ENV['REDIS_URL_TWO']
|
||||||
|
attribute :name
|
||||||
|
|
||||||
|
def self.create!(attrs = {})
|
||||||
|
new({:name => 'a widget using database two'}.merge(attrs)).save
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.count
|
||||||
|
all.count
|
||||||
|
end
|
||||||
|
end
|
65
examples/lib/redis_models.rb
Normal file
65
examples/lib/redis_models.rb
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
require 'redis'
|
||||||
|
|
||||||
|
class RedisWidget
|
||||||
|
|
||||||
|
def self.redis
|
||||||
|
threaded ||= Redis.connect
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.redis=(connection)
|
||||||
|
threaded = connection
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.threaded
|
||||||
|
Thread.current[self.class.to_s] ||= {}
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(options = {})
|
||||||
|
options = options.dup
|
||||||
|
@name = options[:name]
|
||||||
|
end
|
||||||
|
|
||||||
|
def connection
|
||||||
|
self.class.redis
|
||||||
|
end
|
||||||
|
|
||||||
|
def save
|
||||||
|
unless connection.get(self.class.to_s + ':id')
|
||||||
|
@id = 0
|
||||||
|
connection.set(self.class.to_s + ':id', @id)
|
||||||
|
end
|
||||||
|
@id = connection.incr(self.class.to_s + ':id')
|
||||||
|
connection.set(self.class.to_s + ':%d:name' % @id, @name)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.count
|
||||||
|
self.redis.keys(self.to_s + '*name').size
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create!
|
||||||
|
new(:name => 'some widget').save
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class RedisWidgetUsingDatabaseOne < RedisWidget
|
||||||
|
|
||||||
|
def self.redis
|
||||||
|
threaded[self.class.to_s] ||= Redis.connect :url => ENV['REDIS_URL_ONE']
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create!
|
||||||
|
new(:name => 'a widget using database one').save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class RedisWidgetUsingDatabaseTwo < RedisWidget
|
||||||
|
|
||||||
|
def self.redis
|
||||||
|
threaded[self.class.to_s] ||= Redis.connect :url => ENV['REDIS_URL_TWO']
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.create!
|
||||||
|
new(:name => 'a widget using database two').save
|
||||||
|
end
|
||||||
|
end
|
|
@ -11,12 +11,14 @@ Feature: database cleaning
|
||||||
Then I should see all green
|
Then I should see all green
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
| ORM | Strategy |
|
| ORM | Strategy |
|
||||||
| ActiveRecord | transaction |
|
| ActiveRecord | transaction |
|
||||||
| ActiveRecord | truncation |
|
| ActiveRecord | truncation |
|
||||||
| ActiveRecord | deletion |
|
| ActiveRecord | deletion |
|
||||||
| DataMapper | transaction |
|
| DataMapper | transaction |
|
||||||
| DataMapper | truncation |
|
| DataMapper | truncation |
|
||||||
| MongoMapper | truncation |
|
| MongoMapper | truncation |
|
||||||
| Mongoid | truncation |
|
| Mongoid | truncation |
|
||||||
| CouchPotato | truncation |
|
| CouchPotato | truncation |
|
||||||
|
| Redis | truncation |
|
||||||
|
| Ohm | truncation |
|
||||||
|
|
|
@ -17,3 +17,5 @@ Feature: database cleaning
|
||||||
| MongoMapper |
|
| MongoMapper |
|
||||||
| Mongoid |
|
| Mongoid |
|
||||||
| CouchPotato |
|
| CouchPotato |
|
||||||
|
| Redis |
|
||||||
|
| Ohm |
|
||||||
|
|
|
@ -15,15 +15,34 @@ Feature: database cleaning using multiple ORMs
|
||||||
| ActiveRecord | MongoMapper |
|
| ActiveRecord | MongoMapper |
|
||||||
| ActiveRecord | Mongoid |
|
| ActiveRecord | Mongoid |
|
||||||
| ActiveRecord | CouchPotato |
|
| ActiveRecord | CouchPotato |
|
||||||
|
| ActiveRecord | Ohm |
|
||||||
|
| ActiveRecord | Redis |
|
||||||
| DataMapper | ActiveRecord |
|
| DataMapper | ActiveRecord |
|
||||||
| DataMapper | MongoMapper |
|
| DataMapper | MongoMapper |
|
||||||
| DataMapper | Mongoid |
|
| DataMapper | Mongoid |
|
||||||
| DataMapper | CouchPotato |
|
| DataMapper | CouchPotato |
|
||||||
|
| DataMapper | Ohm |
|
||||||
|
| DataMapper | Redis |
|
||||||
| MongoMapper | ActiveRecord |
|
| MongoMapper | ActiveRecord |
|
||||||
| MongoMapper | DataMapper |
|
| MongoMapper | DataMapper |
|
||||||
| MongoMapper | Mongoid |
|
| MongoMapper | Mongoid |
|
||||||
| MongoMapper | CouchPotato |
|
| MongoMapper | CouchPotato |
|
||||||
|
| MongoMapper | Ohm |
|
||||||
|
| MongoMapper | Redis |
|
||||||
| CouchPotato | ActiveRecord |
|
| CouchPotato | ActiveRecord |
|
||||||
| CouchPotato | DataMapper |
|
| CouchPotato | DataMapper |
|
||||||
| CouchPotato | MongoMapper |
|
| CouchPotato | MongoMapper |
|
||||||
| CouchPotato | Mongoid |
|
| CouchPotato | Mongoid |
|
||||||
|
| CouchPotato | Ohm |
|
||||||
|
| CouchPotato | Redis |
|
||||||
|
| Ohm | ActiveRecord |
|
||||||
|
| Ohm | DataMapper |
|
||||||
|
| Ohm | MongoMapper |
|
||||||
|
| Ohm | Mongoid |
|
||||||
|
| Ohm | CouchPotato |
|
||||||
|
| Redis | ActiveRecord |
|
||||||
|
| Redis | DataMapper |
|
||||||
|
| Redis | MongoMapper |
|
||||||
|
| Redis | Mongoid |
|
||||||
|
| Redis | CouchPotato |
|
||||||
|
| Redis | Ohm |
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
orms_pattern = /(ActiveRecord|DataMapper|MongoMapper|Mongoid|CouchPotato|Redis|Ohm)/
|
||||||
|
|
||||||
Given /^I am using (ActiveRecord|DataMapper|MongoMapper|Mongoid|CouchPotato)$/ do |orm|
|
Given /^I am using #{orms_pattern}$/ do |orm|
|
||||||
@feature_runner = FeatureRunner.new
|
@feature_runner = FeatureRunner.new
|
||||||
@feature_runner.orm = orm
|
@feature_runner.orm = orm
|
||||||
end
|
end
|
||||||
|
|
||||||
Given /^I am using (ActiveRecord|DataMapper|MongoMapper|CouchPotato|Mongoid) and (ActiveRecord|DataMapper|MongoMapper|CouchPotato|Mongoid)$/ do |orm1,orm2|
|
Given /^I am using #{orms_pattern} and #{orms_pattern}$/ do |orm1,orm2|
|
||||||
@feature_runner = FeatureRunner.new
|
@feature_runner = FeatureRunner.new
|
||||||
@feature_runner.orm = orm1
|
@feature_runner.orm = orm1
|
||||||
@feature_runner.another_orm = orm2
|
@feature_runner.another_orm = orm2
|
||||||
|
|
31
features/step_definitions/ohm_steps.rb
Normal file
31
features/step_definitions/ohm_steps.rb
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
Given /^I have setup database cleaner to clean multiple databases using ohm$/ do
|
||||||
|
#DatabaseCleaner
|
||||||
|
# require "#{File.dirname(__FILE__)}/../../../lib/ohm_models"
|
||||||
|
#
|
||||||
|
# DatabaseCleaner[:ohm, {:connection => ENV['REDIS_URL_ONE']} ].strategy = :truncation
|
||||||
|
# DatabaseCleaner[:ohm, {:connection => ENV['REDIS_URL_TWO']} ].strategy = :truncation
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I create a widget using ohm$/ do
|
||||||
|
OhmWidget.create!
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^I should see ([\d]+) widget using ohm$/ do |widget_count|
|
||||||
|
OhmWidget.count.should == widget_count.to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I create a widget in one db using ohm$/ do
|
||||||
|
OhmWidgetUsingDatabaseOne.create!
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I create a widget in another db using ohm$/ do
|
||||||
|
OhmWidgetUsingDatabaseTwo.create!
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^I should see ([\d]+) widget in one db using ohm$/ do |widget_count|
|
||||||
|
OhmWidgetUsingDatabaseOne.count.should == widget_count.to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^I should see ([\d]+) widget in another db using ohm$/ do |widget_count|
|
||||||
|
OhmWidgetUsingDatabaseTwo.count.should == widget_count.to_i
|
||||||
|
end
|
31
features/step_definitions/redis_steps.rb
Normal file
31
features/step_definitions/redis_steps.rb
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
Given /^I have setup database cleaner to clean multiple databases using redis$/ do
|
||||||
|
#DatabaseCleaner
|
||||||
|
# require "#{File.dirname(__FILE__)}/../../../lib/redis_models"
|
||||||
|
#
|
||||||
|
# DatabaseCleaner[:redis, {:connection => ENV['REDIS_URL_ONE']} ].strategy = :truncation
|
||||||
|
# DatabaseCleaner[:redis, {:connection => ENV['REDIS_URL_TWO']} ].strategy = :truncation
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I create a widget using redis$/ do
|
||||||
|
RedisWidget.create!
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^I should see ([\d]+) widget using redis$/ do |widget_count|
|
||||||
|
RedisWidget.count.should == widget_count.to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I create a widget in one db using redis$/ do
|
||||||
|
RedisWidgetUsingDatabaseOne.create!
|
||||||
|
end
|
||||||
|
|
||||||
|
When /^I create a widget in another db using redis$/ do
|
||||||
|
RedisWidgetUsingDatabaseTwo.create!
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^I should see ([\d]+) widget in one db using redis$/ do |widget_count|
|
||||||
|
RedisWidgetUsingDatabaseOne.count.should == widget_count.to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^I should see ([\d]+) widget in another db using redis$/ do |widget_count|
|
||||||
|
RedisWidgetUsingDatabaseTwo.count.should == widget_count.to_i
|
||||||
|
end
|
|
@ -38,10 +38,6 @@ module DatabaseCleaner
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_connection_class
|
|
||||||
Class.new(::ActiveRecord::Base)
|
|
||||||
end
|
|
||||||
|
|
||||||
def connection_class
|
def connection_class
|
||||||
@connection_class ||= if @db && !@db.is_a?(Symbol)
|
@connection_class ||= if @db && !@db.is_a?(Symbol)
|
||||||
@db
|
@db
|
||||||
|
@ -63,9 +59,7 @@ module DatabaseCleaner
|
||||||
end
|
end
|
||||||
|
|
||||||
def establish_connection
|
def establish_connection
|
||||||
strategy_class = create_connection_class
|
::ActiveRecord::Base.establish_connection(connection_hash)
|
||||||
strategy_class.send :establish_connection, connection_hash
|
|
||||||
strategy_class
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,10 @@ module DatabaseCleaner::ActiveRecord
|
||||||
include ::DatabaseCleaner::Generic::Transaction
|
include ::DatabaseCleaner::Generic::Transaction
|
||||||
|
|
||||||
def start
|
def start
|
||||||
|
# Hack to make sure that the connection is properly setup for
|
||||||
|
# the clean code.
|
||||||
|
connection_class.connection.transaction{ }
|
||||||
|
|
||||||
if connection_maintains_transaction_count?
|
if connection_maintains_transaction_count?
|
||||||
if connection_class.connection.respond_to?(:increment_open_transactions)
|
if connection_class.connection.respond_to?(:increment_open_transactions)
|
||||||
connection_class.connection.increment_open_transactions
|
connection_class.connection.increment_open_transactions
|
||||||
|
|
|
@ -36,12 +36,22 @@ module DatabaseCleaner
|
||||||
|
|
||||||
def clean_with(*args)
|
def clean_with(*args)
|
||||||
strategy = create_strategy(*args)
|
strategy = create_strategy(*args)
|
||||||
|
set_strategy_db strategy, self.db
|
||||||
|
|
||||||
strategy.clean
|
strategy.clean
|
||||||
strategy
|
strategy
|
||||||
end
|
end
|
||||||
|
|
||||||
alias clean_with! clean_with
|
alias clean_with! clean_with
|
||||||
|
|
||||||
|
def set_strategy_db(strategy, desired_db)
|
||||||
|
if strategy.respond_to? :db=
|
||||||
|
strategy.db = desired_db
|
||||||
|
elsif desired_db != :default
|
||||||
|
raise ArgumentError, "You must provide a strategy object that supports non default databases when you specify a database"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def strategy=(args)
|
def strategy=(args)
|
||||||
strategy, *strategy_args = args
|
strategy, *strategy_args = args
|
||||||
if strategy.is_a?(Symbol)
|
if strategy.is_a?(Symbol)
|
||||||
|
@ -52,7 +62,7 @@ module DatabaseCleaner
|
||||||
raise ArgumentError, "You must provide a strategy object, or a symbol for a known strategy along with initialization params."
|
raise ArgumentError, "You must provide a strategy object, or a symbol for a known strategy along with initialization params."
|
||||||
end
|
end
|
||||||
|
|
||||||
self.strategy_db = self.db
|
set_strategy_db @strategy, self.db
|
||||||
|
|
||||||
@strategy
|
@strategy
|
||||||
end
|
end
|
||||||
|
@ -120,8 +130,14 @@ module DatabaseCleaner
|
||||||
:couch_potato
|
:couch_potato
|
||||||
elsif defined? ::Sequel
|
elsif defined? ::Sequel
|
||||||
:sequel
|
:sequel
|
||||||
|
elsif defined? ::Moped
|
||||||
|
:moped
|
||||||
|
elsif defined? ::Ohm
|
||||||
|
:ohm
|
||||||
|
elsif defined? ::Redis
|
||||||
|
:redis
|
||||||
else
|
else
|
||||||
raise NoORMDetected, "No known ORM was detected! Is ActiveRecord, DataMapper, Sequel, MongoMapper, Mongoid, or CouchPotato loaded?"
|
raise NoORMDetected, "No known ORM was detected! Is ActiveRecord, DataMapper, Sequel, MongoMapper, Mongoid, Moped, or CouchPotato, Redis or Ohm loaded?"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -130,7 +146,7 @@ module DatabaseCleaner
|
||||||
case orm
|
case orm
|
||||||
when :active_record, :data_mapper, :sequel
|
when :active_record, :data_mapper, :sequel
|
||||||
self.strategy = :transaction
|
self.strategy = :transaction
|
||||||
when :mongo_mapper, :mongoid, :couch_potato
|
when :mongo_mapper, :mongoid, :couch_potato, :moped, :ohm, :redis
|
||||||
self.strategy = :truncation
|
self.strategy = :truncation
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,7 +11,7 @@ module DatabaseCleaner
|
||||||
# ghetto ordered hash.. maintains 1.8 compat and old API
|
# ghetto ordered hash.. maintains 1.8 compat and old API
|
||||||
@connections ||= []
|
@connections ||= []
|
||||||
end
|
end
|
||||||
|
|
||||||
def [](orm,opts = {})
|
def [](orm,opts = {})
|
||||||
raise NoORMDetected unless orm
|
raise NoORMDetected unless orm
|
||||||
init_cleaners
|
init_cleaners
|
||||||
|
@ -113,6 +113,10 @@ module DatabaseCleaner
|
||||||
DatabaseCleaner::CouchPotato
|
DatabaseCleaner::CouchPotato
|
||||||
when :sequel
|
when :sequel
|
||||||
DatabaseCleaner::Sequel
|
DatabaseCleaner::Sequel
|
||||||
|
when :ohm
|
||||||
|
DatabaseCleaner::Ohm
|
||||||
|
when :redis
|
||||||
|
DatabaseCleaner::Redis
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
require 'database_cleaner/mongoid/base'
|
require 'database_cleaner/mongoid/base'
|
||||||
require 'database_cleaner/generic/truncation'
|
require 'database_cleaner/generic/truncation'
|
||||||
require 'database_cleaner/mongo/truncation_mixin'
|
require 'database_cleaner/mongo/truncation_mixin'
|
||||||
require 'database_cleaner/moped/truncation'
|
require 'database_cleaner/moped/truncation_base'
|
||||||
require 'mongoid/version'
|
require 'mongoid/version'
|
||||||
|
|
||||||
module DatabaseCleaner
|
module DatabaseCleaner
|
||||||
|
@ -22,7 +22,7 @@ module DatabaseCleaner
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
include ::DatabaseCleaner::Moped::Truncation
|
include ::DatabaseCleaner::Moped::TruncationBase
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
35
lib/database_cleaner/moped/base.rb
Normal file
35
lib/database_cleaner/moped/base.rb
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
require 'database_cleaner/generic/base'
|
||||||
|
|
||||||
|
module DatabaseCleaner
|
||||||
|
module Moped
|
||||||
|
def self.available_strategies
|
||||||
|
%w[truncation]
|
||||||
|
end
|
||||||
|
|
||||||
|
module Base
|
||||||
|
include ::DatabaseCleaner::Generic::Base
|
||||||
|
|
||||||
|
def db=(desired_db)
|
||||||
|
@db = desired_db
|
||||||
|
end
|
||||||
|
|
||||||
|
def db
|
||||||
|
@db || :default
|
||||||
|
end
|
||||||
|
|
||||||
|
def host_port=(desired_host)
|
||||||
|
@host = desired_host
|
||||||
|
end
|
||||||
|
|
||||||
|
def host
|
||||||
|
@host || '127.0.0.1:27017'
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def session
|
||||||
|
::Moped::Session.new([host], database: db)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,29 +1,9 @@
|
||||||
|
require 'database_cleaner/moped/truncation_base'
|
||||||
|
|
||||||
module DatabaseCleaner
|
module DatabaseCleaner
|
||||||
module Moped
|
module Moped
|
||||||
module Truncation
|
class Truncation
|
||||||
|
include ::DatabaseCleaner::Moped::TruncationBase
|
||||||
def clean
|
|
||||||
if @only
|
|
||||||
collections.each { |c| session[c].find.remove_all if @only.include?(c) }
|
|
||||||
else
|
|
||||||
collections.each { |c| session[c].find.remove_all unless @tables_to_exclude.include?(c) }
|
|
||||||
end
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def collections
|
|
||||||
if db != :default
|
|
||||||
session.use(db)
|
|
||||||
end
|
|
||||||
|
|
||||||
session['system.namespaces'].find(:name => { '$not' => /system|\$/ }).to_a.map do |collection|
|
|
||||||
_, name = collection['name'].split('.', 2)
|
|
||||||
name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
34
lib/database_cleaner/moped/truncation_base.rb
Normal file
34
lib/database_cleaner/moped/truncation_base.rb
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
require 'database_cleaner/moped/base'
|
||||||
|
require 'database_cleaner/generic/truncation'
|
||||||
|
|
||||||
|
module DatabaseCleaner
|
||||||
|
module Moped
|
||||||
|
module TruncationBase
|
||||||
|
include ::DatabaseCleaner::Moped::Base
|
||||||
|
include ::DatabaseCleaner::Generic::Truncation
|
||||||
|
|
||||||
|
def clean
|
||||||
|
if @only
|
||||||
|
collections.each { |c| session[c].find.remove_all if @only.include?(c) }
|
||||||
|
else
|
||||||
|
collections.each { |c| session[c].find.remove_all unless @tables_to_exclude.include?(c) }
|
||||||
|
end
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def collections
|
||||||
|
if db != :default
|
||||||
|
session.use(db)
|
||||||
|
end
|
||||||
|
|
||||||
|
session['system.namespaces'].find(:name => { '$not' => /system|\$/ }).to_a.map do |collection|
|
||||||
|
_, name = collection['name'].split('.', 2)
|
||||||
|
name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
15
lib/database_cleaner/ohm/truncation.rb
Normal file
15
lib/database_cleaner/ohm/truncation.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
require 'database_cleaner/redis/truncation'
|
||||||
|
|
||||||
|
module DatabaseCleaner
|
||||||
|
module Ohm
|
||||||
|
class Truncation < ::DatabaseCleaner::Redis::Truncation
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def default_redis
|
||||||
|
::Ohm.redis
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
31
lib/database_cleaner/redis/base.rb
Normal file
31
lib/database_cleaner/redis/base.rb
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
require 'database_cleaner/generic/base'
|
||||||
|
|
||||||
|
module DatabaseCleaner
|
||||||
|
module Redis
|
||||||
|
def self.available_strategies
|
||||||
|
%w{truncation}
|
||||||
|
end
|
||||||
|
|
||||||
|
module Base
|
||||||
|
include ::DatabaseCleaner::Generic::Base
|
||||||
|
|
||||||
|
def db=(desired_db)
|
||||||
|
@db = desired_db
|
||||||
|
end
|
||||||
|
|
||||||
|
def db
|
||||||
|
@db || :default
|
||||||
|
end
|
||||||
|
|
||||||
|
alias url db
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def connection
|
||||||
|
@connection ||= url == :default ? ::Redis.connect : ::Redis.connect(:url => url)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
26
lib/database_cleaner/redis/truncation.rb
Normal file
26
lib/database_cleaner/redis/truncation.rb
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
require 'database_cleaner/redis/base'
|
||||||
|
require 'database_cleaner/generic/truncation'
|
||||||
|
|
||||||
|
module DatabaseCleaner
|
||||||
|
module Redis
|
||||||
|
class Truncation
|
||||||
|
include ::DatabaseCleaner::Redis::Base
|
||||||
|
include ::DatabaseCleaner::Generic::Truncation
|
||||||
|
|
||||||
|
def clean
|
||||||
|
if @only
|
||||||
|
@only.each do |term|
|
||||||
|
connection.keys(term).each { |k| connection.del k }
|
||||||
|
end
|
||||||
|
elsif @tables_to_exclude
|
||||||
|
keys_except = []
|
||||||
|
@tables_to_exclude.each { |term| keys_except += connection.keys(term) }
|
||||||
|
connection.keys.each { |k| connection.del(k) unless keys_except.include?(k) }
|
||||||
|
else
|
||||||
|
connection.flushdb
|
||||||
|
end
|
||||||
|
connection.quit unless url == :default
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -119,16 +119,6 @@ my_db:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "create_connection_class" do
|
|
||||||
it "should return a class" do
|
|
||||||
subject.create_connection_class.should be_a(Class)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should return a class extending ::ActiveRecord::Base" do
|
|
||||||
subject.create_connection_class.ancestors.should include(::ActiveRecord::Base)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "connection_class" do
|
describe "connection_class" do
|
||||||
it { expect { subject.connection_class }.to_not raise_error }
|
it { expect { subject.connection_class }.to_not raise_error }
|
||||||
it "should default to ActiveRecord::Base" do
|
it "should default to ActiveRecord::Base" do
|
||||||
|
@ -158,16 +148,9 @@ my_db:
|
||||||
before { ::ActiveRecord::Base.stub!(:respond_to?).and_return(false) }
|
before { ::ActiveRecord::Base.stub!(:respond_to?).and_return(false) }
|
||||||
before { subject.stub(:connection_hash).and_return(hash) }
|
before { subject.stub(:connection_hash).and_return(hash) }
|
||||||
|
|
||||||
it "should create connection_class if it doesnt exist if connection_hash is set" do
|
it "establish a connection using ActiveRecord::Base" do
|
||||||
subject.should_receive(:create_connection_class).and_return(mock('class').as_null_object)
|
::ActiveRecord::Base.should_receive(:establish_connection).with(hash)
|
||||||
subject.connection_class
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should configure the class from create_connection_class if connection_hash is set" do
|
|
||||||
strategy_class = mock('strategy_class')
|
|
||||||
strategy_class.should_receive(:establish_connection).with(hash)
|
|
||||||
|
|
||||||
subject.should_receive(:create_connection_class).and_return(strategy_class)
|
|
||||||
subject.connection_class
|
subject.connection_class
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,6 +15,7 @@ module DatabaseCleaner
|
||||||
[:begin_transaction, :begin_db_transaction].each do |begin_transaction_method|
|
[:begin_transaction, :begin_db_transaction].each do |begin_transaction_method|
|
||||||
context "using #{begin_transaction_method}" do
|
context "using #{begin_transaction_method}" do
|
||||||
before do
|
before do
|
||||||
|
connection.stub(:transaction)
|
||||||
connection.stub(begin_transaction_method)
|
connection.stub(begin_transaction_method)
|
||||||
connection.stub(:respond_to?).with(:begin_transaction).and_return(:begin_transaction == begin_transaction_method)
|
connection.stub(:respond_to?).with(:begin_transaction).and_return(:begin_transaction == begin_transaction_method)
|
||||||
end
|
end
|
||||||
|
@ -35,6 +36,7 @@ module DatabaseCleaner
|
||||||
connection.stub(:respond_to?).with(:increment_open_transactions).and_return(true)
|
connection.stub(:respond_to?).with(:increment_open_transactions).and_return(true)
|
||||||
connection.stub(:increment_open_transactions)
|
connection.stub(:increment_open_transactions)
|
||||||
connection.should_receive(begin_transaction_method)
|
connection.should_receive(begin_transaction_method)
|
||||||
|
connection.should_receive(:transaction)
|
||||||
Transaction.new.start
|
Transaction.new.start
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,6 +18,9 @@ module DatabaseCleaner
|
||||||
Temp_MO = ::Mongoid if defined?(::Mongoid) and not defined?(Temp_MO)
|
Temp_MO = ::Mongoid if defined?(::Mongoid) and not defined?(Temp_MO)
|
||||||
Temp_CP = ::CouchPotato if defined?(::CouchPotato) and not defined?(Temp_CP)
|
Temp_CP = ::CouchPotato if defined?(::CouchPotato) and not defined?(Temp_CP)
|
||||||
Temp_SQ = ::Sequel if defined?(::Sequel) and not defined?(Temp_SQ)
|
Temp_SQ = ::Sequel if defined?(::Sequel) and not defined?(Temp_SQ)
|
||||||
|
Temp_MP = ::Moped if defined?(::Moped) and not defined?(Temp_MP)
|
||||||
|
Temp_RS = ::Redis if defined?(::Redis) and not defined?(Temp_RS)
|
||||||
|
Temp_OH = ::Ohm if defined?(::Ohm) and not defined?(Temp_OH)
|
||||||
end
|
end
|
||||||
|
|
||||||
#Remove all ORM mocks and restore from cache
|
#Remove all ORM mocks and restore from cache
|
||||||
|
@ -28,6 +31,9 @@ module DatabaseCleaner
|
||||||
Object.send(:remove_const, 'Mongoid') if defined?(::Mongoid)
|
Object.send(:remove_const, 'Mongoid') if defined?(::Mongoid)
|
||||||
Object.send(:remove_const, 'CouchPotato') if defined?(::CouchPotato)
|
Object.send(:remove_const, 'CouchPotato') if defined?(::CouchPotato)
|
||||||
Object.send(:remove_const, 'Sequel') if defined?(::Sequel)
|
Object.send(:remove_const, 'Sequel') if defined?(::Sequel)
|
||||||
|
Object.send(:remove_const, 'Moped') if defined?(::Moped)
|
||||||
|
Object.send(:remove_const, 'Ohm') if defined?(::Ohm)
|
||||||
|
Object.send(:remove_const, 'Redis') if defined?(::Redis)
|
||||||
|
|
||||||
|
|
||||||
# Restore ORMs
|
# Restore ORMs
|
||||||
|
@ -36,6 +42,9 @@ module DatabaseCleaner
|
||||||
::MongoMapper = Temp_MM if defined? Temp_MM
|
::MongoMapper = Temp_MM if defined? Temp_MM
|
||||||
::Mongoid = Temp_MO if defined? Temp_MO
|
::Mongoid = Temp_MO if defined? Temp_MO
|
||||||
::CouchPotato = Temp_CP if defined? Temp_CP
|
::CouchPotato = Temp_CP if defined? Temp_CP
|
||||||
|
::Moped = Temp_MP if defined? Temp_MP
|
||||||
|
::Ohm = Temp_OH if defined? Temp_OH
|
||||||
|
::Redis = Temp_RS if defined? Temp_RS
|
||||||
end
|
end
|
||||||
|
|
||||||
#reset the orm mocks
|
#reset the orm mocks
|
||||||
|
@ -46,8 +55,11 @@ module DatabaseCleaner
|
||||||
Object.send(:remove_const, 'Mongoid') if defined?(::Mongoid)
|
Object.send(:remove_const, 'Mongoid') if defined?(::Mongoid)
|
||||||
Object.send(:remove_const, 'CouchPotato') if defined?(::CouchPotato)
|
Object.send(:remove_const, 'CouchPotato') if defined?(::CouchPotato)
|
||||||
Object.send(:remove_const, 'Sequel') if defined?(::Sequel)
|
Object.send(:remove_const, 'Sequel') if defined?(::Sequel)
|
||||||
|
Object.send(:remove_const, 'Moped') if defined?(::Moped)
|
||||||
|
Object.send(:remove_const, 'Ohm') if defined?(::Ohm)
|
||||||
|
Object.send(:remove_const, 'Redis') if defined?(::Redis)
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:cleaner) { DatabaseCleaner::Base.new :autodetect }
|
let(:cleaner) { DatabaseCleaner::Base.new :autodetect }
|
||||||
|
|
||||||
it "should raise an error when no ORM is detected" do
|
it "should raise an error when no ORM is detected" do
|
||||||
|
@ -61,6 +73,9 @@ module DatabaseCleaner
|
||||||
Object.const_set('Mongoid', 'Mongoid mock')
|
Object.const_set('Mongoid', 'Mongoid mock')
|
||||||
Object.const_set('CouchPotato', 'Couching mock potatos')
|
Object.const_set('CouchPotato', 'Couching mock potatos')
|
||||||
Object.const_set('Sequel', 'Sequel mock')
|
Object.const_set('Sequel', 'Sequel mock')
|
||||||
|
Object.const_set('Moped', 'Moped mock')
|
||||||
|
Object.const_set('Ohm', 'Ohm mock')
|
||||||
|
Object.const_set('Redis', 'Redis mock')
|
||||||
|
|
||||||
cleaner.orm.should == :active_record
|
cleaner.orm.should == :active_record
|
||||||
cleaner.should be_auto_detected
|
cleaner.should be_auto_detected
|
||||||
|
@ -72,6 +87,9 @@ module DatabaseCleaner
|
||||||
Object.const_set('Mongoid', 'Mongoid mock')
|
Object.const_set('Mongoid', 'Mongoid mock')
|
||||||
Object.const_set('CouchPotato', 'Couching mock potatos')
|
Object.const_set('CouchPotato', 'Couching mock potatos')
|
||||||
Object.const_set('Sequel', 'Sequel mock')
|
Object.const_set('Sequel', 'Sequel mock')
|
||||||
|
Object.const_set('Moped', 'Moped mock')
|
||||||
|
Object.const_set('Ohm', 'Ohm mock')
|
||||||
|
Object.const_set('Redis', 'Redis mock')
|
||||||
|
|
||||||
cleaner.orm.should == :data_mapper
|
cleaner.orm.should == :data_mapper
|
||||||
cleaner.should be_auto_detected
|
cleaner.should be_auto_detected
|
||||||
|
@ -82,6 +100,9 @@ module DatabaseCleaner
|
||||||
Object.const_set('Mongoid', 'Mongoid mock')
|
Object.const_set('Mongoid', 'Mongoid mock')
|
||||||
Object.const_set('CouchPotato', 'Couching mock potatos')
|
Object.const_set('CouchPotato', 'Couching mock potatos')
|
||||||
Object.const_set('Sequel', 'Sequel mock')
|
Object.const_set('Sequel', 'Sequel mock')
|
||||||
|
Object.const_set('Moped', 'Moped mock')
|
||||||
|
Object.const_set('Ohm', 'Ohm mock')
|
||||||
|
Object.const_set('Redis', 'Redis mock')
|
||||||
|
|
||||||
cleaner.orm.should == :mongo_mapper
|
cleaner.orm.should == :mongo_mapper
|
||||||
cleaner.should be_auto_detected
|
cleaner.should be_auto_detected
|
||||||
|
@ -91,6 +112,9 @@ module DatabaseCleaner
|
||||||
Object.const_set('Mongoid', 'Mongoid mock')
|
Object.const_set('Mongoid', 'Mongoid mock')
|
||||||
Object.const_set('CouchPotato', 'Couching mock potatos')
|
Object.const_set('CouchPotato', 'Couching mock potatos')
|
||||||
Object.const_set('Sequel', 'Sequel mock')
|
Object.const_set('Sequel', 'Sequel mock')
|
||||||
|
Object.const_set('Moped', 'Moped mock')
|
||||||
|
Object.const_set('Ohm', 'Ohm mock')
|
||||||
|
Object.const_set('Redis', 'Redis mock')
|
||||||
|
|
||||||
cleaner.orm.should == :mongoid
|
cleaner.orm.should == :mongoid
|
||||||
cleaner.should be_auto_detected
|
cleaner.should be_auto_detected
|
||||||
|
@ -99,17 +123,45 @@ module DatabaseCleaner
|
||||||
it "should detect CouchPotato fifth" do
|
it "should detect CouchPotato fifth" do
|
||||||
Object.const_set('CouchPotato', 'Couching mock potatos')
|
Object.const_set('CouchPotato', 'Couching mock potatos')
|
||||||
Object.const_set('Sequel', 'Sequel mock')
|
Object.const_set('Sequel', 'Sequel mock')
|
||||||
|
Object.const_set('Moped', 'Moped mock')
|
||||||
|
Object.const_set('Ohm', 'Ohm mock')
|
||||||
|
Object.const_set('Redis', 'Redis mock')
|
||||||
|
|
||||||
cleaner.orm.should == :couch_potato
|
cleaner.orm.should == :couch_potato
|
||||||
cleaner.should be_auto_detected
|
cleaner.should be_auto_detected
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should detect Sequel last" do
|
it "should detect Sequel sixth" do
|
||||||
Object.const_set('Sequel', 'Sequel mock')
|
Object.const_set('Sequel', 'Sequel mock')
|
||||||
|
Object.const_set('Moped', 'Moped mock')
|
||||||
|
Object.const_set('Ohm', 'Ohm mock')
|
||||||
|
Object.const_set('Redis', 'Redis mock')
|
||||||
|
|
||||||
cleaner.orm.should == :sequel
|
cleaner.orm.should == :sequel
|
||||||
cleaner.should be_auto_detected
|
cleaner.should be_auto_detected
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'detects Ohm seventh' do
|
||||||
|
Object.const_set('Ohm', 'Ohm mock')
|
||||||
|
Object.const_set('Redis', 'Redis mock')
|
||||||
|
|
||||||
|
cleaner.orm.should == :ohm
|
||||||
|
cleaner.should be_auto_detected
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'detects Redis last' do
|
||||||
|
Object.const_set('Redis', 'Redis mock')
|
||||||
|
|
||||||
|
cleaner.orm.should == :redis
|
||||||
|
cleaner.should be_auto_detected
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'detects Moped seventh' do
|
||||||
|
Object.const_set('Moped', 'Moped mock')
|
||||||
|
|
||||||
|
cleaner.orm.should == :moped
|
||||||
|
cleaner.should be_auto_detected
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "orm_module" do
|
describe "orm_module" do
|
||||||
|
@ -160,7 +212,7 @@ module DatabaseCleaner
|
||||||
cleaner = ::DatabaseCleaner::Base.new "mongoid"
|
cleaner = ::DatabaseCleaner::Base.new "mongoid"
|
||||||
cleaner.orm.should == :mongoid
|
cleaner.orm.should == :mongoid
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is autodetected if orm is not provided" do
|
it "is autodetected if orm is not provided" do
|
||||||
cleaner = ::DatabaseCleaner::Base.new
|
cleaner = ::DatabaseCleaner::Base.new
|
||||||
cleaner.should be_auto_detected
|
cleaner.should be_auto_detected
|
||||||
|
@ -317,7 +369,7 @@ module DatabaseCleaner
|
||||||
|
|
||||||
it "should attempt to set strategy db" do
|
it "should attempt to set strategy db" do
|
||||||
subject.stub(:db).and_return(:my_db)
|
subject.stub(:db).and_return(:my_db)
|
||||||
subject.should_receive(:strategy_db=).with(:my_db)
|
subject.should_receive(:set_strategy_db).with(mock_strategy, :my_db)
|
||||||
subject.strategy = mock_strategy
|
subject.strategy = mock_strategy
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -330,8 +382,7 @@ module DatabaseCleaner
|
||||||
describe "strategy" do
|
describe "strategy" do
|
||||||
subject { ::DatabaseCleaner::Base.new :a_orm }
|
subject { ::DatabaseCleaner::Base.new :a_orm }
|
||||||
|
|
||||||
it "returns a null strategy when strategy no set and undetectable" do
|
it "returns a null strategy when strategy is not set and undetectable" do
|
||||||
subject.instance_values["@strategy"] = nil
|
|
||||||
subject.strategy.should == DatabaseCleaner::NullStrategy
|
subject.strategy.should == DatabaseCleaner::NullStrategy
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -487,6 +538,21 @@ module DatabaseCleaner
|
||||||
cleaner = DatabaseCleaner::Base.new(:couch_potato)
|
cleaner = DatabaseCleaner::Base.new(:couch_potato)
|
||||||
cleaner.strategy.should be_instance_of DatabaseCleaner::CouchPotato::Truncation
|
cleaner.strategy.should be_instance_of DatabaseCleaner::CouchPotato::Truncation
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'sets strategy to :truncation for Moped' do
|
||||||
|
cleaner = DatabaseCleaner::Base.new(:moped)
|
||||||
|
cleaner.strategy.should be_instance_of DatabaseCleaner::Moped::Truncation
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets strategy to :truncation for Ohm' do
|
||||||
|
cleaner = DatabaseCleaner::Base.new(:ohm)
|
||||||
|
cleaner.strategy.should be_instance_of DatabaseCleaner::Ohm::Truncation
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets strategy to :truncation for Redis' do
|
||||||
|
cleaner = DatabaseCleaner::Base.new(:redis)
|
||||||
|
cleaner.strategy.should be_instance_of DatabaseCleaner::Redis::Truncation
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -55,6 +55,20 @@ describe ::DatabaseCleaner do
|
||||||
cleaner.orm.should == :couch_potato
|
cleaner.orm.should == :couch_potato
|
||||||
::DatabaseCleaner.connections.size.should == 1
|
::DatabaseCleaner.connections.size.should == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "should accept :moped" do
|
||||||
|
cleaner = ::DatabaseCleaner[:moped]
|
||||||
|
cleaner.should be_a(::DatabaseCleaner::Base)
|
||||||
|
cleaner.orm.should == :moped
|
||||||
|
::DatabaseCleaner.connections.size.should == 1
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'accepts :ohm' do
|
||||||
|
cleaner = ::DatabaseCleaner[:ohm]
|
||||||
|
cleaner.should be_a(::DatabaseCleaner::Base)
|
||||||
|
cleaner.orm.should == :ohm
|
||||||
|
::DatabaseCleaner.connections.size.should == 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should accept multiple orm's" do
|
it "should accept multiple orm's" do
|
||||||
|
@ -119,7 +133,7 @@ describe ::DatabaseCleaner do
|
||||||
it "should give me a default (autodetection) databasecleaner by default" do
|
it "should give me a default (autodetection) databasecleaner by default" do
|
||||||
cleaner = mock("cleaner").as_null_object
|
cleaner = mock("cleaner").as_null_object
|
||||||
::DatabaseCleaner::Base.stub!(:new).and_return(cleaner)
|
::DatabaseCleaner::Base.stub!(:new).and_return(cleaner)
|
||||||
|
|
||||||
::DatabaseCleaner.connections.should == [cleaner]
|
::DatabaseCleaner.connections.should == [cleaner]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
26
spec/database_cleaner/moped/moped_examples.rb
Normal file
26
spec/database_cleaner/moped/moped_examples.rb
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
module MopedTest
|
||||||
|
class ThingBase
|
||||||
|
def self.collection
|
||||||
|
@db ||= 'database_cleaner_specs'
|
||||||
|
@session ||= ::Moped::Session.new(['127.0.0.1:27017'], database: @db)
|
||||||
|
@collection ||= @session[name]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.count
|
||||||
|
@collection.find.count
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(attrs={})
|
||||||
|
@attrs = attrs
|
||||||
|
end
|
||||||
|
|
||||||
|
def save!
|
||||||
|
self.class.collection.insert(@attrs)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Widget < ThingBase
|
||||||
|
end
|
||||||
|
class Gadget < ThingBase
|
||||||
|
end
|
||||||
|
end
|
75
spec/database_cleaner/moped/truncation_spec.rb
Normal file
75
spec/database_cleaner/moped/truncation_spec.rb
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
require File.dirname(__FILE__) + '/../../spec_helper'
|
||||||
|
require 'moped'
|
||||||
|
require 'database_cleaner/moped/truncation'
|
||||||
|
require File.dirname(__FILE__) + '/moped_examples'
|
||||||
|
|
||||||
|
module DatabaseCleaner
|
||||||
|
module Moped
|
||||||
|
|
||||||
|
describe Truncation do
|
||||||
|
let(:args) {{}}
|
||||||
|
let(:truncation) { described_class.new(args).tap { |t| t.db=@db } }
|
||||||
|
#doing this in the file root breaks autospec, doing it before(:all) just fails the specs
|
||||||
|
before(:all) do
|
||||||
|
@test_db = 'database_cleaner_specs'
|
||||||
|
@session = ::Moped::Session.new(['127.0.0.1:27017'], database: @test_db)
|
||||||
|
end
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
truncation.db = @test_db
|
||||||
|
end
|
||||||
|
|
||||||
|
after(:each) do
|
||||||
|
@session.drop
|
||||||
|
end
|
||||||
|
|
||||||
|
def ensure_counts(expected_counts)
|
||||||
|
# I had to add this sanity_check garbage because I was getting non-determinisc results from mongo at times..
|
||||||
|
# very odd and disconcerting...
|
||||||
|
expected_counts.each do |model_class, expected_count|
|
||||||
|
model_class.count.should equal(expected_count), "#{model_class} expected to have a count of #{expected_count} but was #{model_class.count}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_widget(attrs={})
|
||||||
|
MopedTest::Widget.new({:name => 'some widget'}.merge(attrs)).save!
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_gadget(attrs={})
|
||||||
|
MopedTest::Gadget.new({:name => 'some gadget'}.merge(attrs)).save!
|
||||||
|
end
|
||||||
|
|
||||||
|
it "truncates all collections by default" do
|
||||||
|
create_widget
|
||||||
|
create_gadget
|
||||||
|
ensure_counts(MopedTest::Widget => 1, MopedTest::Gadget => 1)
|
||||||
|
truncation.clean
|
||||||
|
ensure_counts(MopedTest::Widget => 0, MopedTest::Gadget => 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when collections are provided to the :only option" do
|
||||||
|
let(:args) {{:only => ['MopedTest::Widget']}}
|
||||||
|
it "only truncates the specified collections" do
|
||||||
|
create_widget
|
||||||
|
create_gadget
|
||||||
|
ensure_counts(MopedTest::Widget => 1, MopedTest::Gadget => 1)
|
||||||
|
truncation.clean
|
||||||
|
ensure_counts(MopedTest::Widget => 0, MopedTest::Gadget => 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when collections are provided to the :except option" do
|
||||||
|
let(:args) {{:except => ['MopedTest::Widget']}}
|
||||||
|
it "truncates all but the specified collections" do
|
||||||
|
create_widget
|
||||||
|
create_gadget
|
||||||
|
ensure_counts(MopedTest::Widget => 1, MopedTest::Gadget => 1)
|
||||||
|
truncation.clean
|
||||||
|
ensure_counts(MopedTest::Widget => 1, MopedTest::Gadget => 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
70
spec/database_cleaner/ohm/truncation_spec.rb
Normal file
70
spec/database_cleaner/ohm/truncation_spec.rb
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
require File.dirname(__FILE__) + '/../../spec_helper'
|
||||||
|
require 'ohm'
|
||||||
|
require 'database_cleaner/ohm/truncation'
|
||||||
|
|
||||||
|
module DatabaseCleaner
|
||||||
|
module Ohm
|
||||||
|
|
||||||
|
class Widget < ::Ohm::Model
|
||||||
|
attribute :name
|
||||||
|
end
|
||||||
|
|
||||||
|
class Gadget < ::Ohm::Model
|
||||||
|
attribute :name
|
||||||
|
end
|
||||||
|
|
||||||
|
describe Truncation do
|
||||||
|
before(:all) do
|
||||||
|
config = YAML::load(File.open("#{File.dirname(__FILE__)}/../../../examples/config/redis.yml"))
|
||||||
|
::Ohm.connect :url => config['test']['url']
|
||||||
|
@redis = ::Ohm.redis
|
||||||
|
end
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
@redis.flushdb
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should flush the database" do
|
||||||
|
Truncation.new.clean
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_widget(attrs={})
|
||||||
|
Widget.new({:name => 'some widget'}.merge(attrs)).save
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_gadget(attrs={})
|
||||||
|
Gadget.new({:name => 'some gadget'}.merge(attrs)).save
|
||||||
|
end
|
||||||
|
|
||||||
|
it "truncates all keys by default" do
|
||||||
|
create_widget
|
||||||
|
create_gadget
|
||||||
|
@redis.keys.size.should == 6
|
||||||
|
Truncation.new.clean
|
||||||
|
@redis.keys.size.should == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when keys are provided to the :only option" do
|
||||||
|
it "only truncates the specified keys" do
|
||||||
|
create_widget
|
||||||
|
create_gadget
|
||||||
|
@redis.keys.size.should == 6
|
||||||
|
Truncation.new(:only => ['*Widget*']).clean
|
||||||
|
@redis.keys.size.should == 3
|
||||||
|
@redis.get('DatabaseCleaner::Ohm::Gadget:id').should == '1'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when keys are provided to the :except option" do
|
||||||
|
it "truncates all but the specified keys" do
|
||||||
|
create_widget
|
||||||
|
create_gadget
|
||||||
|
@redis.keys.size.should == 6
|
||||||
|
Truncation.new(:except => ['*Widget*']).clean
|
||||||
|
@redis.keys.size.should == 3
|
||||||
|
@redis.get('DatabaseCleaner::Ohm::Widget:id').should == '1'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
32
spec/database_cleaner/redis/base_spec.rb
Normal file
32
spec/database_cleaner/redis/base_spec.rb
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
require 'database_cleaner/redis/base'
|
||||||
|
require 'database_cleaner/shared_strategy'
|
||||||
|
|
||||||
|
module DatabaseCleaner
|
||||||
|
describe Redis do
|
||||||
|
it { should respond_to(:available_strategies) }
|
||||||
|
end
|
||||||
|
|
||||||
|
module Redis
|
||||||
|
class ExampleStrategy
|
||||||
|
include ::DatabaseCleaner::Redis::Base
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ExampleStrategy do
|
||||||
|
|
||||||
|
it_should_behave_like "a generic strategy"
|
||||||
|
it { should respond_to(:db) }
|
||||||
|
it { should respond_to(:db=) }
|
||||||
|
|
||||||
|
it "should store my describe db" do
|
||||||
|
url = 'redis://localhost:6379/2'
|
||||||
|
subject.db = 'redis://localhost:6379/2'
|
||||||
|
subject.db.should == url
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should default to :default" do
|
||||||
|
subject.db.should == :default
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
63
spec/database_cleaner/redis/truncation_spec.rb
Normal file
63
spec/database_cleaner/redis/truncation_spec.rb
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
require File.dirname(__FILE__) + '/../../spec_helper'
|
||||||
|
require 'redis'
|
||||||
|
require 'database_cleaner/redis/truncation'
|
||||||
|
|
||||||
|
|
||||||
|
module DatabaseCleaner
|
||||||
|
module Redis
|
||||||
|
|
||||||
|
describe Truncation do
|
||||||
|
before(:all) do
|
||||||
|
config = YAML::load(File.open("#{File.dirname(__FILE__)}/../../../examples/config/redis.yml"))
|
||||||
|
@redis = ::Redis.connect :url => config['test']['url']
|
||||||
|
end
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
@redis.flushdb
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should flush the database" do
|
||||||
|
Truncation.new.clean
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_widget(attrs={})
|
||||||
|
@redis.set 'Widget', 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_gadget(attrs={})
|
||||||
|
@redis.set 'Gadget', 1
|
||||||
|
end
|
||||||
|
|
||||||
|
it "truncates all keys by default" do
|
||||||
|
create_widget
|
||||||
|
create_gadget
|
||||||
|
@redis.keys.size.should == 2
|
||||||
|
Truncation.new.clean
|
||||||
|
@redis.keys.size.should == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when keys are provided to the :only option" do
|
||||||
|
it "only truncates the specified keys" do
|
||||||
|
create_widget
|
||||||
|
create_gadget
|
||||||
|
@redis.keys.size.should == 2
|
||||||
|
Truncation.new(:only => ['Widge*']).clean
|
||||||
|
@redis.keys.size.should == 1
|
||||||
|
@redis.get('Gadget').should == '1'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when keys are provided to the :except option" do
|
||||||
|
it "truncates all but the specified keys" do
|
||||||
|
create_widget
|
||||||
|
create_gadget
|
||||||
|
@redis.keys.size.should == 2
|
||||||
|
Truncation.new(:except => ['Widg*']).clean
|
||||||
|
@redis.keys.size.should == 1
|
||||||
|
@redis.get('Widget').should == '1'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue