This tutorial was conducted during the QA Automation Course. It consists of the mandatory part and the individual tasks which I developed by myself to practice testing skills on API, Database and UI testing. That part of code is highlighted by comments.
Mandatory Part:
Create the folder and file structure for the framework.
In the cloned GitHub repository, create the following hierarchy of files and folders, which we will consider as the initial structure of the framework:
Folder structure from the root directory of the project:
/config
/modules
/modules/common
/modules/ui
/modules/ui/page_objects
/modules/api
/modules/api/clients
/tests
/tests/ui
/tests/api
File structure from the root directory of the project:
/config/config.py
/modules/common/init.py
/modules/ui/page_objects/init.py
/modules/api/clients/init.py
/tests/ui/test_ui.py
/tests/api/test_api.py
To develop tests using the pytest
module, fixtures, and markers, follow these requirements:
-
Markers
check
andchange
are registered in thepytest.ini
file. -
In the
conftest.py
file, describe theUser
class:
- Use the constructor to set the name and second_name fields with default values as
None
. - The class has a
create
method. This method sets thename
andsecond_name
fields with your name and surname. - The class has a
remove
method. This method sets thename
andsecond_name
fields to an empty string.
- In the
conftest.py
file, describe theuser
fixture. This fixture:
- Creates an object of the
User
class. - Calls the
create
method of the object. - Returns the object after calling the
create
method to the tests. - After the test execution, calls the
remove
method of the object.
- In the
/tests/api/test_fixtures.py
file, create the testtest_change_name
:
- The test has a
check
marker. - The test has a
check
marker. - It checks that the
name
field of theuser
object matches the expected value.
- In the
/tests/api/test_fixtures.py
file, create the testtest_change_second_name
:
- The test has a
check
marker. - It uses the
user
fixture. - It checks that the
second_name
field of theuser
object matches the expected value.
- In the
/tests/api/test_api.py
file, create the testtest_remove_name
:
- The test has a
change
marker. - It uses the
user
fixture. - As the first step, the test changes the
name
field of theuser
object to an empty string. - As the second step, the test checks that the changes occurred and are correct.
- In the
/tests/api/test_api.py
file, create the testtest_name
:
- The test has a
check
marker. - It uses the
user
fixture. - It checks that the
name
field of theuser
object matches the expected value.
- In the
/tests/api/test_api.py
file, create the testtest_second_name
:
- The test has a
check
marker. - It uses the
user
fixture. - It checks that the
second_name
field of theuser
object matches the expected value.
Develop tests for testing the HTTP protocol using the pytest
and requests modules, using fixtures and markers.
In the cloned GitHub repository, develop tests using the pytest and requests modules that meet the following requirements:
-
The
http
marker is registered in thepytest.ini
file -
In the file
/tests/test_http.py
, create thetest_first_request
:
- The test has the
http
marker - As the first step, the test sends an
HTTP GET
request to the address https://api.github.com/zen and stores the server's response in a variable. - As the second step, the test prints the text attribute of the server's response to the screen using f-strings.
- In the file
/tests/test_http.py
, create the testtest_second_request
:
- The test has the
http
marker - As the first step, the test sends an
HTTP GET
request to the address https://api.github.com/users/defunkt and stores the server's response in a variable - The test checks that the name attribute of the response body from the server corresponds to the value
Chris Wanstrath
. - The test checks that the status code of the response from the server corresponds to the number
200
. - The test checks that the Server header of the response from the server corresponds to the value
GitHub.com
.
- In the file
/tests/test_http.py
, create a test namedtest_status_code_request
:
- The test should have the
http
marker. - In the first step, the test sends an
HTTP GET
request to the address https://api.github.com/users/sergii_butenko and stores the server's response in a variable. - The test verifies that the status code of the server's response corresponds to the number
404
.
Develop tests for testing the Github API
by creating your own API client, using the GitHub API documentation https://docs.github.com/en/rest/users/users?apiVersion=2022-11-28, and the pytest and requests modules.
In the cloned repository, develop tests using the pytest
and requests modules that meet the following requirements:
-
The
api
marker is registered in thepytest.ini file
. -
In the file
/modules/api/clients/github.py
, create a classGitHub
.
- The method description includes a mandatory parameter
username
. - In the body of the method, the
URL
to which the HTTP request should be sent is formed. The logic of forming the URL is to concatenate two strings:- https://api.github.com/users/
- The value of the
username
parameter - In the body of the method, an HTTP request with the
GET
method is sent to theURL
from the previous step. - The method returns the body of the response from the server in json format.
- The method description includes a mandatory parameter
name
. - In the body of the method, an
HTTP
request with theGET
method is sent to theURL
"https://api.github.com/search/repositories" with the query string parameterq
, the value of which is equal to the value of the name parameter of the method. - The method returns the body of the response from the server in json format.
- The class has an object method
get_user
- The class has an object method
search_repo
- The class has an object method
- In the
conftest.py
file, describe thegithub_api
fixture. This fixture:
- Creates an object of the
GitHub
class. - Returns the created object to the tests.
- In the file
/tests/api/test_github_api.py
, create the testtest_user_exists
:
- The test has the
api
marker. - Uses the
github_api
fixture. - In the body of the test, use the
get_user
method of thegithub_api
fixture. - Use the
username
for the search:defunkt
. - Verify that the body of the response from the server has an attribute
login
, the value of which should be equal todefunkt
.
- In the file
/tests/api/test_github_api.py
, create the testtest_user_not_exists
:
- The test has the
api
marker. - Uses the
github_api
fixture. - In the body of the test, use the
get_user
method of thegithub_api
fixture. - Use the
username
for the search:butenkosergii
. - Verify that the body of the response from the server has an attribute message, and its value should be equal to
Not Found
.
- In the file
/tests/api/test_github_api.py
, create the testtest_repo_can_be_found
:
- The test has the
api
marker. - Uses the
github_api
fixture. - In the body of the test, use the
search_repo
method of thegithub_api
fixture. - Use the repository
name
for the search:become-qa-auto
. - Verify that the body of the response from the server has an attribute
total_count
, and its value should be equal to the expected value at the time of test creation, for example,25
.
- In the file
/tests/api/test_github_api.py
, create the testtest_repo_cannot_be_found
:
- The test has the
api
marker. - Uses the
github_api
fixture. - In the body of the test, use the
search_repo
method of thegithub_api
fixture. - Use a repository
name
for the search that does not exist at the time of test creation, for example,sergiibutenko_repo_non_exist
. - Verify that the body of the response from the server has an attribute
total_count
, and its value should be0
.
- In the file
/tests/api/test_github_api.py
, create the testtest_repo_with_single_char_be_found
:
- The test has the
api
marker. - Uses the
github_api
fixture. - In the body of the test, use the
search_repo
method of thegithub_api
fixture. - Use the repository
name
for the search:s
or any other name consisting of a single character. - Verify that the body of the response from the server has an attribute
total_count
, and its value should not be0
.
In the cloned repository, develop tests using the pytest
and sqlite3
modules, meeting the following requirements:
-
The marker
database
is registered in thepytest.ini
file. -
In the file
/modules/common/database.py
, create theDatabase
class.
- The class has a constructor where two object attributes are initialized:
self.connection
- an object that implements a connection to the databaseself.cursor
- the cursor of theself.connection
object
- The class has an object method
test_connection
:- The method executes an SQL query
SELECT
sqlite_version();
- The result of the method is the version of the database printed to the terminal.
- The method executes an SQL query
- The class has an object method
get_all_users
:- The method should return the values of the
name
,address
, andcity
fields for all users from the customers table.
- The method should return the values of the
- The class has an object method
get_user_address_by_name
:- The method has a mandatory parameter
name
. - The method should return the values of the
address
,city
,postalCode
, andcountry
fields for the user with the specified name from thecustomers
table.
- The method has a mandatory parameter
- The class has an object method
update_product_qnt_by_id
:- The method has mandatory parameters
product_id
,qnt
. - The method should change the quantity of the product with the specified
product_id
in the products table to the value specified in theqnt
parameter.
- The method has mandatory parameters
- The class has an object method
select_product_qnt_by_id
:- The method has a mandatory parameter
product_id
. - The method should return the quantity of the product with the specified
product_id
, a unique value from the products table.
- The method has a mandatory parameter
- The class has an object method
insert_product
:- The method has mandatory parameters
product_id
,name
,description
,qnt
. - The method should insert or replace data in the
products
table for theid
,name
,description
, andquantity
columns. Data should be taken from theproduct_id
,name
,description
, andqnt
parameters.
- The method has mandatory parameters
- The class has an object method
delete_product_by_id
:- The method has a mandatory parameter
product_id
. - The method should delete the product with the specified
product_id
, a unique value, from the products table.
- The method has a mandatory parameter
- The class has an object method
get_detailed_orders
:- Using the
JOIN
command and tablesorders
,customers
,products
, return the following information from theorders
table in the corresponding order:unique order number
,customer name
,ordered product name
,ordered product description
,order date
.
- Using the
- In the file
/tests/database/test_database.py
, create the testtest_database_connection
:
- The test has the
database
marker. - In the test body, create an instance of the
Database
class. - In the test body, execute the
test_connection
object method.
- In the file
/tests/database/test_database.py
, create the testtest_check_all_users
:
- The test has the
database
marker. - In the test body, create an instance of the
Database
class. - In the test body, execute the
get_all_users
object method. - Print the result of executing the
get_all_users
object method to the terminal.
- In the file
/tests/database/test_database.py
, create the testtest_check_user_sergii
:
- The test has the
database
marker. - In the test body, create an instance of the
Database
class. - In the test body, execute the
get_user_address_by_name
object method with the parametername = Sergii
. - Verify that the data returned by the
get_user_address_by_name
method corresponds to the following data:1. Maydan Nezalezhnosti 1 2. Kyiv 3. 3127 4. Ukraine
- In the file
/tests/database/test_database.py
, create the testtest_product_qnt_update
:
- The test has the
database
marker. - In the test body, create an instance of the
Database
class. - In the test body, execute the
update_product_qnt_by_id
object method with the parametervalues product_id = 1
andqnt = 25
. - Verify that after updating the data, the quantity of the product with the unique number
1
is equal to25
.
- In the file
/tests/database/test_database.py
, create the testtest_product_insert
:
- The test has the
database
marker. - In the test body, create an instance of the
Database
class. - In the test body, execute the
insert_product
object method with the parameter valuesproduct_id = 4
,name = печиво
,description = солодке
,qnt = 30
. - Verify that after updating the data, the quantity of the product with the unique number
4
is equal to30
.
- In the file
/tests/database/test_database.py
, create thetest test_product_delete
:
- The test has the
database
marker. - In the test body, create an instance of the
Database
class. - In the test body, create test data by creating a product in the
products
table with the parameter valuesproduct_id = 99
,name = тестові
,description = дані
,qnt = 999
. - In the test body, delete data from the
products
table with the parameter valueproduct_id = 99
. - Verify that the number of rows found is equal to
0
.
- In the file
/tests/database/test_database.py
, create the testtest_detailed_orders
:
- The test has the
database
marker. - In the test body, create an instance of the
Database
class. - In the test body, print to the terminal the result of executing the
get_detailed_orders
method of theDatabase
class object. - Verify that the number of found results is equal to
1
. - Verify that the data returned by the
get_detailed_orders
method corresponds to the following data:1. 1 2. Sergii 3. солодка вода 4. з цукром
In the cloned repository, develop tests using the pytest
and selenium
modules that meet the following requirements:
-
The
ui
marker is registered in thepytest.ini
file. -
In the
modules/ui/page_object
directory, create a file namedbase_page.py
, and define a class namedBasePage
in it.
- In the class constructor, initialize an object for communication with the web driver.
- The class should have a close method whose task is to close the open browser.
- In the
modules/ui/page_object
directory, create a file namedsign_in_page.py
, and in it, define a class namedSignInPage
.
- The
SignInPage
class should inherit from theBasePage
class. - In the class constructor, call the constructor of the parent class.
- Implement a method of the object that takes
username
andpassword
as parameters. The task of the method is to enter theusername
into the email field, thepassword
into the password field, and click the sign-in button. - Implement a method of the object that checks whether the page title matches the expected title.
- In the
tests/ui
directory, create a file namedtest_ui_page_object.py
. In this file, create a test that:
- Has the
ui
marker. - Performs the following steps:
- Opens the
Sign In
page. - Enters incorrect data into the
username
andpassword
fields. - Checks whether the page title matches the expected title.
- Closes the browser.
- Opens the