Using BDD and Robot Framework in Squash - Automating test cases
Getting the test cases
Annita Squash TM administrator |
Pravash Product owner |
Fabrice Functional tester |
Antonine Automatician |
---|---|---|---|
Set up Squash TM | |||
Write requirements | |||
Write test cases | |||
Transmit test cases | |||
Get test cases | |||
Automate test cases | |||
Deliver automated test cases | |||
Indicate automation is performed | |||
Run automated tests |
Picking up the test cases to automate in Squash TM
Antonine picks some tests to be automated in the "To Do" Tab of the Automation Workspace (see Squash TM documentation) by selecting them and clicking the "Assign to me" button.
Then, using "Assigned to me" Tab of the Automation Workspace (see Squash TM documentation), she indicates that the automation of these tests is started:
Getting the robot
files
Antonine updates her local repository to get the robot
files pushed by Squash TM in the remote Git repository.
git pull
Automating the test cases
Annita Squash TM administrator |
Pravash Product owner |
Fabrice Functional tester |
Antonine Automatician |
---|---|---|---|
Set up Squash TM | |||
Write requirements | |||
Write test cases | |||
Transmit test cases | |||
Get test cases | |||
Automate test cases | |||
Deliver automated test cases | |||
Indicate automation is performed | |||
Run automated tests |
Boiler plate setup
Structure of the code base
Before implementing the first Robot Framework steps, Antonine creates some directories to organize her code. The resulting file hierarchy is:
-
.git
/ → Git -
resources
/-
browser_helpers
/ → technical HTML helperscheckbox_radiobutton_helpers.resource
- …
-
helpers
/ → technical data helpersdatatable_helpers.resource
quote_helpers.resource
- …
-
step_definitions
/ → test step definitionsaccount_management.resource
cart_management.resource
navigation.resource
product_management.resource
- …
-
page_objects
/ → page objectsaccount_creation_page.resource
cart_page.resource
header_page.resource
home_page.resource
identity_page.resource
login_page.resource
product_page.resource
- …
setup_teardown.resource
-
-
tests
/-
bdd_squash
/ → containsrobot
files generated by Squash TM 🛑 Subdirectory hierarchy androbot
files must not be modified!-
Account_management
/squash_resources.resource
created by Antonine 🛑 File name must not be modified!271_Standard_account_creation.robot
294_Cannot_log_with_incorrect_password.robot
- …
-
Cart_management
/squash_resources.resource
created by Antonine 🛑 File name must not be modified!296_One_product.robot.robot
297_Add_two_products_in_the_cart.robot
- …
-
…
-
-
bdd_duplicates
/ →robot
file duplicates in order to perform tests in Antonine's local environmentAccount_management
/squash_resources.resource
271_Standard_account_creation.robot
- …
-
-
.gitignore
Some design notes
graph TD
A[Step definitions] --> B[Page objects]
A --> D[Helpers]
B --> E[Browser helpers]
B --> D
Antonine wants to clearly separate the concerns:
-
resources/page_objects
contains the usual page objects.
A page object is a file encapsulating the technical details of a tested page (IDs, names, XPaths… of the HTML elements).
This design pattern has two main advantages:- It reduces the maintenance cost by centralizing the page details in one place: if a developer modifies a HTML element on the page and this change breaks the locator used by Antonine to find the element, she would have to update it in only one place.
- It provides an API that has business semantics: code using the page object knows the features supported by the page (e.g. enter email and password, then try to login) but it doesn't need to know its HTML structure or its JavaScript behaviour.
-
resources/step_definitions
contains the implementation of Robot Framework keywords (test steps). Each keyword interacts with one or several page objects, it has no knowledge about the HTML structure. -
resources/helpers
- contains the code which is not related to the tested application (data format, string transformation, conversion of list or dictionary…);
- is a technical layer: it does not know about the business rules of the tested application.
-
resources/browser_helpers
- contains the code used by page objects for common HTML interactions;
- is also technical layer.
The tests/bdd_squash
directory
🛑 The robot
files of the tests/bdd_squash
directory must not be modified, they are controlled by Squash TM.
Modifying some files in that directory, other than the squash_resources.resource
files, could impede the transmission of new or updated test cases (i.e. robot
files) in the future.
But, even if the transmission would work, all the modifications would be lost, overwritten by Squash TM.
.gitignore
file
Antonine creates the usual .gitignore
file. It defines the files that Git should not track and, hence, not consider for commits, see Git documentation. Here, she wants Git to ignore the test reports and screenshots.
This file contains:
# browser → contains all files generated after executing Robot Framework tests with the Browser library
# screenshot
# failure_screen_1.png → full page screenshot embedded in Robot Framework report
# …
# traces → created by the Browser library to store temporary trace files
browser/
# output.xml → test execution results
output.xml
# playwright-log.txt → log generated by the Browser library
playwright-log.txt
# log.html → report file: details about executed tests
log.html
# report.html → report file: overview of test execution
report.html
Structure of a robot
file generated by Squash TM
Antonine analyses a robot
test generated by Squash TM:
# Automation priority: 42
# Test case importance: High
*** Settings ***
Resource squash_resources.resource
*** Keywords ***
Test Setup
${__TEST_SETUP} Get Variable Value ${TEST SETUP}
${__TEST_294_SETUP} Get Variable Value ${TEST 294 SETUP}
Run Keyword If $__TEST_SETUP is not None ${__TEST_SETUP}
Run Keyword If $__TEST_294_SETUP is not None ${__TEST_294_SETUP}
Test Teardown
${__TEST_294_TEARDOWN} Get Variable Value ${TEST 294 TEARDOWN}
${__TEST_TEARDOWN} Get Variable Value ${TEST TEARDOWN}
Run Keyword If $__TEST_294_TEARDOWN is not None ${__TEST_294_TEARDOWN}
Run Keyword If $__TEST_TEARDOWN is not None ${__TEST_TEARDOWN}
*** Test Cases ***
Cannot log with incorrect password
[Setup] Test Setup
Given I am on the AccountCreation page
When I fill AccountCreation fields with gender "F" firstName "Alice" lastName "Noel" password "police" email "alice@noel.com" birthDate "01/01/1970" acceptPartnerOffers "yes" acceptPrivacyPolicy "yes" acceptNewsletter "yes" acceptGpdr "yes" and submit
And I sign out
And I sign in with email "alice@noel.com" and password "poluce"
Then The error message "Échec d'authentification" is displayed
[Teardown] Test Teardown
The file is organized in three main parts:
1 - Settings:
*** Settings ***
Resource squash_resources.resource
squash_resources.resource
file will contain a list of all dependencies required by the scenario. Antonine must create this squash_resources.resource
file in the test folder and list in it the relative paths of the dependencies.
For instance, if the test steps needed by the tests/bdd_squash/Account_management/271_Standard_account_creation.robot
test are located in:
resources/setup_teardown.resource
resources/step_definitions/account_management.resource
she would fill the tests/bdd_squash/Account_management/squash_resources.resource
file as:
*** Settings ***
Documentation Resources for all account management tests
Resource ../../../resources/setup_teardown.resource
Resource ../../../resources/step_definitions/account_management.resource
squash_resources.resource
Antonine must create and implement the squash_resources.resource
file in each folder containing BDD tests.
This file must contain the list of files defining the keywords used in the robot
file generated by Squash TM (see below).
2 - Setup and Teardown:
*** Keywords ***
Test Setup
${__TEST_SETUP} Get Variable Value ${TEST SETUP}
${__TEST_294_SETUP} Get Variable Value ${TEST 294 SETUP}
Run Keyword If $__TEST_SETUP is not None ${__TEST_SETUP}
Run Keyword If $__TEST_294_SETUP is not None ${__TEST_294_SETUP}
Test Teardown
${__TEST_294_TEARDOWN} Get Variable Value ${TEST 294 TEARDOWN}
${__TEST_TEARDOWN} Get Variable Value ${TEST TEARDOWN}
Run Keyword If $__TEST_294_TEARDOWN is not None ${__TEST_294_TEARDOWN}
Run Keyword If $__TEST_TEARDOWN is not None ${__TEST_TEARDOWN}
Squash TM has created keywords to run as setup and teardown of the test. (The setup is used to prepare the test context. The teardown to clean it up.) For each test, Antonine has to choose to implement none, one, or several of those keywords:
-
${TEST SETUP}
and${TEST TEARDOWN}
are shared by all tests: used for basic non-specific setup and teardown (for instance: opening or closing a browser) -
${TEST 294 SETUP}
and${TEST 294 TEARDOWN}
are specific setup and teardown for this specific 294 test case. If this test needs some specific steps in addition to the basic setup and teardown, Antonine can write the corresponding code in one of those keywords.
Setup and teardown keywords
- If all tests require a common setup, Antonine must define the
${TEST SETUP}
keyword; otherwise, she must keep this keyword undefined. - If all tests require a common teardown, Antonine must define the
${TEST TEARDOWN}
keyword; otherwise, she must keep this keyword undefined. - If a given test requires a specific setup, Antonine must define the
${TEST <test_id> SETUP}
keyword; otherwise, she must keep this keyword undefined. - If a given test a specific teardown, Antonine must define the
${TEST <test_id> TEARDOWN}
keyword; otherwise, she must keep this keyword undefined.
The files implementing these keywords shall be referenced in the squash_resources.resource
file.
(Some IDEs improperly report a warning when a Robot Framework keyword is undefined. This may be the case for these keywords. This warning should be ignored.)
3 - The test case as written in Squash TM:
Each keyword appearing in the test case will have to be implemented in the *** Keywords ***
section of one of the resource
files.
*** Test Cases ***
Cannot log with incorrect password
[Setup] Test Setup
Given I am on the AccountCreation page
When I fill AccountCreation fields with gender "F" firstName "Alice" lastName "Noel" password "police" email "alice@noel.com" birthDate "01/01/1970" acceptPartnerOffers "yes" acceptPrivacyPolicy "yes" acceptNewsletter "yes" acceptGpdr "yes" and submit
And I sign out
And I sign in with email "alice@noel.com" and password "poluce"
Then The error message "Échec d'authentification" is displayed
[Teardown] Test Teardown
Keyword implementation
Antonine has to implement all the keywords.
The files implementing these keywords shall be referenced in the squash_resources.resource
file.
Implementing setup and teardown
Once the file hierarchy has been set up, Antonine writes some necessary basic building bricks, starting with the setup and teardown of the tests that she places in resources/setup_teardown.resource
as Robot Framework keywords.
-
the definition of variables
*** Variables *** ${TEST SETUP} Open Application ${URL} http://localhost:8080/
-
setup
This setup opens a new Page at the given***Keywords*** Open Application [Documentation] Test setup. Register Keyword To Run On Failure Take Screenshot failure_screen_{index} fullPage=True New Browser browser=firefox headless=True New Page url=${URL} Set Viewport Size 1900 1000
${URL}
location, with the Firefox browser, and changes the size of the window to a basic laptop screen size. This setup also generates full-page screenshots in case of one or several step failures in the test. The screenshots are placed in thebrowser/screenshot
folder and are also embedded in the test reports. This will be very helpful to analyse why a test failed:
Writing browser helpers
resources/browser_helpers/
contains resources with keywords used in several page objects, for instance, the resources/browser_helpers/checkbox_radiobutton_helpers.resource
contains keywords to:
-
verify which radiobutton is selected in a list of radiobuttons
*** Settings *** Documentation Helpers for checkboxes and radiobuttons Library Browser *** Keywords *** Verify Selected Radiobutton [Arguments] ${choice} @{radiobuttons} [Documentation] Checks if the specified radiobutton state matches the specified choice FOR ${radiobutton} IN @{radiobuttons} IF "${choice}" == "${radiobutton}[label]" Get Checkbox State ${radiobutton}[rb] == True BREAK END END
-
select a checkbox
*** Keywords *** Select Checkbox Regarding Choice [Arguments] ${choice} ${cb} [Documentation] Check checkbox regarding the specified choice. IF "${choice}" == "yes" Check Checkbox ${cb}
-
select a radiobutton
*** Keywords *** Select Radiobutton Regarding Choice [Arguments] ${choice} @{radiobuttons} [Documentation] Select radiobutton in a list of radiobuttons regarding the specified choice. FOR ${radiobutton} IN @{radiobuttons} IF "${choice}" == "${radiobutton}[label]" Check Checkbox ${radiobutton}[rb] BREAK END END
Manage different kinds of data
Parameters
Fabrice has written a first type of basic test, with embedded values of variables directly inside the test steps:
Squash TM has generated a Robot Framework test with embedded parameters between quotes:
*** Test Cases ***
Cannot log with incorrect password
[Setup] Test Setup
Given I am on the AccountCreation page
When I fill AccountCreation fields with gender "F" firstName "Alice" lastName "Noel" password "police" email "alice@noel.com" birthDate "01/01/1970" acceptPartnerOffers "yes" acceptPrivacyPolicy "yes" acceptNewsletter "yes" acceptGpdr "yes" and submit
And I sign out
And I sign in with email "alice@noel.com" and password "poluce"
Then The error message "Échec d'authentification" is displayed
[Teardown] Test Teardown
Datasets
Fabrice has also written a second type of test, using datasets and embedded variables:
For this test, values are defined using Squash TM's dataset section:
Squash TM has generated a Robot Framework test with embedded variables:
*** Test Cases ***
Standard account creation
[Setup] Test Setup
Given I am on the AccountCreation page
When I fill AccountCreation fields with gender ${gender} firstName ${first} lastName ${last} password ${password} email ${mail} birthDate ${birth} acceptPartnerOffers ${offers} acceptPrivacyPolicy ${privacy} acceptNewsletter ${news} acceptGpdr ${gpdr} and submit
And I sign out
And I sign in with email ${mail} and password ${password}
Then My personal informations are gender ${gender} firstName ${first} lastName ${last} email ${mail} birthDate ${birth}
[Teardown] Test Teardown
Managing quotes to avoid code duplication
Some test steps are shared by those two tests, for instance the I sign in with email "alice@noel.com" and password "poluce"
and I sign in with email ${mail} and password ${password}
are similar: the main difference between the two generated keywords are the quotes surrounding the variables in the first one.
Antonine wants to avoid code duplication, thus, she wants to implement only once the I sign in with email ${mail} and password ${password}
keyword.
In order to achieve this, Antonine has to manage the quotes because if she would not remove the quotes from the variables values, the keyword would work perfectly for the embedded parameters test, but would fail on the basic one, because Robot Framework would consider the parameter value as "Alice" and would inject it in the tested application with the quotes.
(This issue should be fixed in a future Squash TM release, as all robot
keywords generated by Squash TM will have quotes.).
In the resources/step_definitions/account_management.robot
file, Antonine implements the keyword I sign in with email ${mail} and password ${password}
:
*** Keywords ***
I sign in with email ${mail} and password ${password}
[Documentation] Logs a user.
${mail} = Remove Framing Quotes From Parameter ${mail}
${password} = Remove Framing Quotes From Parameter ${password}
Go To The SignIn Page
Clear Login Fields
Fill Login Fields ${mail} ${password}
Submit Login
by using the resources/helpers/quotes.resource
resource:
*** Settings ***
Documentation helpers for quoted parameters coming from Squash TM.
Library String
Library Collections
*** Keywords ***
Remove Framing Quotes From Parameter
[Arguments] ${parameter}
[Documentation] If the parameter starts and ends with a quote,
... this keyword removes them.
... Examples:
... "hello world!" -> hello world!
... "hello world! -> "hello world!
... hello world! -> hello world!
${parameter} = Replace String Using Regexp ${parameter} \\".*\\" ${parameter}[1:-1]
RETURN ${parameter}
Running Robot Framework test using datasets on local environment
For tests using datasets, it is possible to retrieve their values by using the squash-tf-services
library (see that page):
*** Settings ***
Library squash_tf.TFParamService
...
*** Test Cases ***
Standard account creation
${gender} = Get Test Param DS_gender
${first} = Get Test Param DS_first
${last} = Get Test Param DS_last
${password} = Get Test Param DS_password
${mail} = Get Test Param DS_mail
${birth} = Get Test Param DS_birth
${offers} = Get Test Param DS_offers
${privacy} = Get Test Param DS_privacy
${news} = Get Test Param DS_news
${gpdr} = Get Test Param DS_gpdr
...
tests\bdd_duplicates
folder, in order to leave the .robot
files used by Squash untouched. In the duplicated files, she then adds a *** Variables ***
section and removes the ${data} = Get Test Param DS_data
:
*** Settings ***
*** Variables ***
${gender} F
${first} Alice
${last} Bob
${password} Pass1234
${mail} alice.bob@mail.fr
${birth} 10/08/1998
${offers} yes
${privacy} yes
${news} yes
${gpdr} yes
*** Test Cases ***
Standard account creation
...
.robot
file generated by Squash TM.
Docstring
Fabrice can also use docstrings to add multilines or long strings to the tests:
The docstring is managed by Squash TM by declaring a variable and assigning the text value to it:
*** Test Cases ***
Navigate to one product
${docstring_1} = Set Variable Le meilleur reste à venir ! Faites parler vos murs avec cette affiche encadrée chargée d'optimisme sera du plus bel effet dans un bureau ou un open-space. Cadre en bois peint avec passe-partout integré pour un effet de profondeur.
...
When I navigate to category "art"
And I navigate to product "Affiche encadrée The best is yet to come"
Then The product description is "${docstring_1}"
...
In the case of a multiline docstring such as:
Le meilleur reste Ă venir !
Faites parler vos murs avec cette affiche encadrée chargée d'optimisme sera du plus bel effet dans un bureau ou un open-space.
Cadre en bois peint avec passe-partout integré pour un effet de profondeur.
Squash TM generates a robot
file using \n
:
*** Test Cases ***
Navigate to one product
${docstring_1} = Set Variable Le meilleur reste à venir !\nFaites parler vos murs avec cette affiche encadrée chargée d'optimisme sera du plus bel effet dans un bureau ou un open-space.\nCadre en bois peint avec passe-partout integré pour un effet de profondeur.
Antonine writes the The product description is "${docstring_1}"
as documented in the parameters and datasets section above.
Datatables
Fabrice also used datatables to add data to the tests:
The datatable has been extracted and converted in the Robot Framework syntax by Squash TM:
*** Settings ***
Resource squash_resources.resource
...
*** Test Cases ***
Add two products in the cart
${row_1_1} = Create List Product Number Dimension
${row_1_2} = Create List Affiche encadrée The best is yet to come 1 40x60cm
${row_1_3} = Create List Illustration vectorielle Renard 1
${datatable_1} = Create List ${row_1_1} ${row_1_2} ${row_1_3}
...
Then the cart contains "${datatable_1}"
...
Datatables are managed row by row: Squash TM generates a list of strings for each row, called ${row_1_*}
.
The ${datatable_1}
list is a list of all the rows, in other words, a list of lists, the first row being a list of the header labels.
Antonine has several ways to manage this input, she chooses to convert it from a list of lists to a list of dictionaries. She adds the method in the resources/helpers/datatable_helper.resource
file:
*** Keywords ***
Create ListOfDictionary From Datatable
[Arguments] ${datatable}
[Documentation] Convert a list of lists to a list of dictionaries.
... Example of input from Squash TM's BDD datatable (list of lists):
... ['['name', 'firstName', 'age']', '['Doe', 'Alice', '12']', '['Smith', 'John', '45']']
... Output (list of dictionaries):
... {'{'name': 'Doe', 'firstName': Alice, 'age': '12'}',
... '{'name': 'Smith', 'firstName': 'John', 'age': '45'}']
${datatable_size} = Get Length ${datatable}
@{final_list} = Create List
FOR ${i} IN RANGE 1 ${datatable_size} 1
${nb_items} = Get Length ${datatable}[${i}]
&{dict} = Create Dictionary
FOR ${j} IN RANGE 0 ${nb_items} 1
Set To Dictionary ${dict} ${datatable}[0][${j}]=${datatable}[${i}][${j}]
END
Append To List ${final_list} ${dict}
END
RETURN @{final_list}
Then, Antonine implements easily the Then the cart contains "${datatable_1}"
, using her structured data:
*** Keywords ***
The Cart contains "${datatable}"
[Documentation] Checks that specified products are found in the cart.
@{products} = Create ListOfDictionary From Datatable ${datatable}
Go To The Cart Page
Products Should Be In Cart @{products}
Writing page objects
Antonine creates a page object for each page used by the test steps, in the resources/page_objects
folder.
A page object contains a *** Variables ***
section with the locators, and a *** Keywords ***
section where keywords used in the test steps are implemented. For instance, the page object of the login page is:
*** Settings ***
Documentation Login page object
Library Browser
*** Variables ***
&{log_locators} create_account_link=//a[contains(@href, "connexion?create_account=1")]
... login_button=//*[@id="submit-login"]
... email_field=//*[@id="field-email"]
... password_field=//*[@id="field-password"]
*** Keywords ***
Clear Login Fields
[Documentation] Clear all login fields.
Clear Text ${log_locators}[email_field]
Clear Text ${log_locators}[password_field]
Fill Login Fields
[Arguments] ${email} ${password}
[Documentation] Logs a user on the website using specified values.
Type Text ${log_locators}[email_field] ${email}
Type Text ${log_locators}[password_field] ${password}
Submit Login
[Documentation] Initiate login.
Click ${log_locators}[login_button]
Error Message Should Be Displayed
[Arguments] ${message}
[Documentation] Checks that the specified error message is displayed.
Get Element //li[text()="${message}"]
Go To The AccountCreation Page
[Documentation] Navigates to the AccountCreation page.
Click ${log_locators}[create_account_link]
Encapsulation in Robot Framework
One keyword can depend on several page objects. Thus, to avoid any ambiguity, Antonine choose to store all the locators variables in a dictionary with a clear page object identification name. In the login-page
, this dictionary is called &{log_locators}
.
Implementing Robot Framework keywords (steps)
The resources/step_definitions/*
files contain the definitions of the Robot Framework test steps.
There are three types of steps:
Given
A Given
step is used to set up a test precondition.
It can navigate and interact with several pages in order to arrange the necessary data. It can even set up the data by bypassing the application user interface: calling the REST API provided by the application, injecting data in the application database…
A Given
step does not need to be on a particular page to be called.
For example, some test cases need to start in the AccountCreation page.
This step is implemented by navigating to the AccountCreation page and checking that the navigation has succeeded (resources/step_definitions/account_management
file):
*** Settings ***
Resource ../page_objects/header_page.resource
Resource ../page_objects/login_page.resource
Resource ../page_objects/account_creation_page.resource
***Keywords***
I am on the AccountCreation page
[Documentation] Navigates to the AccountCreation page
Go To The SignIn Page
Go To The AccountCreation Page
Page Should Be AccountCreation Page
The verification that navigation has succeeded is done by the Page Should Be AccountCreation Page
keyword, implemented in resources/page_objects/account_creation_page.resource
by checking both the page title and the tab title:
*** Variables ***
&{acc_locators} page_title=//h1[contains(text(), "Créez votre compte")]
... mister_rb=//*[@id="field-id_gender-1"]
... miss_rb=//*[@id="field-id_gender-2"]
... first_name_field=//*[@id="field-firstname"]
... last_name_field=//*[@id="field-lastname"]
... email_field=//*[@id="field-email"]
... password_field=//*[@id="field-password"]
... birth_date_field=//*[@id="field-birthday"]
... privacy_cb=//*[@name="customer_privacy"]
... gpdr_cb=//*[@name="psgdpr"]
... news_cb=//*[@name="newsletter"]
... offers_cb=//*[@name="optin"]
... validate_button=//*[@id="customer-form"]/footer/button
***Keywords***
Page Should Be AccountCreation Page
[Documentation] Checks if we are on the AccountCreation page.
Get Title == Identifiant
Get Element ${acc_locators}[page_title]
When
A When
step performs an action.
For example, the code implemented by the I sign in with email ${mail} and password ${password}
keyword is:
*** Keywords ***
I sign in with email ${mail} and password ${password}
[Documentation] Logs a user.
${mail} = Remove Framing Quotes From Parameter ${mail}
${password} = Remove Framing Quotes From Parameter ${password}
Go To The SignIn Page
Clear Login Fields
Fill Login Fields ${mail} ${password}
Submit Login
Many When
steps expect to be applied while a given page is displayed, so they assert that this is the case.
For instance, the implementation of I sign out
is:
*** Keywords ***
I sign out
[Documentation] Logs out a user.
Sign Out
User Is Logged Out
The verification that the user is indeed logged out is done by the User Is Logged Out
keyword, implemented in resources/page_objects/header_page.resource
by checking that the login link is visible again.
*** Variables ***
&{h_locators} login_link=//a[@title="Identifiez-vous"]
... logout_link=//a[contains(@href, "?mylogout=") and @class="logout hidden-sm-down"]
... welcome_message=//a[@title="Voir mon compte client"]/span
... cart_link=//span[text()="Panier"]
... home_link=//img[@alt="Prestashop-Robot"]
*** Keywords ***
User Is Logged In
[Arguments] ${first_name} ${last_name}
[Documentation] Checks that the specified user is logged in.
Get Text ${h_locators}[logout_link] *= DĂ©connexion
Get Text ${h_locators}[welcome_message] == ${first_name} ${last_name}
Then
A Then
step is used to verify that a test postcondition is fulfilled.
It can navigate and interact with several pages in order to arrange the necessary data. It can even set up the data by bypassing the application user interface: calling the REST API provided by the application, injecting data in the application database…
A Then
step does not need to be on a particular page to be called.
For example, the implementation of the Then My personal informations are gender ${gender} firstName ${first} lastName ${last} email ${mail} birthDate ${birth}
keyword is achieved by displaying the personal data page, getting the field values, and checking that they have the expected values:
*** Keywords ***
My personal informations are gender ${gender} firstName ${first} lastName ${last} email ${mail} birthDate ${birth}
[Documentation] Checks if the specified values match the personal informations of a logged user.
${gender} = Remove Framing Quotes From Parameter ${gender}
${first} = Remove Framing Quotes From Parameter ${first}
${last} = Remove Framing Quotes From Parameter ${last}
${mail} = Remove Framing Quotes From Parameter ${mail}
${birth} = Remove Framing Quotes From Parameter ${birth}
Go To The MyAccount Page
Page Should Be MyAccount Page
Go To The Identity Page
Private Informations Should Be ${gender} ${first} ${last} ${mail} ${birth}
The verification of the informations is done by the Private Informations Should Be
keyword, implemented in resources/page_objects/identity_page.resource
by checking the values of all specified parameters:
*** Variables ***
&{id_locators} mister_rb=//*[@id="field-id_gender-1"]
... miss_rb=//*[@id="field-id_gender-2"]
... first_name_field=//*[@id="field-firstname"]
... last_name_field=//*[@id="field-lastname"]
... email_field=//*[@id="field-email"]
... birth_date_field=//*[@id="field-birthday"]
... submit_button=//*[@id="customer-form"]/footer/button
... privacy_cb=//*[@name="customer_privacy"]
... gpdr_cb=//*[@name="psgdpr"]
... old_password_field=//*[@id="field-password"]
... new_password_field=//*[@id="field-new_password"]
*** Keywords ***
Private Informations Should Be
[Arguments] ${gender} ${first} ${last} ${mail} ${birth}
[Documentation] Checks that the specified values match the personal informations of a logged user.
&{gender_M} = Create Dictionary label=M rb=${id_locators}[mister_rb]
&{gender_F} = Create Dictionary label=F rb=${id_locators}[miss_rb]
@{genders} = Create List ${gender_M} ${gender_F}
Verify Selected Radiobutton ${gender} @{genders}
Get Attribute ${id_locators}[first_name_field] value == ${first}
Get Attribute ${id_locators}[last_name_field] value == ${last}
Get Attribute ${id_locators}[email_field] value == ${mail}
Get Attribute ${id_locators}[birth_date_field] value == ${birth}
Robocop linter
Antonine uses the Robocop linter (a linter is a static code analyzer) to ensure her code is clean:
Installation
Antonine installs Robocop as described in the Robocop documentation:
pip install robotframework-robocop
Usage
Then, to analyze the code in a file or a folder, Antonine runs:
robocop [path 1] [path 2] [path n]
Robocop warnings
The Robot Framework code generated by Squash TM may trigger some robocop warnings, some of them should be corrected in future releases.
Regarding the Robot Framework code written by Antonine, good coding practices should prevent warnings, except for ones resulting from the way Squash TM generates its robot
files:
- wrong-case-in-keyword-name: BDD test steps are not written in title case (i.e. using uppercase for the first letter of each word).
- line-too-long: Squash TM allows to write test step up to 255 characters long whereas robocop recommends less than 120 characters.
- too-long-test-case: Squash TM allows to write many step tests, whereas robocop recommends less than 20 steps.
Antonine can ignore those warnings, or she can configure her project to ignore some rules or some robot
files as detailed in the Robocop documentation on including and excluding rules.
Delivering the automated test cases
Annita Squash TM administrator |
Pravash Product owner |
Fabrice Functional tester |
Antonine Automatician |
---|---|---|---|
Set up Squash TM | |||
Write requirements | |||
Write test cases | |||
Transmit test cases | |||
Get test cases | |||
Automate test cases | |||
Deliver automated test cases | |||
Indicate automation is performed | |||
Run automated tests |
Antonine is now ready to run the test on her local environment:
robot <test.robot>
/report.html
file):
and the Robot Framework log (/log.html
file):
When she finds something suspicious while automating a test, she performs the test manually and, if there really is a bug, she reports it as described in the Squash TM documentation.
When the tests are running properly, she commits and pushes:
git add .
git commit -m "Implemented first account and cart steps"
git push
Indicating that the automation is performed
Annita Squash TM administrator |
Pravash Product owner |
Fabrice Functional tester |
Antonine Automatician |
---|---|---|---|
Set up Squash TM | |||
Write requirements | |||
Write test cases | |||
Transmit test cases | |||
Get test cases | |||
Automate test cases | |||
Deliver automated test cases | |||
Indicate automation is performed | |||
Run automated tests |
Then, using the "Assigned to me" Tab of the Automation Workspace (see Squash TM documentation), Antonine indicates that the tests have been automated: