test_data 0.2.0 → 0.2.1
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.
- checksums.yaml +4 -4
- data/.standard.yml +2 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +1 -1
- data/README.md +588 -693
- data/example/.gitignore +1 -4
- data/example/Gemfile.lock +1 -1
- data/example/config/application.rb +3 -0
- data/example/spec/requests/rails_fixtures_override_spec.rb +26 -4
- data/example/test/integration/test_data_hooks_test.rb +89 -0
- data/lib/generators/test_data/initializer_generator.rb +18 -6
- data/lib/test_data/config.rb +29 -1
- data/lib/test_data/custom_loaders/rails_fixtures.rb +2 -0
- data/lib/test_data/manager.rb +2 -0
- data/lib/test_data/rake.rb +2 -3
- data/lib/test_data/version.rb +1 -1
- data/script/reset_example_app +1 -0
- data/script/test +18 -6
- metadata +4 -2
data/example/.gitignore
CHANGED
@@ -18,7 +18,4 @@
|
|
18
18
|
# Ignore master key for decrypting credentials and more.
|
19
19
|
/config/master.key
|
20
20
|
|
21
|
-
|
22
|
-
/config/environments/test_data.rb
|
23
|
-
/test/support/test_data
|
24
|
-
/db/migrate/20210418220133_add_beep_to_boops.rb
|
21
|
+
|
data/example/Gemfile.lock
CHANGED
@@ -24,6 +24,9 @@ module Example
|
|
24
24
|
# Initialize configuration defaults for originally generated Rails version.
|
25
25
|
config.load_defaults 6.1
|
26
26
|
|
27
|
+
# Uncomment this to switch from schema.rb to structure.sql
|
28
|
+
# config.active_record.schema_format = :sql
|
29
|
+
|
27
30
|
# Configuration for the application, engines, and railties goes here.
|
28
31
|
#
|
29
32
|
# These settings can be overridden in specific environments using the files
|
@@ -2,18 +2,40 @@ require "rails_helper"
|
|
2
2
|
|
3
3
|
TestData.prevent_rails_fixtures_from_loading_automatically!
|
4
4
|
|
5
|
+
module TestDataModes
|
6
|
+
def uses(mode)
|
7
|
+
case mode
|
8
|
+
when :clean_slate
|
9
|
+
before(:each) { TestData.uses_clean_slate }
|
10
|
+
when :test_data
|
11
|
+
before(:each) { TestData.uses_test_data }
|
12
|
+
else
|
13
|
+
raise "Invalid test data mode: #{mode}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
config.extend(TestDataModes)
|
20
|
+
end
|
21
|
+
|
5
22
|
RSpec.describe "FixtureFreeTestData", type: :request do
|
6
23
|
fixtures :boops
|
7
24
|
|
8
|
-
|
9
|
-
TestData.uses_test_data
|
10
|
-
end
|
11
|
-
|
25
|
+
uses :test_data
|
12
26
|
it "has 15 boops in the test_data" do
|
13
27
|
expect(Boop.count).to eq(15)
|
14
28
|
end
|
15
29
|
end
|
16
30
|
|
31
|
+
RSpec.describe "Clean Slate" do
|
32
|
+
uses :clean_slate
|
33
|
+
|
34
|
+
it "has no boops" do
|
35
|
+
expect(Boop.count).to eq(0)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
17
39
|
RSpec.describe "FixturesUsingTest", type: :request do
|
18
40
|
fixtures :boops
|
19
41
|
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
TestData.config do |config|
|
4
|
+
config.after_test_data_load { MetaBoop.refresh_materialized_view }
|
5
|
+
config.after_test_data_truncate(-> { MetaBoop.refresh_materialized_view })
|
6
|
+
config.after_rails_fixture_load { MetaBoop.refresh_materialized_view }
|
7
|
+
end
|
8
|
+
|
9
|
+
TestData.prevent_rails_fixtures_from_loading_automatically!
|
10
|
+
MetaBoop.refresh_materialized_view # count = 1
|
11
|
+
|
12
|
+
class TestDataHooksTest < ActiveSupport::TestCase
|
13
|
+
fixtures :all
|
14
|
+
i_suck_and_my_tests_are_order_dependent!
|
15
|
+
|
16
|
+
def test_uses_test_data_hook
|
17
|
+
assert_equal 1, MetaBoop.refresh_materialized_view_count
|
18
|
+
MetaBoop.reset_refresh_materialized_view_count
|
19
|
+
|
20
|
+
# Materialized view is refreshed and called 1 time
|
21
|
+
TestData.uses_test_data
|
22
|
+
assert_equal 15, Boop.count
|
23
|
+
assert_equal 15, MetaBoop.count
|
24
|
+
assert_equal 1, MetaBoop.refresh_materialized_view_count
|
25
|
+
MetaBoop.reset_refresh_materialized_view_count
|
26
|
+
|
27
|
+
# Rollbacks also rollback to materialized view changes without calling again
|
28
|
+
Boop.create!(other_boop: Boop.new)
|
29
|
+
assert_equal 16, Boop.count
|
30
|
+
assert_equal 15, MetaBoop.count
|
31
|
+
MetaBoop.refresh_materialized_view
|
32
|
+
assert_equal 16, MetaBoop.count
|
33
|
+
assert_equal 1, MetaBoop.refresh_materialized_view_count
|
34
|
+
TestData.uses_test_data
|
35
|
+
assert_equal 15, Boop.count
|
36
|
+
assert_equal 15, MetaBoop.count
|
37
|
+
assert_equal 1, MetaBoop.refresh_materialized_view_count
|
38
|
+
MetaBoop.reset_refresh_materialized_view_count
|
39
|
+
|
40
|
+
# The same hook also works when cleaning slates
|
41
|
+
TestData.uses_clean_slate
|
42
|
+
assert_equal 0, Boop.count
|
43
|
+
assert_equal 0, MetaBoop.count
|
44
|
+
assert_equal 1, MetaBoop.refresh_materialized_view_count
|
45
|
+
Boop.create!(other_boop: Boop.new)
|
46
|
+
MetaBoop.refresh_materialized_view
|
47
|
+
assert_equal 1, Boop.count
|
48
|
+
assert_equal 1, MetaBoop.count
|
49
|
+
assert_equal 2, MetaBoop.refresh_materialized_view_count
|
50
|
+
TestData.uses_clean_slate
|
51
|
+
assert_equal 0, Boop.count
|
52
|
+
assert_equal 0, MetaBoop.count
|
53
|
+
assert_equal 2, MetaBoop.refresh_materialized_view_count
|
54
|
+
MetaBoop.reset_refresh_materialized_view_count
|
55
|
+
|
56
|
+
# The same hook works with fixtures
|
57
|
+
TestData.uses_rails_fixtures(self)
|
58
|
+
assert_equal 2, Boop.count
|
59
|
+
assert_equal 2, MetaBoop.count
|
60
|
+
assert_equal 1, MetaBoop.refresh_materialized_view_count
|
61
|
+
Boop.first.delete
|
62
|
+
assert_equal 1, Boop.count
|
63
|
+
assert_equal 2, MetaBoop.count
|
64
|
+
MetaBoop.refresh_materialized_view
|
65
|
+
assert_equal 1, MetaBoop.count
|
66
|
+
assert_equal 2, MetaBoop.refresh_materialized_view_count
|
67
|
+
TestData.uses_rails_fixtures(self)
|
68
|
+
assert_equal 2, Boop.count
|
69
|
+
assert_equal 2, MetaBoop.count
|
70
|
+
assert_equal 2, MetaBoop.refresh_materialized_view_count
|
71
|
+
MetaBoop.reset_refresh_materialized_view_count
|
72
|
+
|
73
|
+
# Rewinding two steps will not call refresh materialized views
|
74
|
+
TestData.uses_test_data
|
75
|
+
assert_equal 15, Boop.count
|
76
|
+
assert_equal 15, MetaBoop.count
|
77
|
+
assert_equal 0, MetaBoop.refresh_materialized_view_count
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_that_hooks_require_valid_settings
|
81
|
+
foo = Struct.new(:thing)
|
82
|
+
assert_raises(TestData::Error) { TestData.config.after_test_data_load(nil) }
|
83
|
+
assert_raises(TestData::Error) { TestData.config.after_test_data_truncate(nil) }
|
84
|
+
assert_raises(TestData::Error) { TestData.config.after_rails_fixture_load(nil) }
|
85
|
+
assert_raises(TestData::Error) { TestData.config.after_test_data_load(foo) }
|
86
|
+
assert_raises(TestData::Error) { TestData.config.after_test_data_truncate(foo) }
|
87
|
+
assert_raises(TestData::Error) { TestData.config.after_rails_fixture_load(foo) }
|
88
|
+
end
|
89
|
+
end
|
@@ -8,14 +8,17 @@ module TestData
|
|
8
8
|
return unless defined?(TestData)
|
9
9
|
|
10
10
|
TestData.config do |config|
|
11
|
-
#
|
12
|
-
#
|
11
|
+
# Hook run after test data is loaded by `TestData.uses_test_data`,
|
12
|
+
# but before a savepoint is taken
|
13
|
+
# config.after_test_data_load { }
|
13
14
|
|
14
|
-
#
|
15
|
-
#
|
15
|
+
# Hook run after test data is truncated by `TestData.uses_clean_slate`,
|
16
|
+
# but before a savepoint is taken
|
17
|
+
# config.after_test_data_truncate { }
|
16
18
|
|
17
|
-
#
|
18
|
-
#
|
19
|
+
# Hook run after test data is truncated by `TestData.uses_rails_fixtures`,
|
20
|
+
# but before a savepoint is taken
|
21
|
+
# config.after_rails_fixture_load { }
|
19
22
|
|
20
23
|
# Tables whose data shouldn't be loaded into tests.
|
21
24
|
# ("ar_internal_metadata" and "schema_migrations" are always excluded)
|
@@ -24,6 +27,15 @@ module TestData
|
|
24
27
|
# Tables whose data should be excluded from SQL dumps (still dumps their schema DDL)
|
25
28
|
# config.dont_dump_these_tables = []
|
26
29
|
|
30
|
+
# Where to store SQL dumps of the test_data database schema
|
31
|
+
# config.schema_dump_path = "test/support/test_data/schema.sql"
|
32
|
+
|
33
|
+
# Where to store SQL dumps of the test_data database test data
|
34
|
+
# config.data_dump_path = "test/support/test_data/data.sql"
|
35
|
+
|
36
|
+
# Where to store SQL dumps of the test_data database non-test data
|
37
|
+
# config.non_test_data_dump_path = "test/support/test_data/non_test_data.sql"
|
38
|
+
|
27
39
|
# Tables whose data should be truncated by TestData.uses_clean_slate
|
28
40
|
# If left as `nil`, all tables inserted into by the SQL file at
|
29
41
|
# `data_dump_path` will be truncated
|
data/lib/test_data/config.rb
CHANGED
@@ -41,7 +41,8 @@ module TestData
|
|
41
41
|
TestData.log.level = level
|
42
42
|
end
|
43
43
|
|
44
|
-
attr_reader :pwd, :cable_yaml_path, :database_yaml_path, :secrets_yaml_path
|
44
|
+
attr_reader :pwd, :cable_yaml_path, :database_yaml_path, :secrets_yaml_path,
|
45
|
+
:after_test_data_load_hook, :after_test_data_truncate_hook, :after_rails_fixture_load_hook
|
45
46
|
|
46
47
|
def self.full_path_reader(*relative_path_readers)
|
47
48
|
relative_path_readers.each do |relative_path_reader|
|
@@ -64,6 +65,33 @@ module TestData
|
|
64
65
|
@non_test_data_tables = []
|
65
66
|
@dont_dump_these_tables = []
|
66
67
|
@truncate_these_test_data_tables = nil
|
68
|
+
@after_test_data_load_hook = -> {}
|
69
|
+
@after_test_data_truncate_hook = -> {}
|
70
|
+
@after_rails_fixture_load_hook = -> {}
|
71
|
+
end
|
72
|
+
|
73
|
+
def after_test_data_load(callable = nil, &blk)
|
74
|
+
hook = callable || blk
|
75
|
+
if !hook.respond_to?(:call)
|
76
|
+
raise Error.new("after_test_data_load must be passed a callable (e.g. a Proc) or called with a block")
|
77
|
+
end
|
78
|
+
@after_test_data_load_hook = hook
|
79
|
+
end
|
80
|
+
|
81
|
+
def after_test_data_truncate(callable = nil, &blk)
|
82
|
+
hook = callable || blk
|
83
|
+
if !hook.respond_to?(:call)
|
84
|
+
raise Error.new("after_test_data_truncate must be passed a callable (e.g. a Proc) or called with a block")
|
85
|
+
end
|
86
|
+
@after_test_data_truncate_hook = hook
|
87
|
+
end
|
88
|
+
|
89
|
+
def after_rails_fixture_load(callable = nil, &blk)
|
90
|
+
hook = callable || blk
|
91
|
+
if !hook.respond_to?(:call)
|
92
|
+
raise Error.new("after_rails_fixture_load must be passed a callable (e.g. a Proc) or called with a block")
|
93
|
+
end
|
94
|
+
@after_rails_fixture_load_hook = hook
|
67
95
|
end
|
68
96
|
|
69
97
|
def database_yaml
|
@@ -2,6 +2,7 @@ module TestData
|
|
2
2
|
module CustomLoaders
|
3
3
|
class RailsFixtures < AbstractBase
|
4
4
|
def initialize
|
5
|
+
@config = TestData.config
|
5
6
|
@statistics = TestData.statistics
|
6
7
|
@already_loaded_rails_fixtures = {}
|
7
8
|
end
|
@@ -34,6 +35,7 @@ module TestData
|
|
34
35
|
test_instance.__test_data_gem_setup_fixtures
|
35
36
|
@already_loaded_rails_fixtures[test_instance.class] = test_instance.instance_variable_get(:@loaded_fixtures)
|
36
37
|
@statistics.count_load_rails_fixtures!
|
38
|
+
@config.after_rails_fixture_load_hook.call
|
37
39
|
end
|
38
40
|
end
|
39
41
|
end
|
data/lib/test_data/manager.rb
CHANGED
@@ -14,6 +14,7 @@ module TestData
|
|
14
14
|
|
15
15
|
create_save_point(:before_data_load)
|
16
16
|
@inserts_test_data.call
|
17
|
+
@config.after_test_data_load_hook.call
|
17
18
|
record_ar_internal_metadata_that_test_data_is_loaded
|
18
19
|
create_save_point(:after_data_load)
|
19
20
|
end
|
@@ -41,6 +42,7 @@ module TestData
|
|
41
42
|
end
|
42
43
|
|
43
44
|
@truncates_test_data.call
|
45
|
+
@config.after_test_data_truncate_hook.call
|
44
46
|
record_ar_internal_metadata_that_test_data_is_truncated
|
45
47
|
create_save_point(:after_data_truncate)
|
46
48
|
end
|
data/lib/test_data/rake.rb
CHANGED
@@ -52,8 +52,7 @@ task "test_data:initialize" => ["test_data:verify_config", :environment] do
|
|
52
52
|
end
|
53
53
|
|
54
54
|
TestData.log.info <<~MSG
|
55
|
-
Your test_data environment and database are ready for use! You can now run
|
56
|
-
your server (or any command) to create some test data like so:
|
55
|
+
Your test_data environment and database are ready for use! You can now run your server (or any command) to create some test data like so:
|
57
56
|
|
58
57
|
$ RAILS_ENV=test_data bin/rails server
|
59
58
|
|
@@ -83,7 +82,7 @@ task "test_data:load" => ["test_data:verify_config", :environment] do
|
|
83
82
|
TestData::LoadsDatabaseDumps.new.call
|
84
83
|
|
85
84
|
if ActiveRecord::Base.connection.migration_context.needs_migration?
|
86
|
-
TestData.log.warn "There are pending migrations for database '#{TestData.config.database_name}'. To run them, run:\n\n RAILS_ENV=test_data bin/rake db:migrate\n\n"
|
85
|
+
TestData.log.warn "There are pending migrations for database '#{TestData.config.database_name}'. To run them, run:\n\n $ RAILS_ENV=test_data bin/rake db:migrate\n\n"
|
87
86
|
end
|
88
87
|
end
|
89
88
|
|
data/lib/test_data/version.rb
CHANGED
data/script/reset_example_app
CHANGED
data/script/test
CHANGED
@@ -83,18 +83,30 @@ cp ../test/fixtures/20210423190737_add_foreign_keys.rb db/migrate/
|
|
83
83
|
cp ../test/fixtures/boop_with_other_boops.rb app/models/boop.rb
|
84
84
|
RAILS_ENV=test_data bin/rake db:migrate
|
85
85
|
bin/rake test_data:dump
|
86
|
-
bin/rake db:migrate
|
87
|
-
bin/rake db:test:prepare
|
86
|
+
bin/rake db:migrate db:test:prepare
|
88
87
|
bin/rails test test/integration/boops_that_boop_boops_test.rb
|
89
88
|
|
90
89
|
# Make sure it loads cleanly again
|
91
90
|
bin/rake test_data:drop_database
|
92
|
-
|
93
|
-
echo "Running test_data:load after adding FK constraints led to errors"
|
94
|
-
exit 1
|
95
|
-
fi
|
91
|
+
bin/rake test_data:load
|
96
92
|
bin/rails test test/integration/boops_that_boop_boops_test.rb
|
97
93
|
|
94
|
+
# Test all the after hooks!
|
95
|
+
cp ../test/fixtures/20210729130542_add_materialized_meta_boop_view.rb db/migrate/
|
96
|
+
cp ../test/fixtures/meta_boop.rb app/models/meta_boop.rb
|
97
|
+
# Gsub config file to switch to structure.sql b/c materialized view
|
98
|
+
ruby -e '
|
99
|
+
path = "config/application.rb"
|
100
|
+
IO.write(path, File.open(path) { |f|
|
101
|
+
f.read.gsub("# config.active_record.schema_format = :sql", "config.active_record.schema_format = :sql")
|
102
|
+
})
|
103
|
+
'
|
104
|
+
rm db/schema.rb
|
105
|
+
bin/rake db:migrate db:test:prepare
|
106
|
+
RAILS_ENV=test_data bin/rake db:migrate
|
107
|
+
bin/rake test_data:dump
|
108
|
+
bin/rails test test/integration/test_data_hooks_test.rb
|
109
|
+
|
98
110
|
# Cleanup
|
99
111
|
cd ..
|
100
112
|
./script/reset_example_app
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: test_data
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Searls
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-07-
|
11
|
+
date: 2021-07-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -33,6 +33,7 @@ extra_rdoc_files: []
|
|
33
33
|
files:
|
34
34
|
- ".github/workflows/ruby.yml"
|
35
35
|
- ".gitignore"
|
36
|
+
- ".standard.yml"
|
36
37
|
- CHANGELOG.md
|
37
38
|
- Gemfile
|
38
39
|
- Gemfile.lock
|
@@ -109,6 +110,7 @@ files:
|
|
109
110
|
- example/test/integration/parallel_boops_without_fixtures_test.rb
|
110
111
|
- example/test/integration/rails_fixtures_double_load_test.rb
|
111
112
|
- example/test/integration/rails_fixtures_override_test.rb
|
113
|
+
- example/test/integration/test_data_hooks_test.rb
|
112
114
|
- example/test/integration/transaction_committing_boops_test.rb
|
113
115
|
- example/test/integration/updated_boops_test.rb
|
114
116
|
- example/test/test_helper.rb
|