SECRET OF CSS

Writing Automation Test Scripts With Python | by Ng Wai Foong | Aug, 2022


Level up your testing game with pytest

Photo by Rock’n Roll Monkey on Unsplash

Testing is an important aspect of the software development lifecycle. Long gone are the days when software was 100% manually tested. Most companies are leveraging automation tools as part of the testing lifecycle. These tools help to control and automate the execution of tests on each commit or update to the code base.

Test automation is key to a successful project that follows the Agile or DevOps methodology. It significantly improves the efficiency and accuracy of your product during each release.

In this tutorial, we are going to learn about a Python testing module called pytest. Based on its official documentation, pytest is:

“… an open-source framework to write small tests, yet scales to support complex functional testing for applications and libraries.”

Let’s proceed to the next section and start installing the necessary modules.

It is highly recommended to create a virtual environment before you continue. Activate your virtual environment and run the following command:

pip install pytest

You can confirm the installation via

pip show pytest

or

pytest -h

In this section, we are going to learn about the fundamental concepts behind pytest.

To begin, create a new Python file in your working directory called utils.py. The file serves as the utility function for our test case. Add the following code inside the file:

def add(x, y):
return x + y
def subtract(x, y):
return x - y
def multiply(x, y):
return x * y

Creating a test script

After that, create a new Python file called test_app.py. You can name it anything that you prefer, but it must follow either of the following syntax:

  • starts with test_
  • ends with _test

Let’s create a few test functions inside test_app.py file. pytest automatically executes functions that start with test_ prefix. All you need to do is to add assertions inside the functions. For example,

Running the test

Once you are done with it, run the following command at your terminal:

pytest

You should see the following output:

1*TZjoyGVQ9L25O9mDIJ7ztg
Image by author

You can specify -v argument for verbose output:

pytest -v

Running the command above yields the following output:

1*yNghGprz p7vOiZqqQUyig
Image by author

Let’s create a failed test case to understand how pytest reports errors. Inside test_app.py, change the following assertion from

assert utils.multiply(3, 3) == 9

to:

assert utils.multiply(3, 3) == 8

Run the test again, and you should get the following expected output for a failed test case:

1*0 T6 K XC31rS4ZGpqo5bg
Image by author

Change the value back to 9 once you are done with it.

You can group some of the test functions inside a class. The class has to start with Test prefix for it to take effect.

Using substring expression

If you intend to run only a subset of the test functions, you can choose to do it via:

  • substring expression, or
  • marker

For the first use case, simply specify the -k argument followed by the desired string. For example, the following command will only run functions that contain the substring add:

pytest -k add -v

Notice that pytest collected three functions and only ran one of them:

1*eE9YOlYCwHu8dDPHsyoWHQ
Image by author

Using Markers

Furthermore, you can also use markers to subset your test functions into different groups. Add the following import statement at the top of the file:

import pytest

Then, decorate the desired function with the following decorator. name represents the custom name for the marker. You can name it anything that you like.

@pytest.mark.<name>

I am going to mark two functions using basic as the name:

For markers, you need to call -m argument instead as follows:

pytest -m basic -v

The following output will be displayed at your terminal.

1*Hw9QqXqlAsJpHGOGjndsZw
Image by author

Do not be alarmed by the warnings, as it indicates that your marker is not registered yet. Simply create a new file called pytest.ini in the same directory. Add the following configuration inside it:

[pytest]
markers =
basic

You can add an optional description to it as follows:

[pytest]
markers =
basic: mark test as basic

pytest comes with built-in parametrize marker, which allows you to parameterize input value to your functions. Let’s modify test_multiplication function to accept two input parameters:

  • input value for multiplication
  • expected output

You should end up with the following code snippet:

def test_multiplication(self, value, output):
assert utils.multiply(value, value) == output

Then, decorate the function as follows:

@pytest.mark.parametrize("value, output", [(2, 4), (3, 9), (4, 16), (5, 25)])
def test_multiplication(self, value, output):
assert utils.multiply(value, value) == output

You must provide a string representation of the expected input as the first parameter to the decorator.

The second parameter represents the input values passed to the function during testing. Since I have specified four items in the list, pytest will run test_multiplication four times using the corresponding values.

You should get the following output when you run the test:

1*E0i7H4ee2OzZ OdFn3Salw
Image by author

Besides, you can store the test data in a variable and reuse it again on other test functions:

data = [(2, 4), (3, 9), (4, 16), (5, 25)]

Our final test script is as follows:

Let’s recap what we have learned today.

We started with a brief explanation of the importance of testing and why we should automate the testing process.

Next, we installed pytest module in our virtual environment.

We moved on to implement three basic functions and created the corresponding test functions. Besides, we also learned to group functions to create subset test cases using either substring expression or markers.

Finally, we explored decorating our test functions with parameterize decorator.

Thanks for reading this piece. Hope to see you again in the next article!

  1. Pytest’s Github
  2. Pytest’s Documentation
  3. Pytest’s Tutorialspoint
  4. Introduction to unittest: a Unit Testing Framework in Python



News Credit

%d bloggers like this: