database_cleaner 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.rdoc +12 -0
- data/README.markdown +24 -14
- data/Rakefile +1 -1
- data/VERSION.yml +1 -1
- data/lib/database_cleaner/active_record/deletion.rb +7 -1
- data/lib/database_cleaner/active_record/transaction.rb +2 -2
- data/lib/database_cleaner/active_record/truncation.rb +10 -4
- data/lib/database_cleaner/base.rb +4 -0
- data/lib/database_cleaner/configuration.rb +6 -0
- data/lib/database_cleaner/cucumber.rb +2 -10
- data/lib/database_cleaner/data_mapper/truncation.rb +13 -3
- data/lib/database_cleaner/generic/base.rb +6 -0
- data/lib/database_cleaner/sequel/transaction.rb +15 -0
- data/spec/database_cleaner/active_record/transaction_spec.rb +3 -3
- data/spec/database_cleaner/base_spec.rb +13 -0
- data/spec/database_cleaner/configuration_spec.rb +27 -0
- data/spec/database_cleaner/sequel/truncation/sqlite3_spec.rb +0 -0
- data/spec/database_cleaner/sequel/truncation_spec.rb +131 -0
- data/spec/database_cleaner/shared_strategy.rb +2 -0
- data/spec/support/active_record/database_setup.rb +2 -0
- metadata +344 -6
data/History.rdoc
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
== 1.3.0 2014-05-23
|
2
|
+
|
3
|
+
=== New Features/Changes
|
4
|
+
* Introduced `DatabaseCleaener::cleaninng` method that takes a block. (@ethco)
|
5
|
+
* Improved Sequel support and added more tests (@ethco, @rhunter)
|
6
|
+
|
7
|
+
=== Bug Fixes
|
8
|
+
|
9
|
+
* Fixed an issue with the `Transaction` strategy and Active Record where application-level transactions
|
10
|
+
are not rolledback correctly. (Godfrey Chan)
|
11
|
+
* activerecord-oracle_enhanced-adapter now works again (#259, @sockmonk)
|
12
|
+
|
1
13
|
== 1.2.0 2013-10-09
|
2
14
|
|
3
15
|
A huge thanks goes to @tommeier for fixing the bug with class loading that was cuasing the wrong adapters
|
data/README.markdown
CHANGED
@@ -146,7 +146,7 @@ passed to [`keys`](http://redis.io/commands/keys)).
|
|
146
146
|
|
147
147
|
(I should point out the truncation strategy will never truncate your schema_migrations table.)
|
148
148
|
|
149
|
-
Some strategies
|
149
|
+
Some strategies need to be started before tests are run (for example the `:transaction` strategy needs to know to open up a transaction). This can be accomplished by calling `DatabaseCleaner.start` at the beginning of the run, or by running the tests inside a block to `Database.cleaning`. So you would have:
|
150
150
|
|
151
151
|
```ruby
|
152
152
|
require 'database_cleaner'
|
@@ -158,6 +158,12 @@ DatabaseCleaner.start # usually this is called in setup of a test
|
|
158
158
|
dirty_the_db
|
159
159
|
|
160
160
|
DatabaseCleaner.clean # cleanup of the test
|
161
|
+
|
162
|
+
# OR
|
163
|
+
|
164
|
+
DatabaseCleaner.cleaning do
|
165
|
+
dirty_the_db
|
166
|
+
end
|
161
167
|
```
|
162
168
|
|
163
169
|
At times you may want to do a single clean with one strategy.
|
@@ -196,12 +202,10 @@ RSpec.configure do |config|
|
|
196
202
|
DatabaseCleaner.clean_with(:truncation)
|
197
203
|
end
|
198
204
|
|
199
|
-
config.
|
200
|
-
DatabaseCleaner.
|
201
|
-
|
202
|
-
|
203
|
-
config.after(:each) do
|
204
|
-
DatabaseCleaner.clean
|
205
|
+
config.around(:each) do |example|
|
206
|
+
DatabaseCleaner.cleaning do
|
207
|
+
example.run
|
208
|
+
end
|
205
209
|
end
|
206
210
|
|
207
211
|
end
|
@@ -221,6 +225,13 @@ class MiniTest::Spec
|
|
221
225
|
DatabaseCleaner.clean
|
222
226
|
end
|
223
227
|
end
|
228
|
+
|
229
|
+
# with the minitest-around gem, this may be used instead:
|
230
|
+
class Minitest::Spec
|
231
|
+
around do |tests|
|
232
|
+
DatabaseCleaner.cleaning(&tests)
|
233
|
+
end
|
234
|
+
end
|
224
235
|
```
|
225
236
|
|
226
237
|
### Cucumber Example
|
@@ -239,12 +250,8 @@ rescue NameError
|
|
239
250
|
raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
|
240
251
|
end
|
241
252
|
|
242
|
-
|
243
|
-
DatabaseCleaner.
|
244
|
-
end
|
245
|
-
|
246
|
-
After do |scenario|
|
247
|
-
DatabaseCleaner.clean
|
253
|
+
Around do |scenario, block|
|
254
|
+
DatabaseCleaner.cleaning(&block)
|
248
255
|
end
|
249
256
|
```
|
250
257
|
|
@@ -314,7 +321,7 @@ Usage beyond that remains the same with `DatabaseCleaner.start` calling any setu
|
|
314
321
|
<tr>
|
315
322
|
<td> Sequel</td>
|
316
323
|
<td> <code>DatabaseCleaner[:sequel]</code></td>
|
317
|
-
<td> Multiple databases supported; specify <code>
|
324
|
+
<td> Multiple databases supported; specify <code>DatabaseCleaner[:sequel, {:connection => Sequel.connect(uri)}]</code></td>
|
318
325
|
</tr>
|
319
326
|
<tr>
|
320
327
|
<td>Redis</td>
|
@@ -358,6 +365,9 @@ If you are using Postgres and have foreign key constraints, the truncation strat
|
|
358
365
|
client_min_messages = warning
|
359
366
|
```
|
360
367
|
|
368
|
+
### Nothing happens in JRuby with Sequel using transactions
|
369
|
+
|
370
|
+
Due to an inconsistency in JRuby's implementation of Fibers, Sequel gives a different connection to `DatabaseCleaner.start` than is used for tests run between `.start` and `.clean`. This can be worked around by running your tests in a block like `DatabaseCleaner.cleaning { run_my_tests }` instead, which does not use Fibers.
|
361
371
|
|
362
372
|
## Debugging
|
363
373
|
|
data/Rakefile
CHANGED
@@ -14,7 +14,7 @@ begin
|
|
14
14
|
s.description = "Strategies for cleaning databases. Can be used to ensure a clean state for testing."
|
15
15
|
s.files = FileList["[A-Z]*.*", "{examples,lib,features,spec}/**/*", "Rakefile", "cucumber.yml"]
|
16
16
|
s.authors = ["Ben Mabey"]
|
17
|
-
s.licence = 'MIT'
|
17
|
+
# s.licence = 'MIT'
|
18
18
|
end
|
19
19
|
rescue LoadError
|
20
20
|
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
data/VERSION.yml
CHANGED
@@ -17,6 +17,12 @@ module DatabaseCleaner
|
|
17
17
|
execute("DELETE FROM #{quote_table_name(table_name)};")
|
18
18
|
end
|
19
19
|
end
|
20
|
+
|
21
|
+
module OracleDeleteAdapter
|
22
|
+
def delete_table(table_name)
|
23
|
+
execute("DELETE FROM #{quote_table_name(table_name)}")
|
24
|
+
end
|
25
|
+
end
|
20
26
|
end
|
21
27
|
end
|
22
28
|
|
@@ -32,7 +38,7 @@ module ActiveRecord
|
|
32
38
|
PostgreSQLAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::GenericDeleteAdapter } if defined?(PostgreSQLAdapter)
|
33
39
|
IBM_DBAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::GenericDeleteAdapter } if defined?(IBM_DBAdapter)
|
34
40
|
SQLServerAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::GenericDeleteAdapter } if defined?(SQLServerAdapter)
|
35
|
-
OracleEnhancedAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::
|
41
|
+
OracleEnhancedAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::OracleDeleteAdapter } if defined?(OracleEnhancedAdapter)
|
36
42
|
end
|
37
43
|
end
|
38
44
|
|
@@ -19,7 +19,7 @@ module DatabaseCleaner::ActiveRecord
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
if connection_class.connection.respond_to?(:begin_transaction)
|
22
|
-
connection_class.connection.begin_transaction
|
22
|
+
connection_class.connection.begin_transaction joinable: false
|
23
23
|
else
|
24
24
|
connection_class.connection.begin_db_transaction
|
25
25
|
end
|
@@ -36,7 +36,7 @@ module DatabaseCleaner::ActiveRecord
|
|
36
36
|
end
|
37
37
|
|
38
38
|
# The below is for handling after_commit hooks.. see https://github.com/bmabey/database_cleaner/issues/99
|
39
|
-
if connection_class.connection.respond_to?(:rollback_transaction_records)
|
39
|
+
if connection_class.connection.respond_to?(:rollback_transaction_records, true)
|
40
40
|
connection_class.connection.send(:rollback_transaction_records, true)
|
41
41
|
end
|
42
42
|
|
@@ -114,13 +114,13 @@ module DatabaseCleaner
|
|
114
114
|
def truncate_table(table_name)
|
115
115
|
begin
|
116
116
|
execute("TRUNCATE TABLE #{quote_table_name(table_name)};")
|
117
|
-
rescue ActiveRecord::StatementInvalid
|
117
|
+
rescue ::ActiveRecord::StatementInvalid
|
118
118
|
execute("DELETE FROM #{quote_table_name(table_name)};")
|
119
119
|
end
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
123
|
-
module
|
123
|
+
module OracleAdapter
|
124
124
|
def truncate_table(table_name)
|
125
125
|
execute("TRUNCATE TABLE #{quote_table_name(table_name)}")
|
126
126
|
end
|
@@ -176,7 +176,13 @@ module ActiveRecord
|
|
176
176
|
#Apply adapter decoraters where applicable (adapter should be loaded)
|
177
177
|
AbstractAdapter.class_eval { include DatabaseCleaner::ConnectionAdapters::AbstractAdapter }
|
178
178
|
|
179
|
-
|
179
|
+
if defined?(JdbcAdapter)
|
180
|
+
if defined?(OracleJdbcConnection)
|
181
|
+
JdbcAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::OracleAdapter }
|
182
|
+
else
|
183
|
+
JdbcAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::TruncateOrDelete }
|
184
|
+
end
|
185
|
+
end
|
180
186
|
AbstractMysqlAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::AbstractMysqlAdapter } if defined?(AbstractMysqlAdapter)
|
181
187
|
Mysql2Adapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::AbstractMysqlAdapter } if defined?(Mysql2Adapter)
|
182
188
|
SQLiteAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::SQLiteAdapter } if defined?(SQLiteAdapter)
|
@@ -184,7 +190,7 @@ module ActiveRecord
|
|
184
190
|
PostgreSQLAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::PostgreSQLAdapter } if defined?(PostgreSQLAdapter)
|
185
191
|
IBM_DBAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::IBM_DBAdapter } if defined?(IBM_DBAdapter)
|
186
192
|
SQLServerAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::TruncateOrDelete } if defined?(SQLServerAdapter)
|
187
|
-
OracleEnhancedAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::
|
193
|
+
OracleEnhancedAdapter.class_eval { include ::DatabaseCleaner::ConnectionAdapters::OracleAdapter } if defined?(OracleEnhancedAdapter)
|
188
194
|
end
|
189
195
|
end
|
190
196
|
|
@@ -81,6 +81,12 @@ module DatabaseCleaner
|
|
81
81
|
|
82
82
|
alias clean! clean
|
83
83
|
|
84
|
+
def cleaning(&inner_block)
|
85
|
+
connections.inject(inner_block) do |curr_block, connection|
|
86
|
+
proc { connection.cleaning(&curr_block) }
|
87
|
+
end.call
|
88
|
+
end
|
89
|
+
|
84
90
|
def clean_with(*args)
|
85
91
|
connections.each { |connection| connection.clean_with(*args) }
|
86
92
|
end
|
@@ -1,11 +1,3 @@
|
|
1
|
-
|
2
|
-
DatabaseCleaner.
|
3
|
-
end
|
4
|
-
|
5
|
-
After do
|
6
|
-
begin
|
7
|
-
DatabaseCleaner.clean
|
8
|
-
rescue Exception => e
|
9
|
-
DatabaseCleaner.logger.error "Exception encountered by DatabaseCleaner in Cucumber After block: #{e}"
|
10
|
-
end
|
1
|
+
Around do |scenario, block|
|
2
|
+
DatabaseCleaner.cleaning(&block)
|
11
3
|
end
|
@@ -10,6 +10,12 @@ module DataMapper
|
|
10
10
|
raise NotImplementedError
|
11
11
|
end
|
12
12
|
|
13
|
+
def truncate_tables(table_names)
|
14
|
+
table_names.each do |table_name|
|
15
|
+
adapter.truncate_table table_name
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
13
19
|
end
|
14
20
|
|
15
21
|
class MysqlAdapter < DataObjectsAdapter
|
@@ -136,6 +142,12 @@ module DataMapper
|
|
136
142
|
execute("TRUNCATE TABLE #{quote_name(table_name)} RESTART IDENTITY CASCADE;")
|
137
143
|
end
|
138
144
|
|
145
|
+
# override to use a single statement
|
146
|
+
def truncate_tables(table_names)
|
147
|
+
quoted_names = table_names.collect { |n| quote_name(n) }.join(', ')
|
148
|
+
execute("TRUNCATE TABLE #{quoted_names} RESTART IDENTITY;")
|
149
|
+
end
|
150
|
+
|
139
151
|
# FIXME
|
140
152
|
# copied from activerecord
|
141
153
|
def supports_disable_referential_integrity?
|
@@ -177,9 +189,7 @@ module DatabaseCleaner
|
|
177
189
|
def clean(repository = self.db)
|
178
190
|
adapter = ::DataMapper.repository(repository).adapter
|
179
191
|
adapter.disable_referential_integrity do
|
180
|
-
tables_to_truncate(repository)
|
181
|
-
adapter.truncate_table table_name
|
182
|
-
end
|
192
|
+
adapter.truncate_tables(tables_to_truncate(repository))
|
183
193
|
end
|
184
194
|
end
|
185
195
|
|
@@ -4,7 +4,18 @@ module DatabaseCleaner
|
|
4
4
|
class Transaction
|
5
5
|
include ::DatabaseCleaner::Sequel::Base
|
6
6
|
|
7
|
+
def self.check_fiber_brokenness
|
8
|
+
if !@checked_fiber_brokenness && Fiber.new { Thread.current }.resume != Thread.current
|
9
|
+
raise RuntimeError, "This ruby engine's Fibers are not compatible with Sequel's connection pool. " +
|
10
|
+
"To work around this, please use DatabaseCleaner.cleaning with a block instead of " +
|
11
|
+
"DatabaseCleaner.start and DatabaseCleaner.clean"
|
12
|
+
end
|
13
|
+
@checked_fiber_brokenness = true
|
14
|
+
end
|
15
|
+
|
7
16
|
def start
|
17
|
+
self.class.check_fiber_brokenness
|
18
|
+
|
8
19
|
@fibers||= []
|
9
20
|
db= self.db
|
10
21
|
f= Fiber.new do
|
@@ -20,6 +31,10 @@ module DatabaseCleaner
|
|
20
31
|
f= @fibers.pop
|
21
32
|
f.resume
|
22
33
|
end
|
34
|
+
|
35
|
+
def cleaning
|
36
|
+
self.db.transaction(:rollback => :always, :savepoint => true) { yield }
|
37
|
+
end
|
23
38
|
end
|
24
39
|
end
|
25
40
|
end
|
@@ -58,7 +58,7 @@ module DatabaseCleaner
|
|
58
58
|
connection.should_receive(:open_transactions).and_return(1)
|
59
59
|
|
60
60
|
connection.stub(:respond_to?).with(:decrement_open_transactions).and_return(true)
|
61
|
-
connection.stub(:respond_to?).with(:rollback_transaction_records).and_return(false)
|
61
|
+
connection.stub(:respond_to?).with(:rollback_transaction_records, true).and_return(false)
|
62
62
|
connection.stub(:respond_to?).with(:rollback_transaction).and_return(false)
|
63
63
|
connection.stub(:rollback_db_transaction)
|
64
64
|
|
@@ -75,7 +75,7 @@ module DatabaseCleaner
|
|
75
75
|
it "should decrement connection via ActiveRecord::Base if connection won't" do
|
76
76
|
connection.should_receive(:open_transactions).and_return(1)
|
77
77
|
connection.stub(:respond_to?).with(:decrement_open_transactions).and_return(false)
|
78
|
-
connection.stub(:respond_to?).with(:rollback_transaction_records).and_return(false)
|
78
|
+
connection.stub(:respond_to?).with(:rollback_transaction_records, true).and_return(false)
|
79
79
|
connection.stub(:respond_to?).with(:rollback_transaction).and_return(false)
|
80
80
|
connection.stub(:rollback_db_transaction)
|
81
81
|
|
@@ -112,7 +112,7 @@ module DatabaseCleaner
|
|
112
112
|
|
113
113
|
it "should decrement connection via ActiveRecord::Base if connection won't" do
|
114
114
|
connection.should_receive(:open_transactions).and_return(1)
|
115
|
-
connection.stub(:respond_to?).with(:rollback_transaction_records).and_return(false)
|
115
|
+
connection.stub(:respond_to?).with(:rollback_transaction_records, true).and_return(false)
|
116
116
|
connection.stub(:respond_to?).with(:rollback_transaction).and_return(true)
|
117
117
|
connection.stub(:rollback_transaction)
|
118
118
|
|
@@ -42,6 +42,7 @@ module DatabaseCleaner
|
|
42
42
|
::MongoMapper = Temp_MM if defined? Temp_MM
|
43
43
|
::Mongoid = Temp_MO if defined? Temp_MO
|
44
44
|
::CouchPotato = Temp_CP if defined? Temp_CP
|
45
|
+
::Sequel = Temp_SQ if defined? Temp_SQ
|
45
46
|
::Moped = Temp_MP if defined? Temp_MP
|
46
47
|
::Ohm = Temp_OH if defined? Temp_OH
|
47
48
|
::Redis = Temp_RS if defined? Temp_RS
|
@@ -451,6 +452,13 @@ module DatabaseCleaner
|
|
451
452
|
subject.clean!
|
452
453
|
end
|
453
454
|
end
|
455
|
+
|
456
|
+
describe "cleaning" do
|
457
|
+
it "should proxy cleaning to the strategy" do
|
458
|
+
strategy.should_receive(:cleaning)
|
459
|
+
subject.cleaning { }
|
460
|
+
end
|
461
|
+
end
|
454
462
|
end
|
455
463
|
|
456
464
|
describe "auto_detected?" do
|
@@ -535,6 +543,11 @@ module DatabaseCleaner
|
|
535
543
|
cleaner.strategy.should be_instance_of DatabaseCleaner::CouchPotato::Truncation
|
536
544
|
end
|
537
545
|
|
546
|
+
it 'sets strategy to :transaction for Sequel' do
|
547
|
+
cleaner = DatabaseCleaner::Base.new(:sequel)
|
548
|
+
cleaner.strategy.should be_instance_of DatabaseCleaner::Sequel::Transaction
|
549
|
+
end
|
550
|
+
|
538
551
|
it 'sets strategy to :truncation for Moped' do
|
539
552
|
cleaner = DatabaseCleaner::Base.new(:moped)
|
540
553
|
cleaner.strategy.should be_instance_of DatabaseCleaner::Moped::Truncation
|
@@ -163,6 +163,11 @@ describe ::DatabaseCleaner do
|
|
163
163
|
::DatabaseCleaner.clean
|
164
164
|
end
|
165
165
|
|
166
|
+
it 'should proxy cleaning' do
|
167
|
+
connection.should_receive(:cleaning)
|
168
|
+
::DatabaseCleaner.cleaning { }
|
169
|
+
end
|
170
|
+
|
166
171
|
it "should proxy clean_with" do
|
167
172
|
stratagem = double("stratgem")
|
168
173
|
connection.should_receive(:clean_with).with(stratagem, {})
|
@@ -203,6 +208,28 @@ describe ::DatabaseCleaner do
|
|
203
208
|
::DatabaseCleaner.clean
|
204
209
|
end
|
205
210
|
|
211
|
+
it "should initiate cleaning on each connection, yield, and finish cleaning each connection" do
|
212
|
+
[active_record, data_mapper].each do |connection|
|
213
|
+
mc = class << connection; self; end
|
214
|
+
mc.send(:attr_reader, :started, :cleaned)
|
215
|
+
mc.send(:define_method, 'cleaning') do |&block|
|
216
|
+
@started = true
|
217
|
+
block.call
|
218
|
+
@cleaned = true
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
::DatabaseCleaner.cleaning do
|
223
|
+
active_record.started.should == true
|
224
|
+
data_mapper.started.should == true
|
225
|
+
active_record.cleaned.should == nil
|
226
|
+
data_mapper.cleaned.should == nil
|
227
|
+
@yielded = true
|
228
|
+
end
|
229
|
+
active_record.cleaned.should == true
|
230
|
+
data_mapper.cleaned.should == true
|
231
|
+
end
|
232
|
+
|
206
233
|
it "should proxy clean_with to all connections" do
|
207
234
|
stratagem = double("stratgem")
|
208
235
|
active_record.should_receive(:clean_with).with(stratagem)
|
File without changes
|
@@ -3,11 +3,142 @@ require 'database_cleaner/sequel/truncation'
|
|
3
3
|
require 'database_cleaner/shared_strategy'
|
4
4
|
require 'sequel'
|
5
5
|
|
6
|
+
# XXX: use ActiveRecord's db_config (`db/config.yml`) for CI/dev convenience
|
7
|
+
require 'support/active_record/database_setup'
|
8
|
+
|
6
9
|
module DatabaseCleaner
|
7
10
|
module Sequel
|
8
11
|
describe Truncation do
|
9
12
|
it_should_behave_like "a generic strategy"
|
10
13
|
it_should_behave_like "a generic truncation strategy"
|
11
14
|
end
|
15
|
+
|
16
|
+
shared_examples 'a Sequel truncation strategy' do
|
17
|
+
|
18
|
+
# XXX: it'd be really nice if Truncation accepted db: constructor parameter
|
19
|
+
let(:truncation) do
|
20
|
+
t = Truncation.new
|
21
|
+
t.db = db
|
22
|
+
t
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when several tables have data' do
|
26
|
+
before(:each) do
|
27
|
+
db.create_table!(:precious_stones) { primary_key :id }
|
28
|
+
db.create_table!(:replaceable_trifles) { primary_key :id }
|
29
|
+
db.create_table!(:worthless_junk) { primary_key :id }
|
30
|
+
|
31
|
+
db[:precious_stones].insert
|
32
|
+
db[:replaceable_trifles].insert
|
33
|
+
db[:worthless_junk].insert
|
34
|
+
end
|
35
|
+
context 'by default' do
|
36
|
+
it 'truncates all the tables' do
|
37
|
+
t = Truncation.new
|
38
|
+
t.db = db
|
39
|
+
t.clean
|
40
|
+
|
41
|
+
expect(db[:replaceable_trifles]).to have(0).rows
|
42
|
+
expect(db[:worthless_junk]).to have(0).rows
|
43
|
+
expect(db[:precious_stones]).to have(0).rows
|
44
|
+
end
|
45
|
+
end
|
46
|
+
context 'when the Truncation is restricted to "only: [...]" some tables' do
|
47
|
+
it 'truncates only the mentioned tables (and leaves the rest alone)' do
|
48
|
+
t = Truncation.new(only: ['worthless_junk', 'replaceable_trifles'])
|
49
|
+
t.db = db
|
50
|
+
t.clean
|
51
|
+
|
52
|
+
expect(db[:replaceable_trifles]).to have(0).rows
|
53
|
+
expect(db[:worthless_junk]).to have(0).rows
|
54
|
+
expect(db[:precious_stones]).to have(1).rows
|
55
|
+
end
|
56
|
+
end
|
57
|
+
context 'when the Truncation is restricted to "except: [...]" some tables' do
|
58
|
+
it 'leaves the mentioned tables alone (and truncates the rest)' do
|
59
|
+
t = Truncation.new(except: ['precious_stones']) # XXX: Strings only, symbols are ignored
|
60
|
+
t.db = db
|
61
|
+
t.clean
|
62
|
+
|
63
|
+
expect(db[:replaceable_trifles]).to be_empty
|
64
|
+
expect(db[:worthless_junk]).to be_empty
|
65
|
+
expect(db[:precious_stones]).to have(1).item
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
shared_examples_for 'a truncation strategy without autoincrement resets' do
|
72
|
+
it "leaves AUTO_INCREMENT index alone by default (BUG: it should be reset instead)" do
|
73
|
+
# Jordan Hollinger made everything reset auto increment IDs
|
74
|
+
# in commit 6a0104382647e5c06578aeac586c0333c8944492 so I'm pretty sure
|
75
|
+
# everything is meant to reset by default.
|
76
|
+
#
|
77
|
+
# For Postgres, db[:mytable].truncate(restart: true) should work.
|
78
|
+
# For SQLite, db[:sqlite_sequence].where(name: 'mytable').delete
|
79
|
+
|
80
|
+
db.create_table!(:replaceable_trifles) { primary_key :id }
|
81
|
+
table = db[:replaceable_trifles]
|
82
|
+
2.times { table.insert }
|
83
|
+
|
84
|
+
truncation.clean
|
85
|
+
|
86
|
+
id_after_clean = table.insert
|
87
|
+
pending('the bug being fixed') do
|
88
|
+
expect(id_after_clean).to eq 1
|
89
|
+
end
|
90
|
+
end
|
91
|
+
# XXX: it'd be really nice if Truncation accepted db: constructor parameter
|
92
|
+
let(:truncation) do
|
93
|
+
t = Truncation.new
|
94
|
+
t.db = db
|
95
|
+
t
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
shared_examples_for 'a truncation strategy that resets autoincrement keys by default' do
|
100
|
+
it "resets AUTO_INCREMENT primary keys" do
|
101
|
+
db.create_table!(:replaceable_trifles) { primary_key :id }
|
102
|
+
table = db[:replaceable_trifles]
|
103
|
+
2.times { table.insert }
|
104
|
+
|
105
|
+
truncation.clean
|
106
|
+
|
107
|
+
id_after_clean = table.insert
|
108
|
+
expect(id_after_clean).to eq 1
|
109
|
+
end
|
110
|
+
|
111
|
+
# XXX: it'd be really nice if Truncation accepted db: constructor parameter
|
112
|
+
let(:truncation) do
|
113
|
+
t = Truncation.new
|
114
|
+
t.db = db
|
115
|
+
t
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
half_supported_configurations = [
|
120
|
+
{url: 'sqlite:///', connection_options: db_config['sqlite3']},
|
121
|
+
{url: 'postgres:///', connection_options: db_config['postgres']},
|
122
|
+
]
|
123
|
+
supported_configurations = [
|
124
|
+
{url: 'mysql:///', connection_options: db_config['mysql']},
|
125
|
+
{url: 'mysql2:///', connection_options: db_config['mysql2']}
|
126
|
+
]
|
127
|
+
supported_configurations.each do |config|
|
128
|
+
describe "Sequel truncation (using a #{config[:url]} connection)" do
|
129
|
+
let(:db) { ::Sequel.connect(config[:url], config[:connection_options]) }
|
130
|
+
|
131
|
+
it_behaves_like 'a Sequel truncation strategy'
|
132
|
+
it_behaves_like 'a truncation strategy that resets autoincrement keys by default'
|
133
|
+
end
|
134
|
+
end
|
135
|
+
half_supported_configurations.each do |config|
|
136
|
+
describe "Sequel truncation (using a #{config[:url]} connection)" do
|
137
|
+
let(:db) { ::Sequel.connect(config[:url], config[:connection_options]) }
|
138
|
+
|
139
|
+
it_behaves_like 'a Sequel truncation strategy'
|
140
|
+
it_behaves_like 'a truncation strategy without autoincrement resets'
|
141
|
+
end
|
142
|
+
end
|
12
143
|
end
|
13
144
|
end
|
@@ -5,9 +5,11 @@ end
|
|
5
5
|
shared_examples_for "a generic truncation strategy" do
|
6
6
|
it { should respond_to(:start) }
|
7
7
|
it { should respond_to(:clean) }
|
8
|
+
it { should respond_to(:cleaning) }
|
8
9
|
end
|
9
10
|
|
10
11
|
shared_examples_for "a generic transaction strategy" do
|
11
12
|
it { should respond_to(:start) }
|
12
13
|
it { should respond_to(:clean) }
|
14
|
+
it { should respond_to(:cleaning) }
|
13
15
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: database_cleaner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,344 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
dependencies:
|
12
|
+
date: 2014-05-24 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: jeweler
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: json_pure
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: activerecord
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: datamapper
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: dm-migrations
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: dm-sqlite-adapter
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: mongoid
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
type: :development
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: tzinfo
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ! '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
- !ruby/object:Gem::Dependency
|
175
|
+
name: mongo_ext
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
177
|
+
none: false
|
178
|
+
requirements:
|
179
|
+
- - ! '>='
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
type: :development
|
183
|
+
prerelease: false
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
186
|
+
requirements:
|
187
|
+
- - ! '>='
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
190
|
+
- !ruby/object:Gem::Dependency
|
191
|
+
name: bson_ext
|
192
|
+
requirement: !ruby/object:Gem::Requirement
|
193
|
+
none: false
|
194
|
+
requirements:
|
195
|
+
- - ! '>='
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '0'
|
198
|
+
type: :development
|
199
|
+
prerelease: false
|
200
|
+
version_requirements: !ruby/object:Gem::Requirement
|
201
|
+
none: false
|
202
|
+
requirements:
|
203
|
+
- - ! '>='
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: '0'
|
206
|
+
- !ruby/object:Gem::Dependency
|
207
|
+
name: mongo_mapper
|
208
|
+
requirement: !ruby/object:Gem::Requirement
|
209
|
+
none: false
|
210
|
+
requirements:
|
211
|
+
- - ! '>='
|
212
|
+
- !ruby/object:Gem::Version
|
213
|
+
version: '0'
|
214
|
+
type: :development
|
215
|
+
prerelease: false
|
216
|
+
version_requirements: !ruby/object:Gem::Requirement
|
217
|
+
none: false
|
218
|
+
requirements:
|
219
|
+
- - ! '>='
|
220
|
+
- !ruby/object:Gem::Version
|
221
|
+
version: '0'
|
222
|
+
- !ruby/object:Gem::Dependency
|
223
|
+
name: couch_potato
|
224
|
+
requirement: !ruby/object:Gem::Requirement
|
225
|
+
none: false
|
226
|
+
requirements:
|
227
|
+
- - ! '>='
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
230
|
+
type: :development
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
none: false
|
234
|
+
requirements:
|
235
|
+
- - ! '>='
|
236
|
+
- !ruby/object:Gem::Version
|
237
|
+
version: '0'
|
238
|
+
- !ruby/object:Gem::Dependency
|
239
|
+
name: sequel
|
240
|
+
requirement: !ruby/object:Gem::Requirement
|
241
|
+
none: false
|
242
|
+
requirements:
|
243
|
+
- - ~>
|
244
|
+
- !ruby/object:Gem::Version
|
245
|
+
version: 3.21.0
|
246
|
+
type: :development
|
247
|
+
prerelease: false
|
248
|
+
version_requirements: !ruby/object:Gem::Requirement
|
249
|
+
none: false
|
250
|
+
requirements:
|
251
|
+
- - ~>
|
252
|
+
- !ruby/object:Gem::Version
|
253
|
+
version: 3.21.0
|
254
|
+
- !ruby/object:Gem::Dependency
|
255
|
+
name: mysql
|
256
|
+
requirement: !ruby/object:Gem::Requirement
|
257
|
+
none: false
|
258
|
+
requirements:
|
259
|
+
- - ~>
|
260
|
+
- !ruby/object:Gem::Version
|
261
|
+
version: 2.8.1
|
262
|
+
type: :development
|
263
|
+
prerelease: false
|
264
|
+
version_requirements: !ruby/object:Gem::Requirement
|
265
|
+
none: false
|
266
|
+
requirements:
|
267
|
+
- - ~>
|
268
|
+
- !ruby/object:Gem::Version
|
269
|
+
version: 2.8.1
|
270
|
+
- !ruby/object:Gem::Dependency
|
271
|
+
name: mysql2
|
272
|
+
requirement: !ruby/object:Gem::Requirement
|
273
|
+
none: false
|
274
|
+
requirements:
|
275
|
+
- - ! '>='
|
276
|
+
- !ruby/object:Gem::Version
|
277
|
+
version: '0'
|
278
|
+
type: :development
|
279
|
+
prerelease: false
|
280
|
+
version_requirements: !ruby/object:Gem::Requirement
|
281
|
+
none: false
|
282
|
+
requirements:
|
283
|
+
- - ! '>='
|
284
|
+
- !ruby/object:Gem::Version
|
285
|
+
version: '0'
|
286
|
+
- !ruby/object:Gem::Dependency
|
287
|
+
name: pg
|
288
|
+
requirement: !ruby/object:Gem::Requirement
|
289
|
+
none: false
|
290
|
+
requirements:
|
291
|
+
- - ! '>='
|
292
|
+
- !ruby/object:Gem::Version
|
293
|
+
version: '0'
|
294
|
+
type: :development
|
295
|
+
prerelease: false
|
296
|
+
version_requirements: !ruby/object:Gem::Requirement
|
297
|
+
none: false
|
298
|
+
requirements:
|
299
|
+
- - ! '>='
|
300
|
+
- !ruby/object:Gem::Version
|
301
|
+
version: '0'
|
302
|
+
- !ruby/object:Gem::Dependency
|
303
|
+
name: sqlite3
|
304
|
+
requirement: !ruby/object:Gem::Requirement
|
305
|
+
none: false
|
306
|
+
requirements:
|
307
|
+
- - ! '>='
|
308
|
+
- !ruby/object:Gem::Version
|
309
|
+
version: '0'
|
310
|
+
type: :development
|
311
|
+
prerelease: false
|
312
|
+
version_requirements: !ruby/object:Gem::Requirement
|
313
|
+
none: false
|
314
|
+
requirements:
|
315
|
+
- - ! '>='
|
316
|
+
- !ruby/object:Gem::Version
|
317
|
+
version: '0'
|
318
|
+
- !ruby/object:Gem::Dependency
|
319
|
+
name: ohm
|
320
|
+
requirement: !ruby/object:Gem::Requirement
|
321
|
+
none: false
|
322
|
+
requirements:
|
323
|
+
- - ~>
|
324
|
+
- !ruby/object:Gem::Version
|
325
|
+
version: 0.1.3
|
326
|
+
type: :development
|
327
|
+
prerelease: false
|
328
|
+
version_requirements: !ruby/object:Gem::Requirement
|
329
|
+
none: false
|
330
|
+
requirements:
|
331
|
+
- - ~>
|
332
|
+
- !ruby/object:Gem::Version
|
333
|
+
version: 0.1.3
|
334
|
+
- !ruby/object:Gem::Dependency
|
335
|
+
name: guard-rspec
|
336
|
+
requirement: !ruby/object:Gem::Requirement
|
337
|
+
none: false
|
338
|
+
requirements:
|
339
|
+
- - ! '>='
|
340
|
+
- !ruby/object:Gem::Version
|
341
|
+
version: '0'
|
342
|
+
type: :development
|
343
|
+
prerelease: false
|
344
|
+
version_requirements: !ruby/object:Gem::Requirement
|
345
|
+
none: false
|
346
|
+
requirements:
|
347
|
+
- - ! '>='
|
348
|
+
- !ruby/object:Gem::Version
|
349
|
+
version: '0'
|
14
350
|
description: Strategies for cleaning databases. Can be used to ensure a clean state
|
15
351
|
for testing.
|
16
352
|
email: ben@benmabey.com
|
@@ -119,6 +455,7 @@ files:
|
|
119
455
|
- spec/database_cleaner/redis/truncation_spec.rb
|
120
456
|
- spec/database_cleaner/sequel/base_spec.rb
|
121
457
|
- spec/database_cleaner/sequel/transaction_spec.rb
|
458
|
+
- spec/database_cleaner/sequel/truncation/sqlite3_spec.rb
|
122
459
|
- spec/database_cleaner/sequel/truncation_spec.rb
|
123
460
|
- spec/database_cleaner/shared_strategy.rb
|
124
461
|
- spec/rcov.opts
|
@@ -132,8 +469,7 @@ files:
|
|
132
469
|
- LICENSE
|
133
470
|
- TODO
|
134
471
|
homepage: http://github.com/bmabey/database_cleaner
|
135
|
-
licenses:
|
136
|
-
- MIT
|
472
|
+
licenses: []
|
137
473
|
post_install_message:
|
138
474
|
rdoc_options: []
|
139
475
|
require_paths:
|
@@ -144,6 +480,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
144
480
|
- - ! '>='
|
145
481
|
- !ruby/object:Gem::Version
|
146
482
|
version: '0'
|
483
|
+
segments:
|
484
|
+
- 0
|
485
|
+
hash: 2066839847000143499
|
147
486
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
487
|
none: false
|
149
488
|
requirements:
|
@@ -158,4 +497,3 @@ specification_version: 3
|
|
158
497
|
summary: Strategies for cleaning databases. Can be used to ensure a clean state for
|
159
498
|
testing.
|
160
499
|
test_files: []
|
161
|
-
has_rdoc:
|