structuring your RSpec project

it is an established convention to put all your rails tests or spec in the test/spec folder. even jasmine javascript files go in spec/javascripts… seriously, wtf?

cucumber features on the other hand go in the features folder… so?

while i don’t like cucumber (because of the additional complexity that comes with gherkin), i like the idea that they think about features as something different.

when writing acceptance tests i put them in the acceptance folder and have a different spec_helper file (usually called acceptance_spec_helper.rb as RSpec runners get confused with multiple spec_helper-files).

acceptance tests and normal rails tests have orthogonal requirements that should be handled in using different setups!

i like to have use_transactional_fixtures and random test execution turned on for regular Rails tests because it’s super fast and each spec should be independent of other tests.

it’s a different thing when writing acceptance specifications with capybara and a real browser that cover a user-session on a separate rails process and runs arbitrary actions against the server, executing JavaScript code within that context.

those acceptance tests have a basic problem when it comes to database queries. changes in one process/thread might not be seen in another one because of transactional visibility. this is often times hard to debug and mind-boggling. there are some “hacks” to get rid of this problem by sharing the same database connection, but they introduce other problems like race conditions.

long story short, i like to turn use_transactional_fixtures of and use fixtures (or hard-coded factory data) for running acceptance tests, as this fits more into the idea of acceptance tests. if you combine this approach with state-full page-objects, than you can write pretty readable tests like LoginPage.new.login(:bob).

I like to run DatabaseCleaner between each group of specs and recreate the fixtures, so they are fresh for each capybara spec file.
This setup comes pretty close to how cucumber does it, without all the cucumber-world craziness.

Some benefits that come with this approach:

  • faster spec runs for both suites
  • easy to separate out suites for CI
  • great for coverage reports
  • simple spec_helpers
  • separation of concerns via custom test modules

See the example configurations for more details.

Published by

phoet

I am a professional Software Developer from Hamburg, Germany.