test_data 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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
- # Ignore files that are intentionally generated / asserted by the tests
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- test_data (0.2.0)
4
+ test_data (0.2.1)
5
5
  railties (~> 6.0)
6
6
 
7
7
  GEM
@@ -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
- before(:each) do
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
- # Where to store SQL dumps of the test_data database schema
12
- # config.schema_dump_path = "test/support/test_data/schema.sql"
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
- # Where to store SQL dumps of the test_data database test data
15
- # config.data_dump_path = "test/support/test_data/data.sql"
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
- # Where to store SQL dumps of the test_data database non-test data
18
- # config.non_test_data_dump_path = "test/support/test_data/non_test_data.sql"
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
@@ -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
@@ -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
@@ -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
 
@@ -1,3 +1,3 @@
1
1
  module TestData
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -12,6 +12,7 @@ dropdb example_test_data 2>/dev/null || true
12
12
 
13
13
  # Reset files:
14
14
  git checkout app/models/boop.rb
15
+ git checkout config/application.rb
15
16
  git checkout config/database.yml
16
17
  git checkout db/schema.rb
17
18
  git clean -xdf .
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
- if [ ! bin/rake test_data:load | grep -q "ERROR" ]; then
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.0
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-24 00:00:00.000000000 Z
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