database_cleaner 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +15 -0
- data/README.textile +42 -9
- data/VERSION.yml +1 -1
- data/lib/database_cleaner/active_record/base.rb +1 -1
- data/lib/database_cleaner/active_record/deletion.rb +4 -2
- data/lib/database_cleaner/active_record/transaction.rb +2 -0
- data/lib/database_cleaner/active_record/truncation.rb +14 -3
- data/lib/database_cleaner/base.rb +1 -1
- data/lib/database_cleaner/configuration.rb +1 -1
- data/lib/database_cleaner/data_mapper/transaction.rb +3 -5
- data/lib/database_cleaner/data_mapper/truncation.rb +5 -5
- data/lib/database_cleaner/generic/truncation.rb +25 -31
- data/spec/database_cleaner/active_record/base_spec.rb +9 -6
- data/spec/database_cleaner/active_record/transaction_spec.rb +12 -0
- data/spec/database_cleaner/sequel/base_spec.rb +1 -0
- metadata +4 -4
data/History.txt
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
== 0.7.x (in git)
|
2
2
|
|
3
|
+
== 0.7.1 2012-01-15
|
4
|
+
|
5
|
+
=== New Features
|
6
|
+
|
7
|
+
* Support for Rails 3.2. (David Demaree)
|
8
|
+
|
9
|
+
=== Bugfixes
|
10
|
+
|
11
|
+
* Truncation resets the id count on SQLite. (Jordan Hollinger)
|
12
|
+
* AR delete strategy now disables referential integrity. (Ben Mabey)
|
13
|
+
* Fixes Postgres adapter for JRuby. (Dmytrii Nagirniak, Uģis Ozols)
|
14
|
+
* Documenation fixes. (Josh Rendek, Joshua Flanagan)
|
15
|
+
* Fixes bad error message when no database is specified for AR. (issue #72, Ben Mabey)
|
16
|
+
|
17
|
+
|
3
18
|
== 0.7.0 2011-11-12
|
4
19
|
|
5
20
|
=== New Features
|
data/README.textile
CHANGED
@@ -5,7 +5,7 @@ The original use case was to ensure a clean state during tests. Each strategy
|
|
5
5
|
is a small amount of code but is code that is usually needed in any ruby app
|
6
6
|
that is testing with a database.
|
7
7
|
|
8
|
-
ActiveRecord, DataMapper, MongoMapper, Mongoid, and CouchPotato are supported.
|
8
|
+
ActiveRecord, DataMapper, Sequel, MongoMapper, Mongoid, and CouchPotato are supported.
|
9
9
|
|
10
10
|
Here is an overview of the strategies supported for each library:
|
11
11
|
|
@@ -14,15 +14,16 @@ Here is an overview of the strategies supported for each library:
|
|
14
14
|
| DataMapper | Yes | **Yes** | No |
|
15
15
|
| CouchPotato | **Yes** | No | No |
|
16
16
|
| MongoMapper | **Yes** | No | No |
|
17
|
-
|
|
17
|
+
| Sequel | **Yes** | Yes | No |
|
18
18
|
|
19
19
|
(Default strategy for each library is denoted in bold)
|
20
20
|
|
21
|
-
The ActiveRecord @:deletion@ strategy is
|
22
|
-
locks (as reported by some Oracle DB users). The @:
|
23
|
-
|
21
|
+
The ActiveRecord @:deletion@ strategy is useful for when the @:truncation@ strategy causes
|
22
|
+
locks (as reported by some Oracle DB users). The @:deletion@ option has been reported to
|
23
|
+
be faster than @:truncation@ in some cases as well. In general, the best approach is to use
|
24
|
+
@:transaction@ since it is the fastest.
|
24
25
|
|
25
|
-
Database Cleaner also includes a @null@ strategy (that does no cleaning at all) which can be used
|
26
|
+
Database Cleaner also includes a @null@ strategy (that does no cleaning at all) which can be used
|
26
27
|
with any ORM library. You can also explicitly use it by setting your strategy to @nil@.
|
27
28
|
|
28
29
|
h2. How to use
|
@@ -70,7 +71,7 @@ strategy the remaining time. To accomplish this you can say:
|
|
70
71
|
# then make the DatabaseCleaner.start and DatabaseCleaner.clean calls appropriately
|
71
72
|
</pre>
|
72
73
|
|
73
|
-
|
74
|
+
h3. RSpec Example
|
74
75
|
|
75
76
|
<pre>
|
76
77
|
RSpec.configure do |config|
|
@@ -91,7 +92,38 @@ RSpec.configure do |config|
|
|
91
92
|
end
|
92
93
|
</pre>
|
93
94
|
|
94
|
-
|
95
|
+
h3. Cucumber Example
|
96
|
+
|
97
|
+
Add this to your features/support/env.rb file:
|
98
|
+
|
99
|
+
<pre>
|
100
|
+
begin
|
101
|
+
require 'database_cleaner'
|
102
|
+
require 'database_cleaner/cucumber'
|
103
|
+
DatabaseCleaner.strategy = :truncation
|
104
|
+
rescue NameError
|
105
|
+
raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
|
106
|
+
end
|
107
|
+
</pre>
|
108
|
+
|
109
|
+
A good idea is to create the before and after hooks to use the DatabaseCleaner.start and DatabaseCleaner.clean methods.
|
110
|
+
|
111
|
+
Inside features/support/hooks.rb:
|
112
|
+
|
113
|
+
<pre>
|
114
|
+
Before do
|
115
|
+
DatabaseCleaner.start
|
116
|
+
end
|
117
|
+
|
118
|
+
After do |scenario|
|
119
|
+
DatabaseCleaner.clean
|
120
|
+
end
|
121
|
+
</pre>
|
122
|
+
|
123
|
+
This should cover the basics of tear down between scenarios and keeping your database clean.
|
124
|
+
For more examples see the section "Why?"
|
125
|
+
|
126
|
+
h2. Common Errors
|
95
127
|
|
96
128
|
In rare cases DatabaseCleaner will encounter errors that it will log. By default it uses STDOUT set to the ERROR level but you can configure this to use whatever Logger you desire. Here's an example of using the Rails.logger in env.rb:
|
97
129
|
|
@@ -114,7 +146,7 @@ Sometimes you need to use multiple ORMs in your application. You can use Databas
|
|
114
146
|
#How to specify particular orms
|
115
147
|
DatabaseCleaner[:active_record].strategy = :transaction
|
116
148
|
DatabaseCleaner[:mongo_mapper].strategy = :truncation
|
117
|
-
|
149
|
+
|
118
150
|
#How to specify particular connections
|
119
151
|
DatabaseCleaner[:active_record,{:connection => :two}]
|
120
152
|
</pre>
|
@@ -130,6 +162,7 @@ Configuration options
|
|
130
162
|
| Mongo Mapper | DatabaseCleaner[:mongo_mapper] | Multiple connections not yet supported |
|
131
163
|
| Mongoid | DatabaseCleaner[:mongoid] | Multiple connections not yet supported |
|
132
164
|
| Couch Potato | DatabaseCleaner[:couch_potato] | Multiple connections not yet supported |
|
165
|
+
| Sequel | DatabaseCleaner[:sequel] | ? |
|
133
166
|
|
134
167
|
h2. Why?
|
135
168
|
|
data/VERSION.yml
CHANGED
@@ -43,7 +43,7 @@ module DatabaseCleaner
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def connection_klass
|
46
|
-
return ::ActiveRecord::Base
|
46
|
+
return ::ActiveRecord::Base unless connection_hash
|
47
47
|
klass = create_connection_klass
|
48
48
|
klass.send :establish_connection, connection_hash
|
49
49
|
klass
|
@@ -54,8 +54,10 @@ module DatabaseCleaner::ActiveRecord
|
|
54
54
|
|
55
55
|
def clean
|
56
56
|
connection = connection_klass.connection
|
57
|
-
|
58
|
-
connection.
|
57
|
+
connection.disable_referential_integrity do
|
58
|
+
tables_to_truncate(connection).each do |table_name|
|
59
|
+
connection.delete_table table_name
|
60
|
+
end
|
59
61
|
end
|
60
62
|
end
|
61
63
|
|
@@ -29,8 +29,17 @@ module ActiveRecord
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
# ActiveRecord 3.1 support
|
33
|
+
if defined?(AbstractMysqlAdapter)
|
34
|
+
MYSQL_ADAPTER_PARENT = USE_ARJDBC_WORKAROUND ? JdbcAdapter : AbstractMysqlAdapter
|
35
|
+
MYSQL2_ADAPTER_PARENT = AbstractMysqlAdapter
|
36
|
+
else
|
37
|
+
MYSQL_ADAPTER_PARENT = USE_ARJDBC_WORKAROUND ? JdbcAdapter : AbstractAdapter
|
38
|
+
MYSQL2_ADAPTER_PARENT = AbstractAdapter
|
39
|
+
end
|
40
|
+
|
33
41
|
SQLITE_ADAPTER_PARENT = USE_ARJDBC_WORKAROUND ? JdbcAdapter : SQLiteAdapter
|
42
|
+
POSTGRE_ADAPTER_PARENT = USE_ARJDBC_WORKAROUND ? JdbcAdapter : AbstractAdapter
|
34
43
|
|
35
44
|
class MysqlAdapter < MYSQL_ADAPTER_PARENT
|
36
45
|
def truncate_table(table_name)
|
@@ -38,7 +47,7 @@ module ActiveRecord
|
|
38
47
|
end
|
39
48
|
end
|
40
49
|
|
41
|
-
class Mysql2Adapter <
|
50
|
+
class Mysql2Adapter < MYSQL2_ADAPTER_PARENT
|
42
51
|
def truncate_table(table_name)
|
43
52
|
execute("TRUNCATE TABLE #{quote_table_name(table_name)};")
|
44
53
|
end
|
@@ -53,6 +62,7 @@ module ActiveRecord
|
|
53
62
|
class SQLite3Adapter < SQLITE_ADAPTER_PARENT
|
54
63
|
def delete_table(table_name)
|
55
64
|
execute("DELETE FROM #{quote_table_name(table_name)};")
|
65
|
+
execute("DELETE FROM sqlite_sequence where name = '#{table_name}';")
|
56
66
|
end
|
57
67
|
alias truncate_table delete_table
|
58
68
|
end
|
@@ -67,7 +77,7 @@ module ActiveRecord
|
|
67
77
|
end
|
68
78
|
end
|
69
79
|
|
70
|
-
class PostgreSQLAdapter <
|
80
|
+
class PostgreSQLAdapter < POSTGRE_ADAPTER_PARENT
|
71
81
|
|
72
82
|
def db_version
|
73
83
|
@db_version ||= postgresql_version
|
@@ -138,3 +148,4 @@ module DatabaseCleaner::ActiveRecord
|
|
138
148
|
end
|
139
149
|
|
140
150
|
|
151
|
+
|
@@ -3,9 +3,8 @@ require 'database_cleaner/data_mapper/base'
|
|
3
3
|
module DatabaseCleaner::DataMapper
|
4
4
|
class Transaction
|
5
5
|
include ::DatabaseCleaner::DataMapper::Base
|
6
|
-
|
7
|
-
def start(repository =
|
8
|
-
repository = self.db if repository.nil?
|
6
|
+
|
7
|
+
def start(repository = self.db)
|
9
8
|
::DataMapper.repository(repository) do |r|
|
10
9
|
transaction = DataMapper::Transaction.new(r)
|
11
10
|
transaction.begin
|
@@ -13,8 +12,7 @@ module DatabaseCleaner::DataMapper
|
|
13
12
|
end
|
14
13
|
end
|
15
14
|
|
16
|
-
def clean(repository =
|
17
|
-
repository = self.db if repository.nil?
|
15
|
+
def clean(repository = self.db)
|
18
16
|
::DataMapper.repository(repository) do |r|
|
19
17
|
adapter = r.adapter
|
20
18
|
while adapter.current_transaction
|
@@ -53,6 +53,7 @@ module DataMapper
|
|
53
53
|
|
54
54
|
def truncate_table(table_name)
|
55
55
|
execute("DELETE FROM #{quote_name(table_name)};")
|
56
|
+
execute("DELETE FROM sqlite_sequence where name = '#{table_name}';")
|
56
57
|
end
|
57
58
|
|
58
59
|
# this is a no-op copied from activerecord
|
@@ -79,6 +80,7 @@ module DataMapper
|
|
79
80
|
|
80
81
|
def truncate_table(table_name)
|
81
82
|
execute("DELETE FROM #{quote_name(table_name)};")
|
83
|
+
execute("DELETE FROM sqlite_sequence where name = '#{table_name}';")
|
82
84
|
end
|
83
85
|
|
84
86
|
# this is a no-op copied from activerecord
|
@@ -107,7 +109,7 @@ module DataMapper
|
|
107
109
|
end
|
108
110
|
|
109
111
|
def truncate_table(table_name)
|
110
|
-
execute("TRUNCATE TABLE #{quote_name(table_name)} CASCADE;")
|
112
|
+
execute("TRUNCATE TABLE #{quote_name(table_name)} RESTART IDENTITY CASCADE;")
|
111
113
|
end
|
112
114
|
|
113
115
|
# FIXME
|
@@ -148,8 +150,7 @@ module DatabaseCleaner
|
|
148
150
|
include ::DatabaseCleaner::DataMapper::Base
|
149
151
|
include ::DatabaseCleaner::Generic::Truncation
|
150
152
|
|
151
|
-
def clean(repository =
|
152
|
-
repository = self.db if repository.nil?
|
153
|
+
def clean(repository = self.db)
|
153
154
|
adapter = ::DataMapper.repository(repository).adapter
|
154
155
|
adapter.disable_referential_integrity do
|
155
156
|
tables_to_truncate(repository).each do |table_name|
|
@@ -160,8 +161,7 @@ module DatabaseCleaner
|
|
160
161
|
|
161
162
|
private
|
162
163
|
|
163
|
-
def tables_to_truncate(repository =
|
164
|
-
repository = self.db if repository.nil?
|
164
|
+
def tables_to_truncate(repository = self.db)
|
165
165
|
(@only || ::DataMapper.repository(repository).adapter.storage_names(repository)) - @tables_to_exclude
|
166
166
|
end
|
167
167
|
|
@@ -1,42 +1,36 @@
|
|
1
1
|
module DatabaseCleaner
|
2
2
|
module Generic
|
3
3
|
module Truncation
|
4
|
-
def
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
module InstanceMethods
|
9
|
-
def initialize(opts={})
|
10
|
-
if !opts.empty? && !(opts.keys - [:only, :except]).empty?
|
11
|
-
raise ArgumentError, "The only valid options are :only and :except. You specified #{opts.keys.join(',')}."
|
12
|
-
end
|
13
|
-
if opts.has_key?(:only) && opts.has_key?(:except)
|
14
|
-
raise ArgumentError, "You may only specify either :only or :either. Doing both doesn't really make sense does it?"
|
15
|
-
end
|
16
|
-
|
17
|
-
@only = opts[:only]
|
18
|
-
@tables_to_exclude = (opts[:except] || []).dup
|
19
|
-
@tables_to_exclude << migration_storage_name unless migration_storage_name.nil?
|
4
|
+
def initialize(opts={})
|
5
|
+
if !opts.empty? && !(opts.keys - [:only, :except]).empty?
|
6
|
+
raise ArgumentError, "The only valid options are :only and :except. You specified #{opts.keys.join(',')}."
|
20
7
|
end
|
21
|
-
|
22
|
-
|
23
|
-
#included for compatability reasons, do nothing if you don't need to
|
8
|
+
if opts.has_key?(:only) && opts.has_key?(:except)
|
9
|
+
raise ArgumentError, "You may only specify either :only or :except. Doing both doesn't really make sense does it?"
|
24
10
|
end
|
25
11
|
|
26
|
-
|
27
|
-
|
28
|
-
|
12
|
+
@only = opts[:only]
|
13
|
+
@tables_to_exclude = (opts[:except] || []).dup
|
14
|
+
@tables_to_exclude << migration_storage_name if migration_storage_name
|
15
|
+
end
|
29
16
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
17
|
+
def start
|
18
|
+
#included for compatability reasons, do nothing if you don't need to
|
19
|
+
end
|
20
|
+
|
21
|
+
def clean
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def tables_to_truncate
|
27
|
+
raise NotImplementedError
|
28
|
+
end
|
34
29
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
30
|
+
# overwrite in subclasses
|
31
|
+
# default implementation given because migration storage need not be present
|
32
|
+
def migration_storage_name
|
33
|
+
nil
|
40
34
|
end
|
41
35
|
end
|
42
36
|
end
|
@@ -34,7 +34,6 @@ module DatabaseCleaner
|
|
34
34
|
it_should_behave_like "a generic strategy"
|
35
35
|
|
36
36
|
describe "db" do
|
37
|
-
it { should respond_to(:db=) }
|
38
37
|
|
39
38
|
it "should store my desired db" do
|
40
39
|
subject.stub(:load_config)
|
@@ -55,9 +54,8 @@ module DatabaseCleaner
|
|
55
54
|
|
56
55
|
describe "load_config" do
|
57
56
|
|
58
|
-
it { should respond_to(:load_config) }
|
59
|
-
|
60
57
|
before do
|
58
|
+
subject.db = :my_db
|
61
59
|
yaml = <<-Y
|
62
60
|
my_db:
|
63
61
|
database: <%= "ONE".downcase %>
|
@@ -81,7 +79,6 @@ my_db:
|
|
81
79
|
end
|
82
80
|
|
83
81
|
it "should store the relevant config in connection_hash" do
|
84
|
-
subject.should_receive(:db).and_return(:my_db)
|
85
82
|
subject.load_config
|
86
83
|
subject.connection_hash.should == {"database" => "one"}
|
87
84
|
end
|
@@ -91,11 +88,17 @@ my_db:
|
|
91
88
|
subject.load_config
|
92
89
|
subject.connection_hash.should be_blank
|
93
90
|
end
|
91
|
+
|
92
|
+
it "skips the file when the db is set to :default" do
|
93
|
+
# to avoid https://github.com/bmabey/database_cleaner/issues/72
|
94
|
+
subject.db = :default
|
95
|
+
YAML.should_not_receive(:load)
|
96
|
+
subject.load_config
|
97
|
+
end
|
98
|
+
|
94
99
|
end
|
95
100
|
|
96
101
|
describe "connection_hash" do
|
97
|
-
it { should respond_to(:connection_hash) }
|
98
|
-
it { should respond_to(:connection_hash=) }
|
99
102
|
it "should store connection_hash" do
|
100
103
|
subject.connection_hash = { :key => "value" }
|
101
104
|
subject.connection_hash.should == { :key => "value" }
|
@@ -38,12 +38,17 @@ module DatabaseCleaner
|
|
38
38
|
|
39
39
|
describe "#clean" do
|
40
40
|
it "should start a transaction" do
|
41
|
+
connection.should_receive(:open_transactions).and_return(1)
|
42
|
+
|
41
43
|
connection.stub!(:decrement_open_transactions)
|
42
44
|
|
43
45
|
connection.should_receive(:rollback_db_transaction)
|
44
46
|
Transaction.new.clean
|
45
47
|
end
|
48
|
+
|
46
49
|
it "should decrement open transactions if possible" do
|
50
|
+
connection.should_receive(:open_transactions).and_return(1)
|
51
|
+
|
47
52
|
connection.stub!(:respond_to?).with(:decrement_open_transactions).and_return(true)
|
48
53
|
connection.stub!(:rollback_db_transaction)
|
49
54
|
|
@@ -51,7 +56,14 @@ module DatabaseCleaner
|
|
51
56
|
Transaction.new.clean
|
52
57
|
end
|
53
58
|
|
59
|
+
it "should not try to decrement or rollback if open_transactions is 0 for whatever reason" do
|
60
|
+
connection.should_receive(:open_transactions).and_return(0)
|
61
|
+
|
62
|
+
Transaction.new.clean
|
63
|
+
end
|
64
|
+
|
54
65
|
it "should decrement connection via ActiveRecord::Base if connection won't" do
|
66
|
+
connection.should_receive(:open_transactions).and_return(1)
|
55
67
|
connection.stub!(:respond_to?).with(:decrement_open_transactions).and_return(false)
|
56
68
|
connection.stub!(:rollback_db_transaction)
|
57
69
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: database_cleaner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 1
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 7
|
9
|
-
-
|
10
|
-
version: 0.7.
|
9
|
+
- 1
|
10
|
+
version: 0.7.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ben Mabey
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2012-01-15 00:00:00 Z
|
19
19
|
dependencies: []
|
20
20
|
|
21
21
|
description: Strategies for cleaning databases. Can be used to ensure a clean state for testing.
|