I’m assuming you’re already up and running with your Cucumber setup and are ready to start! If you haven’t already set Cucumber up, you may want to go back to this page and follow the tutorial for your particular computer.
Done? OK, good.
The first thing we need to do is create our Cucumber environment file. Select File > Open and navigate to wherever your project folder is, highlight it and then click on Open. You will notice that the folder structure we just created is down the left hand side. Right click on ‘support’ and select ‘New File’. This will give us a blank file we can use, which will become our Cucumber environment file. Save this file as ‘env.rb’. The ‘.rb’ extension tells Sublime Text (and your computer) that this is a Ruby file. Sublime Text will now know which key words to highlight for you. You’ll see this in action now when we begin to write.
At the top of our file (which should still be blank) we need to first tell Cucumber which gems you will be using. You will write each one on a separate line, using the ‘require’ command. Type the following into your file:
require 'capybara' require 'capybara/cucumber' require 'selenium-webdriver'
You will notice that the colour changes depending on what you type. That’s syntax highlighting in action and it will make things a lot easier. Remember the gems we installed earier with Bundler? This is where we tell Cucumber that we want to use them, which we have just done.
For this tutorial, we will be using Capybara to interact with the websites we wish to test. You will have noticed that we have also installed Selenium Webdriver. We could use that directly if we wanted, but we would need to write lots of clever code to deal with things like waits, retries and timeouts. This is because Selenium can only do what we tell it to do. Let us say, for example, that on our website we have a button that needs to be pressed and that button makes another button appear.Let’s call them button A and button B. We might want Selenium to click button A and then click button B. Button B may take a few milliseconds to appear, though. This means that if we tell Selenium to click button A and then click button B, it will fail as button B won’t be there. We could tell Selenium to wait for a second before continuing, but what if it takes more than a second. What if, occasionally it takes three seconds. We don’t want to tell Selenium to wait for three seconds every time it does anything. We would add lots of unneccessary time to our test suite if most of the time things appear almost immediately. What we need is some code to tell Selenium to keep trying to find button B until it appears and, when it does, to click it. We will also need some code to tell Selenium to stop trying to find button B after a set period of time and to fail the test. Those are just a couple of examples of bits of code we’d need to write to successfully test a website. Fortunately for us, Caoybara has already been written and does all this for us, so we’ll be using it instead of using Selenium directly. What is also handy is that we can use different webdrivers too, if we want to, without having to rewrite our code. We just need to tell Capybara which webdriver to use. We can even do this on the fly and specify in our tests which webdriver we want. But we won’t worry about that right now.
Type (or copy & paste) the following into your env.rb file:
Capybara.run_server = false Capybara.app_host = "http://www.google.com" Capybara.default_driver = :selenium
With those commands, we’re telling Capybara a few things. First, we’re telling it not to bother spinning up a Rack server. Without wishing to go into too much detail, Capybara is designed to work very well with Ruby on Rails. If we were writing the website ourselves in Ruby on Rails and hosting it locally on our computers, then we’d want Capybara to spin up a Rack server for us. For this tutorial, we’ll be testing an external website, so we don’t need it. The second command is telling Capybara what our default website is. We’ll be using Google. Once we have this in place, we can use relative URLs to navigate to different webpages. This means we can just type in the second half of any URL we want and Capybara will add it to the app_host, in our case it will add it to ‘http://www.google.com/’ If we find ourselves wanting to go to a completely new URL, we can still do that. We just need to use the full path. More on that, later. The third command simply tells Capybara that we wish to use Selenium as our webdriver.
Now we’re ready to write our first Cucumber feature file.
Feature files are where we write our tests. Specifically, where we write the plain English descriptions of what we want to do. Cucumber is designed for describing behaviours. The concept of Behaviour Driven Development (BDD) is outside ths scope of this tutorial, but there are plenty of other blog posts that will help you. I’ll list a few at the end. For now, we’ll just be using a few simple steps, written in plain English. Once we have our steps, we will write our step definitions, which are where the clever stuff lies. Step definitions are blocks of code that are run whenever we call them. We call them with out steps in our feature file. Don’t worry if you don’t quite understand, yet. All will become clear. For now, all we need to do is concentrate on writing our feature file.
First, we need to create our feature file. Right click on your features folder (within Sublime Text) and select ‘New File’. Next, go to File> Save and save it as something with an extension of .feature. I’m going to call mine google.feature as we’ll be creating a simple test using http://www.google.com. Now we have saved our file, we will have some more syntax highlighting that will help us write our tests.
The first step is to define what our feature will do. We do that by writing the word
Feature: (with a capital ‘F’ and then a colon) at the top of our file. After the colon, we can write a sentence or a few lines about the feature we’re testing. I’m just going to write
Testing Google. It’s not a very good feature definition but it will do, as writing good tests is outside the scope of this article.
The next thing we need to do is define our first scenario. Similar to defining our feature definition, we simply need to write
Scenario: followed by a brief description of what we’ll be testing. I’m going to write
Testing Google search. Now we need to write our test steps. Let’s use the following:
Given I navigate to Google When I search for Capybara Then the Capybara Github page is displayed
Again, these aren’t the best steps I’ve ever written, but they cover the basics. There’s a
Given step that defines the state of the system beforehand, a
When step that defines a state change and a
Then step that defines the state of the system afterwards.
Once you’ve written (or copied) those, save your feature file and navigate to your project directory using your terminal (mine is in
~/code/cucumber_project). Once there, simply run cucumber by typing in
cucumber and hitting return. You might be wondering why we’re running the tests this early as there is nothing behind them. There are no step definitions. This is because Cucumber has a handy feature to help us write these step definitions.
Your output should be something like this:
You’ll see it’s telling us lots of information. It says that it has found one scenario (that’s undefined), that it consists of three steps (and out of those, there are three undefined) an that it ran in 0.062 seconds. At this stage though, by far the most useful feature is the automatic creation of our test steps:
Given(/^I navigate to Google$/) do pending # Write code here that turns the phrase above into concrete actions end When(/^I search for Capybara$/) do pending # Write code here that turns the phrase above into concrete actions end Then(/^the Capybara Github page is displayed$/) do pending # Write code here that turns the phrase above into concrete actions end
Sure, they’re not working yet, but they contain all the boiler plate code we need to make a quick start. Copy them to your clipboard. We’ll need them in a moment.
Now we have the basis of our step definitions (or step definition stubs), we can create a file to store them. Right click on step_definitions in Sublime Text and select New File. Then paste the definitions and select File > Save to save it as
google_steps.rb or something similar. The important thing is to have the
.rb extension as this will tell cucumber that it’s a ruby file and to load it up before running the tests.
You’ll notice that this line is in the middle of each step definition:
pending # Write code here that turns the phrase above into concrete actions
This is where we’ll write our code that will actually do stuff. Before we do though, run the tests again and see what happens. Your output should look something like this:
You’ll now see that Cucumber has recognised that the first step exists, but hasn’t been written fully yet (notice the TODO and pending keywords in the output). It also has not bothered to run the next two steps. What we need to do now is replace the
pending statement with proper code. Don’t worry. With the help of Capybara, it’s very easy.
Simply replace the pending statement with this code:
So your first step should look like this:
Given(/^I navigate to Google$/) do visit '/' end
Run Cucumber again and watch what happens. You should see a Firefox window appear, which should load the Google homepage, before shutting down. Your output should look something like this:
You’ll notice that the first step has turned green, meaning it has passed. We’re not actually checking anything in this step, so there’s not much that can go wrong, but that’s ok. Now we need to write the next step.
Here’s the code for our next step:
fill_in 'q', with: 'capybara'
Like before, replace the pending statement in the second step with that code, save it, then run Cucumber again. You should see it do the same as before, although this time it will search for capybara very quickly before closing. All we’re doing here is using Capybara’s built in
fill_in method that’s designed to fill in txt into text boxes. All we’re telling Capybara to do is fill in ‘q’ (which is the name of the search field in Google) with ‘Capybara’.
If you’re new to writing code, you may not be aware of the ‘red, green, refactor’ mantra, sometimes said as ‘make it work, then make it good’. This means that we should only concentrate on making our code work, initially. When it works, then we can go about cleaning it up and making it better. In this case, you may notice that our step has the text ‘Capybara’ in it and we’re duplicating it by ‘hard coding’ it into our step definition. There’s another coding principle that springs to mind, here: DRY (Don’t Repeat Yourself). What we’ll do now is a simple refactor of our code to remove this duplication and make our step able to cope with searching for different search terms.
The first thing we need to do is change the first line of our second step with this:
When(/^I search for (.*)$/) do |search_text|
You’ll notice that we’ve replaced the word
(.*). This is so we can use the step with many search terms. What the first line of any step actually is is a regular expression. The scope of regex is outside of this article, but basically it’s a way of identifying strings of text and matching them up with our steps. By replacing
(.*), we’re now telling our step definition to accept anything after the text ‘I search for ‘, to capture it and save it as the variable
search_text. We’ll be needing that variable in a moment.
The next stage is taking that variable and inserting it into our step definition’s code. This is very easy. We just need to reference it by it’s name, like so:
fill_in 'q', with: search_text
Your completed step should now look like this:
When(/^I search for (.*)$/) do |search_text| fill_in 'q', with: search_text end
Save it and run Cucumber again to make sure it still works. It does? Good.
The final step is to check that the Capybara homepage is displayed. This is what we need in our final step:
raise method to raise an exception (tell us something has gone wrong) unless it cannot find the content 'jnicklas/capybara · GitHub' on the page. You probably guessed that already, though. Ruby has been designed to be as readable as possible, which is one of the reasons it's so nice to work with. Save your file and run it again. You should see Firefox load, a capybara search conducted and then Firefox closed. However, unlike before, Capybara will have checked that the text we specified is found on the page. If successful, your output will look like this: But wait! We're not done! We may have a false positive. It's important to check our test actually works. What we can do now is ask Capybara to find something we know it won't and watch it fail. I'm going to search for this, instead:
fail 'Capybara GitHub page not found!' unless page.has_content? 'jnicklas/capybara · GitHub'
'jnicklas/capybara · GitHub false'
Save and run it again. Let's let's look at the output:
Great! It failed, as expected and our exception told us that the Capybara GitHub page could not be found. Now we know the test works, we can go back and change our code to what it was. Once you've done that, I suggest running the test one more time to check you haven't made any mistakes.
All passed? Perfect.
That's how easy it is to start with Cucumber. Sure our tests here aren't perfect. We could defector them a little more to make them even more reusable. We could also use Rspec for checking whether the Capybara GitHub page was found. That way we wouldn't need to define our own exception like we did. But these are all things we can do in the future.
Now you're up and running, why not go to the Capybara homepage yourself and see what other commands you can use. Then you can write some more tests!