So you finally decided you want to add automated tests to your web applications. That's great, because automated tests will increase the quality of your product and hopefully find regressions before your users will.
Below is a really simple setup you can start using today on your development machine and improve as your tests grow.
An automated test is a script that will automatically open a browser, perform some tasks in the web page and report a result. My setup uses the following tools:
- Browser: Chrome
- Browser Testing Framework: Selenium
- Testing API: Capybara
- Programming Language: Ruby
- Ruby Testing Framework: RSpec
We'll use Chrome as it's a very popular browser your users are probably using. On top of that we'll use Selenium. Selenium is an automated testing framework which is capable of "controlling" a browser as if a person would be operating it. Selenium can tell the browser to visit a web page, click anywhere on the page, resize the window, wait for some element to appear or hide and so on. Selenium can connect and control many different browsers and has bindings to many programming languages.
While one can call selenium directly, I find it more convenient to use a wrapper that provides some extra functionality on top of selenium. I really like Capybara as it yields a nicer API and was a bit easier for me to set up. Capybara is a ruby library which wraps selenium to provide a nicer developer experience.
Capybara is written in ruby so we'll have to use that as our programming langauge. For automated testing I find ruby easy enough to learn as we go.
Finally RSpec is a BDD framework that provides a structure for our test code. RSpec will be the tool to actually run the code and provide a report of what worked and what didn't.
The entire code for this article is available on github here:
A First Test
Let's start simple: I'd like to check that the word 'DuckDuckGo' appears on the homepage of https://duckduckgo.com. Using Capybara this is the relevant test code (from the file
visit 'https://www.duckduckgo.com' expect(page).to have_text('DuckDuckGo')
Ignoring the weird syntax (one gets used to it), this is a very readable description of what we're doing: Visiting a page and expecting to find a specific text inside.
As we're using RSpec to run our tests we'll need to insert the above into the RSpec structure so the full test file looks like this:
require_relative '../init' RSpec.describe 'Search Page', type: :feature do it 'includes the word DuckDuckGo' do visit 'https://www.duckduckgo.com' expect(page).to have_text('DuckDuckGo') end end
A describe block represents a feature you're testing, and the it blocks below each represent a certain aspect of that feature. It's ok to write multiple describe blocks in the same file, and multiple it blocks in the same describe. You can also nest describe blocks.
Running The First Test
To run the test you'll first need to install some dependencies (which is only done once):
- Download and install ruby (link: https://rubyinstaller.org/downloads/)
gem install bundlerto install bundler gem
- Download and extract test project files (link: ynonp/capybara-rspec-demo.zip)
cmdchange to extracted project directory and type
If all went well you now have everything installed and set up to run the tests. From the same
cmd window type:
A new chrome window should be opened and should automatically visit duckduckgo.com. Later in the cmd you'll get the output:
. Finished in 20.35 seconds (files took 0.39303 seconds to load) 1 example, 0 failures
Which means test ran and succeeded.
A Second (and third) Test
Let's proceed with two more tests. I'll stay with duckduckgo for this post. Visiting the site you can see that writing text in the search box shows an autocomplete popup. Let's write a test to verify the autocomplete windows indeed appears.
To do that we need some way to identify that element. Any CSS selector will work here. I like to use Chrome's copy selector feature which provides a CSS selector to any element on the page.
Using that feature I found the selector to the automcomplete window is
#search_form_homepage > div.search__autocomplete, and the selector to the main search box is
#search_form_input_homepage. We can use both in our test:
visit 'https://www.duckduckgo.com' fill_in 'search_form_input_homepage', with: 'a' assert_selector('#search_form_homepage > div.search__autocomplete')
Note the new method
fill_in which takes an input element ID and fills text in that element.
The complete test file now looks like this:
require_relative '../init' RSpec.describe 'Search Page', type: :feature do it 'has the word duckduckgo' do visit 'https://www.duckduckgo.com' expect(page).to have_text('DuckDuckGo') end it 'shows autocomplete window after we type in the search box' do visit 'https://www.duckduckgo.com' fill_in 'search_form_input_homepage', with: 'a' assert_selector('#search_form_homepage > div.search__autocomplete') end end
You can use
rspec from cmd again to run all the tests. Also it's sometimes useful to run only specific file or tests just to see they work. To do that in RSpec pass the file name and line number of the test. In our case:
Performs only the last test we typed.
Since we're already in the autocomplete window mood let's verify it's not there before typing words in the box. Here's the new it block:
it 'only shows autocomplete window AFTER user types stuff' do visit 'https://www.duckduckgo.com' assert_no_selector('#search_form_homepage > div.search__autocomplete') end
Some Next Steps
Writing capybara tests in the real world will require some more skills than presented here. I suggest learning them as you go, and here are some useful resources to help you along the way:
- Capybara documentation is a great place to find capabilities and examples of this library: http://www.rubydoc.info/github/jnicklas/capybara
- RSpec documentation is a great place to learn about the test structure, including how to run code before and after each test and other capabilities: http://rspec.info
- As your tests will grow, you'll want to wrap them in your own code to reduce duplication. Ruby is a great language and provides all the Object Oriented tools you need to do that. Ruby For Beginners is a good resource for that.
For small developer teams (or even freelance/single developers), automated testing is a crucial tool in writing high quality software. I hope you too will start using it for your own project.