Creating Tests for our First Feature

Introduction

In this section, we will finally begin creating our actual test scenarios and coding them.

The website we will be testing is an Angular website called https://www.zagat.com, a US based website for national restaurant reviews and finding recommended places to eat in any given national location.

Let’s begin 🙂

Creating the first 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.

We also want each test scenario to be small, clean and atomic. This means that ideally each test scenario should only test one specific thing and we should try to avoid repeating flows in our tests.

  1. With the project open in our chosen editor, right-click the ‘features’ folder and add a file called find_a_restaurant.feature
  2. Open up the find_a_restaurant.feature file and add the following description of the feature along with our first test scenario, like below…

Creating the undefined step definitions

The steps in our scenario are currently undefined and do not exist, let’s now get the undefined step definitions so we can add them in to our project 🙂

  1. With the Terminal (or Command prompt) window open in the project root, enter the following command to print out to the console and generate the undefined step definitions…

    It should generate output like below…
  2. With the project open in your chosen editor, right-click on the step_defs python package and create a Python file named ‘test_foodie.py‘ so that this step definition file follows the pytest naming conventions for python files
  3. Copy and paste the console output of the imports and the @scenario fixture in to the ‘test_foodie.py’ file like below, also quickly adding an import to the BASE_URL we specified in our conftest.py file…

‘Given that Frank decides to use Zagat to find recommended restaurants’

  1. Copy the pending ‘Given’ step definition from the console output and add it in to the ‘test_foodie.py‘ step definition file, along with appropriate imports and adding the additional ‘parsers’ import, with the whole thing now looking like below…
  2. Next, let’s edit the step definition a bit so that it can take any actors name as a string parameter by making use of that parsers import we added previously, with the whole thing now looking like below…

‘When he searches for all restaurants in his area of San Diego’

  1. Copy the pending ‘When’ step definition from the console output file and add it in to the ‘test_foodie.py’ step definition file, updating any necessary imports, with the whole thing looking like below…
  2. The ‘When’ step will have some formatting errors, so let’s edit it now to fix that and also take a parameter for the area to search for restaurants in, with the whole thing looking like below…

‘Then a list of recommended restaurants in San Diego are returned to him’

  1. Copy the pending ‘Then’ step definition from the console output and add it in to the ‘test_foodie.py’ step definition file, updating any necessary imports, with the whole thing looking like below…
  2. The ‘Then’ step will have some formatting errors, so let’s edit it now to fix that and also take a parameter for the area again, like so….

Defining the Step Definitions

‘Given that Frank decides to use Zagat to find recommended restaurants’

  1. Edit the ‘Given’ step to access the ‘browser’ in our conftest.py file and navigate to the BASE_URL also specified in the conftest.py file…

    The whole thing should now look like below…

‘When he searches for all restaurants in his area of San Diego’

If we break this step down in to any tasks that need to be performed, we could say that the user attempts to search for recommended restaurants in their given area of ‘San Diego’

  1. Edit the ‘When’ step to look like below…

    You will notice that we get an error, as the BasePage does not exist yet.  Let’s fix that by creating it 🙂

BasePage object

  1. With the project open in your chosen editor, right-click on the ‘pages’ python package and add a python file named ‘base_page.py’
  2. Open up the ‘base_page.py’ file and edit it to create the class with an ‘__init__’ constructor to initialise the browser that we pass in to the base_page object, like below…
Adding our ‘search_for_restaurants_in()’ function
  1. In the BasePage class, add the following function to search for restaurants in a given area, with the whole thing looking like below…

    You’ll notice that we have some errors, as we have not yet added the By locators for the two search fields, so let’s do that next 🙂
  2. Add the following By locators in the class but outside of any functions, like so…

    This is good and will work, but we could also make this arguably cleaner by adding getter functions to get the elements we need and then call them in the search_for_restaurants_in() function instead. We could also create a single function for clearing and entering text in to the LOCATION_SEARCH_FIELD, so let’s also do that now 🙂
  3. Edit the BasePage class to include two private getter functions for the two By locators we added and also add a function for clearing and then entering text in the LOCATION_SEARCH_FIELD element, with the whole thing looking like below…
  4. Finally, let’s go back to the ‘test_foodie.py’ file and add an import for the BasePage class, with the whole thing looking like below…

‘Then a list of recommended restaurants in San Diego are returned to him’

In this step, we will now assert that the user sees a list of recommended restaurants in the area they searched in.  We will do this by asserting that the given area is present in the browser’s current URL and also that the actual returned results are visible 🙂

  1. Edit the ‘Then’ step to look like below (remembering to add the browser parameter too)…

    You will notice we have some errors as we have not added the import for unquote() and we have not yet implemented the SearchResultsPage(), so let’s do all that next

Decode the current URL

  1. Add the following import for the unquote() function and to decode the current URL…

SearchResultsPage object

  1. With the project open in your chosen editor, right-click on the ‘pages’ python package and add a python file named ‘search_results_page.py’
  2. Open up the ‘search_results_page.py’ file and edit it to create a class that inherits from the BasePage() class, like so…

    It might complain about the class being empty, so we’ll fix that next too
Adding our ‘RETURNED_SEARCH_RESULTS’ By locator
  1. Open up the ‘search_results_page.py’ file and add the following By locator in the SearchResultsPage() class, with the whole thing looking like below…
Adding our ‘get_returned_search_results’ function
  1. Add the following function in the SearchResultsPage() class to return the search results container element, with the whole thing looking like below…
  2. Next, we can go back to our ‘test_foodie.py’ step definition file and simply add the import for the SearchResultsPage(), with the whole file looking like below…

    If we now run the command pytest in our Terminal (or Command prompt) window (still in our virtual environment), it should run our test and it should pass successfully 😀
Liked it? Take a second to support Thomas on Patreon!

Previous Article

2 Replies to “Part 3. Creating Tests for our First Feature”

  1. Hi Tom,
    Great post! I have just started taking an interest in Python as a language, having come from a Java and JavaScript/TypeScript background; this post was super helpful.
    The step-by-step setup guide is very clear and the test design walk-through was very well thought out and described.
    Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.