140 Testing basics [3.5d]

Updated . Posted . Visible to the public.

Automated tests are how we keep a low defect rate without a QA department. This lesson covers why we test, the difference between unit and end-to-end tests, and the basics of RSpec and Capybara.

Important

Work on this lesson in teacher mode.

Learning goals

  • You can explain why we test: fewer defects without a QA department, freedom to change code, frequent deploys, no feature lost by accident.
  • You can explain the difference between unit tests and end-to-end tests, with the strengths and costs of each, and why we rarely test controllers or views in isolation.
  • You can decide which tests a change needs: an end-to-end test for the happy path, unit tests for the edge cases.
  • You can write unit tests with RSpec, structured by the behavior under test.
  • You can write end-to-end tests that drive the application through a browser, using RSpec feature specs with Capybara.
  • You can run a whole suite or a single example, read a failure and find its cause.
  • You can explain "test the behavior, not the implementation" and spot a test that is coupled to the implementation.
  • You can name the costs of testing and argue against testing too much.
  • You recognize the legacy should syntax in older specs.

Resources

Read what's new to you, skim what's familiar, skip what you already master. Stop when you can meet the learning goals.

Your agent can also generate an overview, a tutorial or an explanation for anything here, tailored to what you already know. Just ask.

One word on names: most sources today say system specs where we say feature specs. Both use the same Capybara DSL; we write type: :feature specs, and everything you read about system specs applies.

Why and what to test

RSpec and Capybara

Other formats

Your MovieDB already comes with working RSpec examples.

Exercises

Play with existing tests

Pick one of the sample apps.

  • Run one unit spec file and one feature spec file. They should pass.
  • Find an RSpec unit test and break an expectation. See what happens when you re-run the test.
  • Find an RSpec feature test and break an expectation. See what happens when you re-run the test.

Your first E2E feature

  • Write a feature test for CRUDing movies in your MovieDB application.
  • Use Capybara to talk to the simulated browser.

Unit vs. Feature testing

Add the following feature to MovieDB:

  • Above the movies list is a text field and a button "Search"
  • When the user enters text into the text field and hits "Search", the movies index is filtered to only contain matching movies

Some hints for the implementation:

  • Your Movie model should gain a class method Movie.search(query) or even better a scope method you can apply to the scope in the controller. Why should this not be an instance method?
  • You can implement the search in either SQL or Ruby
  • form_with model: is not helpful for the search form above the index. Why is that so? What can you use instead?
  • Add a custom route /movies/search to your routes, and map it to a new #search action in MoviesController
  • Try to reuse some of the existing private methods for the implementation of #search
  • When rendering search results, try to reuse the existing index views, or at least large parts of its.

Now add specs for both the new method Movie.search() and the new UI.

Follow the advice from the "Testing" chapter from Growing Rails Applications in Practice Show archive.org snapshot :

  • RSpec feature specs for the most common "happy path"
  • RSpec unit tests for all the edge cases (like case insensitivity)

From now on

When doing coding exercises in future cards, always deliver tests together with your implementation.

Profile picture of Henning Koch
Henning Koch
Last edit
Dennis Schreiner
License
Source code in this card is licensed under the MIT License.
Posted by Henning Koch to makandra Curriculum (2015-07-07 15:13)