Unit testing with Python

Testing your Python libraries is a great idea! Here is a simple example of how you could implement unit tests for a business logic library written in Python.

See Unit testing with Robot Framework if you want to use Robot Framework for testing your libraries.

The business logic library

The Python library implements a function for calculating net income based on revenues and expenses.

accounting.py:

import math


def net_income(revenues: float, expenses: float, decimals=2) -> float:
    # Revenues - Expenses = Net Income
    #
    # Revenues are the sales or other positive cash inflow that comes into
    # your company. Expenses are the costs that are associated with making
    # sales. By subtracting your revenue from your expenses, you can calculate
    # your net income. This is the money that you have earned at the end of
    # the day. It's possible that this number will be negative when your
    # business is in its nascent stage, so the goal is for your business' net
    # income to become positive, meaning your business is profitable.
    #
    # https://quickbooks.intuit.com/global/resources/bookkeeping/8-accounting-formulas-every-business-should-know/
    multiplier = 10 ** decimals
    net_income = revenues - expenses
    return math.floor(net_income * multiplier + 0.5) / multiplier

See How to write your own Robot Framework libraries in Python for more information.

Import pytest framework as a dependency

pytest is the de facto standard framework for testing Python code.

Create a test_conda.yaml configuration file and add pytest as a dependency:

channels:
  - conda-forge

dependencies:
  - python=3.7.5
  - pytest=6.2.2

See Adding packages to your robot for more information.

Create a configuration file for running the tests

Create a test_robot.yaml configuration file for running the pytest command:

tasks:
  Default:
    command:
      - pytest

condaConfigFile: test_conda.yaml
artifactsDir: output
PATH:
  - .
PYTHONPATH:
  - .
ignoreFiles:
  - .gitignore

See Robot YAML configuration format for more information.

Implement tests for the business logic library

Create a test_accounting.py file for implementing the tests for the business logic:

pytest will run all files of the form test_*.py or *_test.py in the current directory and its subdirectories.

test_accounting.py:

from accounting import net_income


def test_net_income_should_equal_revenues_minus_expenses():
    assert net_income(1256.25, 930.33) == 325.92
    assert net_income(3.0, 2.0) == 1.0
    assert net_income(100.20, 462.12) == -361.92
    assert net_income(200.0, 200.0) == 0

Run the tests with RCC

rcc run --robot test_robot.yaml

See RCC toolchain for more information.

test_accounting.py .                                                     [100%]

============================== 1 passed in 0.01s ===============================

More complex use cases

"Sometimes tests need to invoke functionality that depends on global settings or invokes code that cannot be easily tested, such as network access." - pytest.org

pytest supports mocking or monkeypatching. Read the full pytest documentation to learn about all the supported features.