This article is in a short series about testing your website with Selenium and SpecFlow:
The combination of Selenium and SpecFlow lets you do two useful things:
- Test your website in the way that a user would
- Base these tests on acceptance criteria that you probably have already lying around, e.g. in the user stories that went into the website’s creation.
I’ve written about SpecFlow before, in the context of testing a web API e.g. a REST API. Unlike when testing a web API, a web site needs special things to happen in order to test it – buttons need clicking, text needs entering etc. Therefore, SpecFlow needs Selenium to handle the low-level web stuff. Selenium is available for several platforms. SpecFlow is the C# implementation of Cucumber; there are Cucumber implementations for several platforms.
The big picture of the world is as below – you will need to write the bits in blue (as well as the web site under test, which I’m assuming is already written). I’ll explain the parts shortly.
The job of the various parts is as follows, working upwards from the bottom right.
|Web site under test||This is what you want to be right!|
|Web browser instance||This is a normal instance of Firefox, Chrome etc, that will investigate your web site. It is created and controlled by Selenium on behalf of your test.|
|Selenium||Selenium is the bridge between your test code and the web browser. It turns your test code into a robot that is using the browser to test your site. It allows your test code to send instructions to the browser, e.g. go to this URL, click on this element on the screen, etc. and to read data from the browser e.g. the text inside this div.|
|Page object||You write one of these per page in the web site or per subsection of a page if that makes more sense. This is the only thing that contains calls to Selenium and low-level details about the page, like the id that refers to a particular field. Its job is to present the page to the rest of the test in business terms, e.g. a method called Login(username, password) rather than details of two text input fields and a button.|
|SpecFlow step definition||This has the assertions that will either pass or fail, and so make a test scenario pass or fail. It also contains calls to the page objects and other code (left out of the diagram for clarity) to do the actual work of the test – logging in, adding a product to a basket, reading the account balance etc.|
|SpecFlow feature file||This has the statement of what each test scenario actually is, in the standard Given / When / Then form of a user story. Hidden SpecFlow plumbing will match each line of a test scenario against a method in a SpecFlow step definition and then execute it.|
You don’t have to write page objects, but it will make your life easier and so is worth doing. Without page objects, the details about individual page elements spill upwards into step definitions. This makes the step definitions harder to think about, harder to read, and more brittle to changes in the web page.
For instance, if the id for a user name field changed from uname to username, then a page object for that page would absorb the change (in just that one place) and still present the same business-y interface to the rest of the test code, e.g. a method called Login. Without a page object, all step definitions that used the user name field would need to change.
Once you’ve got all this together, you can write a test scenario like this:
Given I am logged in as a gold tier user
When I go to the home page
Then I can get a free audio book download
When you click Go on the test, an instance of a browser will appear, go to the login page, log in as a particular user, go to the home page, download the audio book and then disappear, and your test runner will say that the test has passed.