test_data 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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