Excluding certain records when doing database cleanup

21 views
Skip to first unread message
Message has been deleted

Uros Certic

unread,
Aug 20, 2018, 11:28:45 AM8/20/18
to rspec
Anyone knows if there is a way to use database_cleaner and clean test database after each test but keep only certain records?
I have some records that are reused in almost all tests and they need to be persisted.
Currently i'm setting them with factorybot in before(:all) block but it takes a lot of time and it would be good if they can be persisted and not removed with database cleaner

Jon Rowe

unread,
Aug 21, 2018, 5:50:40 AM8/21/18
to rs...@googlegroups.com
Hi Uros

This is generally considered “less than ideal” as it encourages shared state making your tests dependant on each other (e.g. if one of your tests deletes this seed data your other specs will fail regardless) if your data is “static” consider making it hard coded instead, or refactor your tests to not “always” need this data.

However if really want to do this consider switching to transactional tests (or cleaning), unfortunately this is not possible in integration testing environments with a real server ala puma or webrick due to thread / process separation. Transactional setup here will rollback any changes made by your individual tests allowing you to do setup in a `before(:suite)`. You can also exclude certain tables from database cleaners truncation if that helps?

Cheers
Jon Rowe
---------------------------

Uros Certic

unread,
Aug 21, 2018, 6:08:15 AM8/21/18
to rspec
Hi Jon, thanks for the info.

Problem is that functions that we are trying to write tests for have a lot of database calls for the records i mentioned above so just hardcoding them or mocking them is not gonna work. Now i know that this is not the best practise but code is old and refactoring it is currently not possible...so i'm trying to work on speeding up tests. Also i tried with excluding tables but it created some other issues in some tests.

My current spec config looks something like this...

 config.use_transactional_fixtures = true


 config
.before(:all) do
 
DatabaseCleaner.clean_with(:truncation)
 
end


 config
.before(:each) do
 
DatabaseCleaner.strategy = :transaction
 
end


 config
.before(:each) do
 
DatabaseCleaner.start
 
end


 config
.after(:each) do
 
DatabaseCleaner.clean
 
end

Not sure on logic behind this since it was not my setup but do you think this can be improved and for the problem above do you maybe have some other solution?

Cheers,
Uros

Jon Rowe

unread,
Aug 21, 2018, 6:23:10 AM8/21/18
to rs...@googlegroups.com
Hi Uros

When I said to hardcode them, I meant to do it in the application, if that data never changes then why is it in the database? If it does change then why isn’t it changing in your tests? If its something like a multi-tenant situation then why doesn’t each type of object just create its own tenant?

Unfortunately I suspect you are feeling the effect of having a large amount of coupled code so you are not going to be able to speed up these tests without uncoupling it so it doesn’t need such test data all the time.

The only further suggestion I have here is to remove the truncation cleanup calls, if you’re using transactional cleaning on tests you shouldn’t need the additional truncation ones.

Cheers
Jon Rowe
---------------------------

Uros Certic

unread,
Aug 21, 2018, 6:45:19 AM8/21/18
to rspec
Well it's a portal object and 99% of application functionalities rely on portal existing with its settings. Portal is changeable but it is not changed everywhere. My thought was that i always have that object in database and just  change portal settings in tests where it is needed since now i'm inserting it before every test. Updating it on some places and reseting it after is by my thought much better for performance than inserting it for each test.

Jon Rowe

unread,
Aug 22, 2018, 4:25:23 AM8/22/18
to rs...@googlegroups.com
If it behaves like a static object during tests but you need its values for settings I suggest refactoring code to need it injected, this will allow you to give either a “non persisted” real value, or a double with the same shape. This could even be memoized across the test suite. 

If everything is hanging off it relationally this becomes a problem but all this test pain is doing here is exposing the complications that have arisen from this pattern of design. God objects are convenient but they often cause growing pains such as you are experiencing!

I wish you luck :)

Jon Rowe
---------------------------
Reply all
Reply to author
Forward
0 new messages