Part 3. Creating our BDD test

Creating our BDD test

Introduction

In this section, we will finally begin coding a test. The test we will perform is simply navigating to https://about.google, clicking on the ‘Our Stories’ link and verifying that we are on the correct page and see the correct elements.

Any more actions and the test would start to become less atomic. For example, if we wanted to click another button on the ‘Our Stories’ page and assert we see the correct thing based on the button that was clicked on, that would be a different test and probably one where we could skip the step where we navigate from the home page to the ‘Our Stories’ page.

Anyway, more on best practices at a later date when I start adding some articles.

Let’s begin πŸ™‚

Creating the Cucumber Scenario

When creating our BDD scenarios, we want to keep them simple and write them in a declarative style, sticking simply to the business logic, rather than writing them in an imperative style.Β  A great article on this can be found atΒ http://itsadeliverything.com/declarative-vs-imperative-gherkin-scenarios-for-cucumber.

  1. In Visual Studio Code, open up the ‘google-about.feature’ file and add the following test scenario, with the whole thing looking like below…

    Currently all these steps will be undefined and not have any step definitions / glue. So let’s add undefined step definitions / skeletons for them next.

Creating the Undefined Step Definitions

If we now run the following command, the console will output the pending step definitions for us…

  1. Open up the ‘google-about.steps.ts’ file and paste in the pending step definitions, also remembering to add in any necessary imports for the Given, When and Then’s, with the whole thing looking similar to below…
  2. Next, we can replace the function()’s with arrow functions :), like below…

Defining the Step Definitions

‘Given a Google fan is on {string}’

  1. Edit the ‘Given’ step definition so it looks like below, with the correct ‘browser’ import also being added from ‘protractor’, like below (we have also renamed the string variable to something more meaningful)…

‘When they navigate to ‘{string}’

For this step definition, we will be defining it by calling a function on our base-page object which performs the navigation page action for us. So first, let’s add the function for that page action πŸ™‚

  1. Open up the ‘base-page.ts’ file and edit it initially to simply be an exportable class with an empty constructor…

    If we go to ‘https://about.google’ in our browser (e.g. Chrome) and we inspect the ‘Our stories’ element, we can see the following…

    From this we can determine that one way the element can be located is via its ‘title’ attribute, so we could find the element by using css selector
  2. Let’s add a generic element finder for the navigation links…
  3. Next, let’s set the locator for the generic ‘navLink’ element in the constructor…
  4. If we now go back to our step definition, we can add the following to instantiate the base page object and click the navLink we added, like so…

‘Then they see information about Google’s background story’

For this step definition, we will be wanting to assert that we are indeed on the ‘Our stories’ page. To keep our test atomic but also have a decent level of verification, we will include two assertions, one for verifying the url we are on and the other for verifying we the ‘View all stories’ button at the bottom of the page is displayed.

Let’s begin πŸ™‚

  1. First, in Visual Studio Code, let’s right-click the ‘pages’ folder and create a new file called ‘our-stories-page.ts’
  2. Next, let’s open that file up and create an exportable class that inherits from the base page and contains a constructor with a super() function setting the navLink string to ‘Our stories’, like so…
  3. Now, let’s add an element finder for the ‘View all stories’ button at the bottom of the ‘Our stories’ page…

    If we now inspect the ‘View all stories’ element at the bottom of the ‘Our stories’ page in the browser, we can see the following…
  4. From the above, one way we could locate the element is by partialLinkText and checking the element contains some specific link text, so let’s find the element in our constructor…
  5. Next, let’s go back to the step definition file and add the assertions to check both the URL and the ‘View all stories’ element is present, remembering to also instantiate the ‘our-stories-page’ class and import ‘chai’…

Making things execute in order

By default, the WebDriverJS and Protractor API’s are asynchronous.

For each function that is called (e.g. from imported ‘protractor’ libraries), a promise is made that can have one of 3 states: ‘pending’, ‘accepted’ or ‘rejected’.

Regardless of the state of the promise, Javascript will by default carry on to the next line of code and execute that.

In traditional OOP languages like Java, the next line of code would only be executed after a so-called promise of the previous line has an ‘accepted’ state, making it ‘synchronous’.

Because of this, we should make our step definition functions asynchronous with the ‘async’ keyword and add ‘await”s to our appropriate lines of code, so that we can rest assure that everything gets executed in order and waits for the previous step to correctly finish.

  1. Update the step definitions to look like below…

If we now run npm test, our test should run and pass πŸ™‚