Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing Practices #111

Closed
alex-handley opened this issue Feb 27, 2013 · 5 comments
Closed

Testing Practices #111

alex-handley opened this issue Feb 27, 2013 · 5 comments

Comments

@alex-handley
Copy link

I wanted to get your thoughts on testing in isolation and how to then do integration tests to test the isolated components together.

Currently I unit test controller and models etc but when creating integration tests to ensure these components are working correctly together, I am unsure how much testing needs to be done to ensure that the two components work correctly together?

@harlow
Copy link
Contributor

harlow commented Feb 28, 2013

Hi @alex-handley thanks for the question. Currently our go-to for integration testing is a combination of RSpec and Capybara. http://robots.thoughtbot.com/post/33771089985/rspec-integration-tests-with-capybara

When developing "outward in" we use the Capybara DSL to drive the web browser, and then jump down into unit tests when we need to create models, and test business logic. Once the unite tests are complete, we jump back up to the integration tests to make sure that all user interactions with the site are covered in the test suite.

@alex-handley
Copy link
Author

Thanks @harlow, I also do integration testing in the same way and it works for most CRUD actions but recently I have been working on some projects with actions that have a lot of logic in them for example a search that uses the elastic search engine. Would you retest all of individual components that make up this test e.g. faceting, pagination, filtering etc?

@harlow
Copy link
Contributor

harlow commented Feb 28, 2013

I have been working on some projects with actions that have a lot of logic in them

Typically its nice to take this logic out of the action if possible and create a class that you can unit test.

Then for the integration tests you could use fixture data to prime your test environment and then use Capybara to emulate a search, test the page contents for search results, pagination buttons, total pages, etc

@jferris
Copy link
Member

jferris commented Feb 28, 2013

How much to test from each perspective (isolated vs integrated) is a tough decision, and depends on the situation.

My general strategy is to start with an integration test for new UI, and continue implementing code based just on the integration tests until the integration test feels too detailed or the code feels too far away from the UI.

As an example, this would be my basic workflow for adding a new form:

  • Write a feature spec using RSpec and Capybara that fills out the form and looks for the result on the page.
  • Implement the view.
  • Add the happy path for the controller action.
  • Define the model class to fix missing constant errors.
  • Once model behavior (instance methods, validations, callbacks) are necessary, I write unit tests for those.

As you can see, I skipped writing unit tests for the controller or view here. On the other hand, I'll write a unit test instead of an integration test for a controller or view if the behavior branches based on a simple condition.

There are a few benefits and drawbacks you have keep in mind when deciding what perspective to take when adding a test:

  • Unit tests are better at improving the class design.
  • Integration tests are better at catching regressions and preventing bugs.
  • Unit tests are close to the code but far away from the user.
  • Integration tests occur from a user's perspective but are far away from the code they're testing.
  • Unit tests are fast and failures are generally clear.
  • Integration tests are slow and failures may not reveal the root problem.
  • Unit tests are precise and can easily test just one thing and it's easy to write just one unit test for each logical branch.
  • Integration tests are blunt and are likely to retest the same behavior over and over in order to get to the behavior you're actually trying to test.

I'd recommend going with your instincts and then listening to what your tests are telling you. If your tests are slow, write more unit tests. If you're catching bugs that slip past your unit tests, write more integration tests. Treat your test suite as a living, evolving thing, and rebalance your testing strategy as problems occur.

@jferris jferris closed this as completed Feb 28, 2013
@alex-handley
Copy link
Author

Thanks, that helped to clear things up!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants