What she said

Conditionally Switching off Transactional Fixtures

Rspec gives us the ability to use transactional fixtures:

1
config.use_transactional_fixtures = true

We like it because it makes the test fast by opening a database transaction at the beginning of a test and rolling it back at the end of it. Nothing gets written into database. But, this does not work with Capybara javascript tests (Such a long name, I’m going to call it selenium specs from now on just for simplicity sake and legacy reasons. And no, I don’t prefer selenium as a driver over Capybara-webkit. Quite the opposite.) because they use a separate server thread, which means the transaction is not visible to the client. So intuitively we wonder, is there a way to turn off transactional fixtures only for selenium specs? A quick googling suggests that one should simply turn off transactional fixtures and use database cleaner for all the tests. I go

no

I’d use database cleaner to truncate my tables after/before each selenium specs but definitely not for every non-selenium specs like model and controller spec. What about using database cleaner’s transaction strategy for those? I could… And more on that later. But hey if rspec can talk to active record to enable transactional fixtures directly why have someone else do it? So here it goes:

To use it, you need to put the js tag on feature(alias of describe) instead of the scenario(alias of it), because it is simply too late once you are in the space of a scenario. For the same reason, you can’t turn it off in a conditional before(:each) hook in spec helper.

*Credit: the above gist was derived from code written by Mike Mazur and I as a pair.

So I was pretty pleased with the above solution and I went ahead made the gist for my future self. But, then I asked myself again: what about database cleaner’s transaction strategy? How does it work differently from active record’s use_transactional_fixtures which rspec essentially use? After a bit of code reading, I realized the answer is… it isn’t any different. Here is how active record does it. Here is how database cleaner does it. Here is me trying to make sure I’m not crazy after reading what I read.

It’s a nice thing to figure out how to turn off transactional fixtures conditionally. But end of the day, it is not necessary. So yea, Interwebz is right – just turn off transactional fixtures all together and use database cleaner. Here is to my future self and anyone who ever wonders how to turn off transactional fixtures for selenium specs only:

Comments