Integration Testing with Capybara
Practicing with Capybara
Let’s put these techniques to work!
Setup
Fetch the Starter Code
Use the Blogger sample application to complete the exercises in this section. See the Setup Instructions for help.
Dependencies
Open the Gemfile
and observe that capybara
already exists in the development
dependencies group.
If you are working on Linux or Windows, you can uncomment the file change detection and notification gems used by guard, and rerun bundle
.
Running
Run bundle exec rake
and all the existing tests should be passing. Then try running guard
to automatically watch your files for changes.
Open a second terminal, start a server (with rails server
), and load http://127.0.0.1:3000/ in your browser.
Fabricators
If you’ve completed the Fabricators tutorial, then spec/fabricators
is already setup with Article fabricators. We can then use them like this in our examples:
1 2 |
|
Setup for Integration Tests
Look in the spec
folder and you’ll see existing models
and fabricators
folders. Let’s create a new folder spec/integration
where we’ll store our new examples.
Writing Examples
We’re ready to start testing! Create a file spec/integration/article_views_spec.rb
, starting with this code:
1 2 3 4 5 6 |
|
The require
lines load up our existing RSpec helper file and the Capybara library’s RSpec integration. Your guard
should notice the new file, run it, and the existing tests should still be passing.
A First Example
Let’s first setup some sample data. Create a before(:all)
block like this:
1 2 3 4 5 6 7 8 9 |
|
Add the Example
Let’s check that the index page lists each of the article titles:
1 2 3 4 5 6 |
|
Run the example and it should pass. We have no idea if it passed for the right reason, though. Hop over to the /app/views/articles/index.html.erb
and change
1
|
|
to this:
1
|
|
Now run the example and it should fail because the index page is no longer showing the article titles.
Undo the change to index.html.erb
and re-run the example. Everything should be green.
Being More Specific
The have_content
matcher has a wide scope: it just checks that the words appear somewhere on the page. Let’s get a little more specific.
First, let’s sabotage that index.html.erb
again, changing the link line to just output the title:
1
|
|
Run your existing example and it should still pass.
Now write a second example that makes sure each title is a link by using the have_link
matcher. Run the example and it should fail, then reinstate the line of the index
template, run the example, and it should go green.
Refactoring our Examples
Both our examples’ names end in "on the index"
and they both start by visiting the same page. This shows that we need to extract a nested context. Refactor your examples (which you can do since your tests are green) so they look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Run your examples and they should pass.
Additional Parameters
Now sabotage the link in index.html.erb
to point to just "/"
. Run your examples and they’ll still pass.
You’ve used have_link
and know there is a link with the text of the article title, but you don’t know if that link points to the right place.
Use the :href
option to check that the link points to the article’s show
page. As a reminder, the API looks like this:
1
|
|
A JavaScript Sample
For the sake of an example, let’s dynamically capitalize the "All Articles" heading on the index page using JavaScript.
First, we need to write an example and tell it to use the current JavaScript engine. It’ll default to Selenium, but go back to the Capybara-Webkit section to set that up if you prefer.
The structure of the example will be:
1 2 3 |
|
Run that example and it will fail. You’ll notice that, even if you are using the headless webkit, that example slows the execution down by a few seconds.
Then open the articles index.html.erb
and replace the title element with this snippet:
1 2 3 |
|
View it in your browser and you’ll see the title has been capitalized. More importantly, run the examples and you’ll see they now pass, proving that they’re using the JavaScript engine!
Group Practice
So you’ve taken a tour of the features available, let’s put them into practice. Together let’s write examples that demonstrate these behaviors:
- When on the index page
- clicking the link for an article takes me to the show page for that article
- there is a link with the DOM ID
"new_article"
- clicking on the new link takes me to the new article form
- When on the new article form
- submitting the form with no data is rejected because of validations
- when I fill in the form with valid data and submit the form, I see the show page and it has that same data
Individual Practice
These exercises should require little or no modification to the underlying Rails code. You should comment out or sabotage sections of the existing Rails code to make sure the test fails, then bring it back to make the test pass.
- When on the article show page
- The title is displayed in H1 tags
- There is an link that reads "edit"
- When I click the edit link I go to the edit form
- Clicking the delete link should take me to the index page and the article should not appear. You’ll need to click "OK" on the alert!
- When on the edit form
- Making no changes then clicking submit should take me to the show page for that article
- Removing the title and clicking submit should keep me on the edit form
- Making a change to the title and clicking save should go to the show and have the new title
- Changing the title so it duplicates another article should prevent saving
Extensions
These exercises are a little trickier and may require modifying the underlying Rails application:
- When on the article show page
- it should display each of the comments associated with the article
- it should have a form for entering in a new comment
- when I click submit without filling out the comment form, it should display the article show page without a new comment added
- when I fill in the comment form with valid data and click submit, it should display the article show page and the comment should be there
Harder Extensions
These may include adding significant functionality to the Rails application itself or the Fabricators:
- When on the article show page
- each comment should have a "delete" link
- clicking the delete link for a comment should remove only that comment and bring us back to the show page
- when there is a single comment, the heading should say "1 Comment"
- when there are multiple (n, where n is an integer) comments, the heading should say "n Comments"
- When on the articles index page
- Clicking a tag should show only articles with that tag
- A tag should not appear in the list if it has no associated articles