I am building a Rails App (I am new to this, so forgive me if some of the wording is clumsy). I am trying to write tests (with RSpec) which draw and use data from the database, and I am having trouble writing the tests in a concise way.
Some of the tests (such as signing up a user, or creating content) seem to be best suited to having a fresh database, while some require a database populated fixtures.
At the moment I am using the database cleaner gem, with the following configuration:
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
DatabaseCleaner.strategy = :truncation end
# start the transaction strategy as examples are run
config.around(:each) do |example|
DatabaseCleaner.cleaning do
example.run
end
end
The reason I am using truncation
for both strategies is that I prefer to have the id
values completely refreshed between examples (so that if I create
in one test, and then create
in a second test, the second example should have id 1
rather than 2
). I am not sure what the various strategies mean exactly - I have found this question which appears to explain them in terms of SQL syntax, but I'm not very familiar with that so my understanding is still quite vague. I believe the database is
managed with PostgreSQL, but I rarely have to interact with it directly through that so I'm not particularly experienced.
So my database is completely dropped and constructed from scratch between every example - if I want a clean database then this is ideal, but if I want to simply load the fixtures then it can take a while to create all of the models. It feels like I should be able to have a 'cached' version of the fixtures, which I can load for those examples it's appropriate for. But I have no idea how to do this, if it is even possible. Is there a way?
Edit: Following a discussion in the comments, I suspect that I may want to remove Database Cleaner and use default Rails fixtures instead. I have tried this, and the only problem I'm having with it is the same as I had with the transaction
strategy described above. That is: when test-created records are rolled back, the id
is not rolled back, and this is awkward behaviour. If I create a user
for the purpose of running a test, it is convenient to refer to it just as User.find(1)
, which is impossible if the id
does not reset.
It might be that this is some kind of red flag, and I shouldn't be doing it (I am open to doing something else). I realise too that I could just say User.first
to get the same behaviour, and this might be better. I'm not sure what's appropriate.