test_data 0.1.0 → 0.2.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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -5
  3. data/CHANGELOG.md +17 -1
  4. data/Gemfile.lock +1 -1
  5. data/LICENSE.txt +1 -1
  6. data/README.md +102 -102
  7. data/example/Gemfile.lock +1 -1
  8. data/example/config/credentials.yml.enc +1 -2
  9. data/example/spec/rails_helper.rb +1 -1
  10. data/example/spec/requests/boops_spec.rb +1 -5
  11. data/example/spec/requests/rails_fixtures_override_spec.rb +84 -0
  12. data/example/test/integration/better_mode_switching_demo_test.rb +2 -10
  13. data/example/test/integration/load_rollback_truncate_test.rb +40 -45
  14. data/example/test/integration/mode_switching_demo_test.rb +4 -14
  15. data/example/test/integration/parallel_boops_with_fixtures_test.rb +1 -5
  16. data/example/test/integration/parallel_boops_without_fixtures_test.rb +1 -5
  17. data/example/test/integration/rails_fixtures_double_load_test.rb +2 -2
  18. data/example/test/integration/rails_fixtures_override_test.rb +18 -35
  19. data/example/test/integration/transaction_committing_boops_test.rb +1 -10
  20. data/example/test/test_helper.rb +1 -5
  21. data/lib/generators/test_data/environment_file_generator.rb +4 -0
  22. data/lib/generators/test_data/initializer_generator.rb +1 -7
  23. data/lib/test_data.rb +32 -1
  24. data/lib/test_data/config.rb +1 -11
  25. data/lib/test_data/custom_loaders/abstract_base.rb +25 -0
  26. data/lib/test_data/custom_loaders/rails_fixtures.rb +40 -0
  27. data/lib/test_data/inserts_test_data.rb +25 -0
  28. data/lib/test_data/manager.rb +185 -0
  29. data/lib/test_data/truncates_test_data.rb +31 -0
  30. data/lib/test_data/version.rb +1 -1
  31. data/script/test +1 -0
  32. metadata +8 -3
  33. data/lib/test_data/transactional_data_loader.rb +0 -300
@@ -2,11 +2,7 @@ require "rails_helper"
2
2
 
3
3
  RSpec.configure do |config|
4
4
  config.before(:each) do
5
- TestData.load
6
- end
7
-
8
- config.after(:each) do
9
- TestData.rollback
5
+ TestData.uses_test_data
10
6
  end
11
7
  end
12
8
 
@@ -0,0 +1,84 @@
1
+ require "rails_helper"
2
+
3
+ TestData.prevent_rails_fixtures_from_loading_automatically!
4
+
5
+ RSpec.describe "FixtureFreeTestData", type: :request do
6
+ fixtures :boops
7
+
8
+ before(:each) do
9
+ TestData.uses_test_data
10
+ end
11
+
12
+ it "has 15 boops in the test_data" do
13
+ expect(Boop.count).to eq(15)
14
+ end
15
+ end
16
+
17
+ RSpec.describe "FixturesUsingTest", type: :request do
18
+ fixtures :boops
19
+
20
+ before(:each) do
21
+ TestData.uses_rails_fixtures(self)
22
+ end
23
+
24
+ it "has_fixture_boops" do
25
+ expect(boops(:boop_1)).to be_persisted
26
+ expect(Boop.count).to eq(2)
27
+ end
28
+
29
+ it "does_not_get_the_other_fixture_accessor" do
30
+ expect { method(:pants) }.to raise_error(NameError)
31
+ end
32
+
33
+ it "even_explicitly_loading_test_data_will_truncate_and_then_load_fixtures" do
34
+ TestData.uses_test_data
35
+ TestData.uses_rails_fixtures(self)
36
+
37
+ expect(Boop.count).to eq(2)
38
+ end
39
+
40
+ it "load_and_rollback_leaves_them_as_is" do
41
+ boop = Boop.first
42
+ original_created_on = boop.created_at.to_date
43
+ a_year_ago = 1.year.ago.to_date
44
+
45
+ boop.update!(created_at: a_year_ago)
46
+
47
+ expect(Boop.find(boop.id).created_at.to_date).to eq(a_year_ago)
48
+
49
+ # Now after rollback
50
+ TestData.uses_rails_fixtures(self)
51
+
52
+ expect(Boop.find(boop.id).created_at.to_date).to eq(original_created_on)
53
+ end
54
+ end
55
+
56
+ RSpec.describe "SomeFixturesAndSomeTestDataInOneClassTest", type: :request do
57
+ fixtures :all
58
+
59
+ it "fixtures_work" do
60
+ TestData.uses_rails_fixtures(self)
61
+
62
+ expect(boops(:boop_1).updated_at.to_date).to eq(Date.civil(2020, 1, 1))
63
+ expect(pants(:pant_1).brand).to eq("Levi")
64
+ end
65
+
66
+ it "test_that_rewinds_to_test_data" do
67
+ TestData.uses_test_data
68
+
69
+ expect(Boop.count).to eq(15)
70
+ end
71
+
72
+ it "that_rewinds_to_the_very_start" do
73
+ TestData.uninitialize
74
+
75
+ expect(Boop.count).to eq(0)
76
+ end
77
+
78
+ it "fixtures_get_reloaded_because_cache_is_cleared" do
79
+ TestData.uses_rails_fixtures(self)
80
+
81
+ expect(boops(:boop_2).updated_at.to_date).to eq(Date.civil(2019, 1, 1))
82
+ expect(pants(:pant_2).brand).to eq("Wrangler")
83
+ end
84
+ end
@@ -8,19 +8,11 @@ class ActiveSupport::TestCase
8
8
  include FactoryBot::Syntax::Methods
9
9
 
10
10
  setup do
11
- TestData.truncate
12
- end
13
-
14
- teardown do
15
- TestData.rollback(:after_data_truncate)
11
+ TestData.uses_clean_slate
16
12
  end
17
13
  when :test_data
18
14
  setup do
19
- TestData.load
20
- end
21
-
22
- teardown do
23
- TestData.rollback
15
+ TestData.uses_test_data
24
16
  end
25
17
  end
26
18
  end
@@ -14,7 +14,6 @@ class LoadRollbackTruncateTest < ActiveSupport::TestCase
14
14
  def teardown
15
15
  TestData.log.reset
16
16
  TestData.statistics.reset
17
- TestData.rollback(:before_data_load)
18
17
  end
19
18
 
20
19
  def test_loads_data_then_truncates_then_rolls_back_etc
@@ -22,101 +21,97 @@ class LoadRollbackTruncateTest < ActiveSupport::TestCase
22
21
  assert_equal 0, Boop.count
23
22
 
24
23
  # Now load the dump
25
- TestData.load
24
+ TestData.uses_test_data
26
25
  assert_equal 15, Boop.count
27
26
  Boop.create!
28
27
  assert_equal 16, Boop.count
29
28
 
30
29
  # Next, truncate the boops
31
- TestData.truncate
30
+ TestData.uses_clean_slate
32
31
  assert_equal 0, Boop.count
33
32
  Boop.create!
34
33
  assert_equal 1, Boop.count
35
34
 
36
35
  # Now roll back to _just after truncate_
37
- TestData.rollback(:after_data_truncate)
36
+ TestData.uses_clean_slate
38
37
  assert_equal 0, Boop.count
39
38
  Boop.create!
40
39
  assert_equal 1, Boop.count
41
40
 
42
41
  # Verify default rollback works after truncate
43
- TestData.rollback
42
+ TestData.uses_test_data
44
43
  assert_equal 15, Boop.count
45
44
 
46
45
  # Verify touching non-test-data tables will also be first rollbacked when truncate is called
47
- TestData.rollback(:before_data_load)
46
+ TestData.uninitialize
48
47
  good = ChattyAuditLog.create!(message: "I do belong here, because now we're at the start, prior to test_data's purview")
49
- TestData.load
48
+ TestData.uses_test_data
50
49
  bad = ChattyAuditLog.create!(message: "I won't belong here after truncate because I'm data that the truncate-calling test wouldn't expect")
51
50
  assert_equal 2, ChattyAuditLog.count
52
51
 
53
- TestData.truncate
52
+ TestData.uses_clean_slate
54
53
 
55
54
  assert_equal 1, ChattyAuditLog.count
56
55
  refute_nil ChattyAuditLog.find_by(id: good.id)
57
56
  assert_nil ChattyAuditLog.find_by(id: bad.id)
58
57
 
59
- # Verify rollbacking to some nonsense savepoint errors out:
60
- error = assert_raise(TestData::Error) { TestData.rollback(:before_nonsense) }
61
- assert_match "No known save point named 'before_nonsense'", error.message
62
-
63
58
  # Warn but load anyway if rolled back to the start and then truncated
64
- TestData.rollback(:before_data_load)
65
- TestData.truncate
59
+ TestData.uninitialize
60
+ TestData.uses_clean_slate
66
61
  assert_equal :debug, @last_log.level
67
- assert_match "TestData.truncate was called, but data was not loaded. Loading data", @last_log.message
62
+ assert_match "TestData.uses_clean_slate was called, but data was not loaded. Loading data", @last_log.message
68
63
  assert_equal 0, Boop.count
69
- TestData.rollback
64
+ TestData.uses_test_data
70
65
  assert_equal 15, Boop.count
71
66
 
72
67
  # Chaos: try rolling back outside the gem (one level of extraneous rollback) and verify load recovers
73
- TestData.rollback(:before_data_load)
68
+ TestData.uninitialize
74
69
  TestData.statistics.reset
75
70
  assert_equal 0, TestData.statistics.load_count
76
- TestData.load
71
+ TestData.uses_test_data
77
72
  assert_equal 1, TestData.statistics.load_count
78
- TestData.load # Smart enough to not load again
73
+ TestData.uses_test_data # Smart enough to not load again
79
74
  assert_equal 1, TestData.statistics.load_count
80
75
  ActiveRecord::Base.connection.rollback_transaction # Someone might do this!
81
- TestData.load # Still smart enough to not do this
76
+ TestData.uses_test_data # Still smart enough to not do this
82
77
  assert_equal 1, TestData.statistics.load_count
83
- TestData.rollback # after load savepoint should have been healed with subsequent load call
78
+ TestData.uses_test_data # after load savepoint should have been healed with subsequent load call
84
79
  assert_equal 15, Boop.count
85
80
 
86
81
  # Chaos: try rolling back outside the gem (one level of extraneous rollback) and verify truncate recovers
87
- TestData.rollback(:before_data_load)
82
+ TestData.uninitialize
88
83
  TestData.statistics.reset
89
84
  assert_equal 0, TestData.statistics.truncate_count
90
- TestData.load
91
- TestData.truncate
85
+ TestData.uses_test_data
86
+ TestData.uses_clean_slate
92
87
  assert_equal 1, TestData.statistics.truncate_count
93
- TestData.truncate
88
+ TestData.uses_clean_slate
94
89
  assert_equal 1, TestData.statistics.truncate_count
95
90
  ActiveRecord::Base.connection.rollback_transaction # Someone might do this!
96
- TestData.truncate # Will recover, not take the bait
91
+ TestData.uses_clean_slate # Will recover, not take the bait
97
92
  assert_equal 1, TestData.statistics.truncate_count
98
- TestData.rollback(:after_data_truncate) # after truncate savepoint should have been healed with subsequent truncate call
93
+ TestData.uses_clean_slate # after truncate savepoint should have been healed with subsequent truncate call
99
94
  assert_equal 0, Boop.count
100
- TestData.rollback
95
+ TestData.uses_test_data
101
96
  assert_equal 15, Boop.count
102
97
 
103
98
  # Chaos: load data then call rollback two times and ensure we're still in a good spot
104
- TestData.rollback(:before_data_load)
99
+ TestData.uninitialize
105
100
  TestData.statistics.reset
106
- TestData.load
101
+ TestData.uses_test_data
107
102
  assert_equal 15, Boop.count
108
103
  2.times do # Two rollbacks means we're back at before_data_load
109
104
  ActiveRecord::Base.connection.rollback_transaction
110
105
  end
111
106
  assert_equal 0, Boop.count
112
- TestData.load # It should successfully load again a second time
107
+ TestData.uses_test_data # It should successfully load again a second time
113
108
  assert_equal 15, Boop.count
114
109
  assert_equal 2, TestData.statistics.load_count
115
110
 
116
111
  # Chaos: truncate data then call rollback two times and ensure we're still in a good spot
117
- TestData.rollback(:before_data_load)
112
+ TestData.uninitialize
118
113
  TestData.statistics.reset
119
- TestData.truncate # will warn-and-load and then truncate
114
+ TestData.uses_clean_slate # will warn-and-load and then truncate
120
115
  assert_equal 0, Boop.count
121
116
  2.times do # Two rollbacks means data is loaded but after_data_load savepoint has been lost
122
117
  ActiveRecord::Base.connection.rollback_transaction
@@ -124,14 +119,14 @@ class LoadRollbackTruncateTest < ActiveSupport::TestCase
124
119
  assert_equal 15, Boop.count
125
120
  assert_equal 1, TestData.statistics.load_count
126
121
  assert_equal 1, TestData.statistics.truncate_count
127
- TestData.truncate # should restore the lost after_data_load savepoint and re-truncate
122
+ TestData.uses_clean_slate # should restore the lost after_data_load savepoint and re-truncate
128
123
  3.times do # Three rollbacks means we are at before_data_load again
129
124
  ActiveRecord::Base.connection.rollback_transaction
130
125
  end
131
126
  assert_equal 0, Boop.count
132
- TestData.load
127
+ TestData.uses_test_data
133
128
  assert_equal 15, Boop.count
134
- TestData.truncate
129
+ TestData.uses_clean_slate
135
130
  assert_equal 0, Boop.count
136
131
  assert_equal 3, TestData.statistics.truncate_count
137
132
  assert_equal 2, TestData.statistics.load_count
@@ -140,17 +135,15 @@ class LoadRollbackTruncateTest < ActiveSupport::TestCase
140
135
  def test_suite_runs_different_tests_in_whatever_order
141
136
  # Imagine a test-datay test runs
142
137
  test_data_using_test = -> do
143
- TestData.load # before each
138
+ TestData.uses_test_data # before each
144
139
  Boop.create!
145
140
  assert_equal 16, Boop.count
146
- TestData.rollback # after each
147
141
  end
148
142
 
149
143
  test_data_avoiding_test = -> do
150
- TestData.truncate # before each
144
+ TestData.uses_clean_slate # before each
151
145
  Boop.create!
152
146
  assert_equal 1, Boop.count
153
- TestData.rollback(:after_data_truncate) # after each
154
147
  end
155
148
 
156
149
  # Run the tests separately:
@@ -170,23 +163,25 @@ class LoadRollbackTruncateTest < ActiveSupport::TestCase
170
163
  # In the interest of behaving similarly to .load, rollback in case the
171
164
  # previous test doesn't have an after_each as you might hope/expect
172
165
  3.times do
173
- TestData.truncate
166
+ TestData.uses_clean_slate
174
167
  Boop.create!
175
168
  assert_equal 1, Boop.count
176
169
  end
177
170
  end
178
171
 
179
172
  def test_other_rollbacks_mess_with_transaction_state_will_debug_you
180
- TestData.load
173
+ TestData.uninitialize
174
+ TestData.statistics.reset
175
+ TestData.uses_test_data
181
176
  ActiveRecord::Base.connection.rollback_transaction # data loaded, after_data_load save point destroyed
182
- TestData.load
177
+ TestData.uses_test_data
183
178
  assert_equal :debug, @last_log.level # debug only b/c rails fixtures will do this on every after_each if enabled
184
179
  assert_match "Recreating the :after_data_load save point", @last_log.message
185
180
  assert_equal 1, TestData.statistics.load_count
186
181
 
187
- TestData.truncate
182
+ TestData.uses_clean_slate
188
183
  ActiveRecord::Base.connection.rollback_transaction # data loaded, after_data_truncate save point destroyed
189
- TestData.truncate
184
+ TestData.uses_clean_slate
190
185
  assert_equal :debug, @last_log.level # debug only b/c rails fixtures will do this on every after_each if enabled
191
186
  assert_match "Recreating the :after_data_truncate save point", @last_log.message
192
187
  assert_equal 1, TestData.statistics.load_count
@@ -1,29 +1,19 @@
1
1
  require "test_helper"
2
2
 
3
3
  class ModeSwitchingTestCase < ActiveSupport::TestCase
4
+ self.use_transactional_tests = false
5
+
4
6
  def self.test_data_mode(mode)
5
7
  if mode == :factory_bot
6
8
  require "factory_bot_rails"
7
9
  include FactoryBot::Syntax::Methods
8
10
 
9
11
  setup do
10
- TestData.rollback(:before_data_load)
11
- ActiveRecord::Base.connection.begin_transaction(joinable: false, _lazy: false)
12
- end
13
-
14
- teardown do
15
- ActiveRecord::Base.connection.rollback_transaction
12
+ TestData.uses_clean_slate
16
13
  end
17
-
18
14
  elsif mode == :test_data
19
- self.use_transactional_tests = false
20
-
21
15
  setup do
22
- TestData.load
23
- end
24
-
25
- teardown do
26
- TestData.rollback
16
+ TestData.uses_test_data
27
17
  end
28
18
  end
29
19
  end
@@ -6,11 +6,7 @@ class ParallelizedTransactionalFixturefullTestCase < ActiveSupport::TestCase
6
6
  fixtures :all
7
7
 
8
8
  setup do
9
- TestData.load
10
- end
11
-
12
- teardown do
13
- TestData.rollback
9
+ TestData.uses_test_data
14
10
  end
15
11
  end
16
12
 
@@ -5,11 +5,7 @@ class ParallelizedNonTransactionalFixturelessTestCase < ActiveSupport::TestCase
5
5
  self.use_transactional_tests = false
6
6
 
7
7
  setup do
8
- TestData.load
9
- end
10
-
11
- teardown do
12
- TestData.rollback
8
+ TestData.uses_test_data
13
9
  end
14
10
  end
15
11
 
@@ -3,8 +3,8 @@ require "test_helper"
3
3
  class FixturesUsingTest < ActiveSupport::TestCase
4
4
  def test_tries_to_load_rails_fixtures_with_test_data
5
5
  error = assert_raises(TestData::Error) do
6
- TestData.load_rails_fixtures(self)
6
+ TestData.uses_rails_fixtures(self)
7
7
  end
8
- assert_match "'TestData.load_rails_fixtures' depends on Rails' default fixture-loading behavior being disabled by calling 'TestData.prevent_rails_fixtures_from_loading_automatically!' as early as possible (e.g. near the top of your test_helper.rb), but it looks like it was never called", error.message
8
+ assert_match "'TestData.uses_rails_fixtures(self)' depends on Rails' default fixture-loading behavior being disabled by calling 'TestData.prevent_rails_fixtures_from_loading_automatically!' as early as possible (e.g. near the top of your test_helper.rb), but it looks like it was never called", error.message
9
9
  end
10
10
  end
@@ -6,26 +6,23 @@ class FixtureFreeTestData < ActiveSupport::TestCase
6
6
  fixtures :boops # why not
7
7
 
8
8
  setup do
9
- TestData.load
9
+ TestData.uses_test_data
10
10
  end
11
11
 
12
12
  def test_has_no_fixture_boops
13
13
  assert_equal 15, Boop.count
14
14
  end
15
-
16
- teardown do
17
- TestData.rollback
18
- end
19
15
  end
20
16
 
21
17
  class FixturesUsingTest < ActiveSupport::TestCase
22
18
  fixtures :boops
23
19
 
24
20
  setup do
25
- TestData.load_rails_fixtures(self)
21
+ TestData.uses_rails_fixtures(self)
26
22
  end
27
23
 
28
24
  def test_has_fixture_boops
25
+ assert boops(:boop_1).persisted?
29
26
  assert_equal 2, Boop.count
30
27
  end
31
28
 
@@ -34,29 +31,25 @@ class FixturesUsingTest < ActiveSupport::TestCase
34
31
  end
35
32
 
36
33
  def test_even_explicitly_loading_test_data_will_truncate_and_then_load_fixtures
37
- TestData.load
38
- TestData.load_rails_fixtures(self)
34
+ TestData.uses_test_data
35
+ TestData.uses_rails_fixtures(self)
39
36
 
40
37
  assert_equal 2, Boop.count
41
38
  end
42
39
 
43
40
  def test_load_and_rollback_leaves_them_as_is
44
41
  boop = Boop.first
45
- original_created_at_time = boop.created_at
46
- a_year_ago = 1.year.ago
42
+ original_created_on = boop.created_at.to_date
43
+ a_year_ago = 1.year.ago.to_date
47
44
 
48
45
  boop.update!(created_at: a_year_ago)
49
46
 
50
- assert_equal Boop.find(boop.id).created_at, a_year_ago
47
+ assert_equal Boop.find(boop.id).created_at.to_date, a_year_ago
51
48
 
52
- # Now after rollback
53
- TestData.rollback(:after_load_rails_fixtures)
49
+ # Now trigger a rollback to the fixtures point
50
+ TestData.uses_rails_fixtures(self)
54
51
 
55
- assert_equal Boop.find(boop.id).created_at, original_created_at_time
56
- end
57
-
58
- teardown do
59
- TestData.rollback(:after_load_rails_fixtures)
52
+ assert_equal Boop.find(boop.id).created_at.to_date, original_created_on
60
53
  end
61
54
  end
62
55
 
@@ -65,35 +58,29 @@ class SomeFixturesAndSomeTestDataInOneClassTest < ActiveSupport::TestCase
65
58
  fixtures :all
66
59
 
67
60
  def test_fixtures_work
68
- TestData.load_rails_fixtures(self)
61
+ TestData.uses_rails_fixtures(self)
69
62
 
70
63
  assert_equal Date.civil(2020, 1, 1), boops(:boop_1).updated_at.to_date
71
64
  assert_equal "Levi", pants(:pant_1).brand
72
-
73
- TestData.rollback(:after_load_rails_fixtures)
74
65
  end
75
66
 
76
67
  def test_that_rewinds_to_test_data
77
- TestData.load
68
+ TestData.uses_test_data
78
69
 
79
70
  assert_equal 15, Boop.count
80
-
81
- TestData.rollback
82
71
  end
83
72
 
84
73
  def test_that_rewinds_to_the_very_start
85
- TestData.rollback(:before_data_load)
74
+ TestData.uninitialize
86
75
 
87
76
  assert_equal 0, Boop.count
88
77
  end
89
78
 
90
79
  def test_fixtures_get_reloaded_because_cache_is_cleared
91
- TestData.load_rails_fixtures(self)
80
+ TestData.uses_rails_fixtures(self)
92
81
 
93
82
  assert_equal Date.civil(2019, 1, 1), boops(:boop_2).updated_at.to_date
94
83
  assert_equal "Wrangler", pants(:pant_2).brand
95
-
96
- TestData.rollback(:after_load_rails_fixtures)
97
84
  end
98
85
  end
99
86
 
@@ -101,11 +88,7 @@ class PantsFixturesTest < ActiveSupport::TestCase
101
88
  fixtures :pants
102
89
 
103
90
  setup do
104
- TestData.load_rails_fixtures(self)
105
- end
106
-
107
- teardown do
108
- TestData.rollback(:after_load_rails_fixtures)
91
+ TestData.uses_rails_fixtures(self)
109
92
  end
110
93
 
111
94
  def test_has_fixture_pants
@@ -120,8 +103,8 @@ end
120
103
  class FixtureTestPassingTheWrongThingTest < ActiveSupport::TestCase
121
104
  def test_doing_it_wrong
122
105
  error = assert_raises(TestData::Error) do
123
- TestData.load_rails_fixtures(ActiveRecord::Base)
106
+ TestData.uses_rails_fixtures(ActiveRecord::Base)
124
107
  end
125
- assert_match "'TestData.load_rails_fixtures' must be passed a test instance that has had ActiveRecord::TestFixtures mixed-in (e.g. `TestData.load_rails_fixtures(self)` in an ActiveSupport::TestCase `setup` block), but the provided argument does not respond to 'setup_fixtures'", error.message
108
+ assert_match "'TestData.uses_rails_fixtures(self)' must be passed a test instance that has had ActiveRecord::TestFixtures mixed-in (e.g. `TestData.uses_rails_fixtures(self)` in an ActiveSupport::TestCase `setup` block), but the provided argument does not respond to 'setup_fixtures'", error.message
126
109
  end
127
110
  end