In-module tests with imports

George Shuklin
OpsOps
Published in
1 min readJun 13, 2023

There is a nice pattern for a scripts: you write their tests right in the script. It’s allow to bypass any import issues and just ship code and tests together.

This approach works perfectly if you have only simple tests:

def my_production_function(x):
if x > 0:
return x+1
else:
raise Exception("Negative")


### TESTS HERE


def test_1():
assert my_production_function(1) == 2

But what we can’t import anything test-related in the top-level of the module. May be this code will run inside an environment where we don’t have pytest. With simple tests it’s simple: you just have unused function (test_1, etc), which are ignored by normal code execution. If you write import pytest at the top of the file, you must have pytest in production, which is odd.

But, let’s say you want to test your function for exceptions. How? My old approach was to import pytest inside test:

def test_0():
import pytest
pytest.raises(Exception):
my_production_function(0)

It was okay… until it’s a one or two tests. If you have more of them, multiple imports slows everything down, and are ugly.

Today I found beautiful solution. Look at this!

def setup_module():
global pytest
import pytest


def test_0():
with pytest.raises(Exception):
my_production_function(0)


def test_negative():
with pytest.raises(Exception):
my_production_function(-1)

The trick is in setup_module where you can have global (top-level) variables. And module is a variable! Pytest runs setup_module before running tests, so, it’s importing pytest module. It’s a neat pytest-style trick.

--

--

George Shuklin
OpsOps

I work at Servers.com, most of my stories are about Ansible, Ceph, Python, Openstack and Linux. My hobby is Rust.