Python pytest workshop part 2
This is part two of 211209-1354 Python testing basics with poetry and pytest. Fixtures scopes work similarly to the various setup/teardown functions of unittest, can be per module/class/etc.
Expecting a test to fail
@pytest.mark.xfail(reason="Reason why it's supposed to fail") def test_...
Expecting a test to raise an exception
For a specific exception, you assert that it raises that exception type and then can do asserts on the exception that is raised.
def test_whatever(): with pytest.raises(Exception) as excinfo: raise Exception("oh no") assert str(excinfo.value) == "oh no"
Regex also works (example directly from
pytest.raises() API Reference
>>> with pytest.raises(ValueError, match=r'must be \d+$'): ... raise ValueError("value must be 42") ## Services (skipped, see below) ### Creating fixtures that get used automatically ```python @pytest.fixture(autouse=True) def skip_servicetest(request, run_services): if request.... pytest.skip("skipped because X")
Using the filesystem
pyfakefs creates a fake filesystem that gets used transparently.
from pyfakefs.fake_filesystem import FakeFilesystem @pytest.fixture def common_fs(fs: FakeFilesystem): fs.create_dir(Path("/tmp/common")) fs.create_file("/tmp/common") def test_filesystem_fixture(common_filesystem): assert os.path.exists("/tmp/common") assert os.path.exists("/tmp/not_there") == False
A development approach from TDD.
- Red - Write a test, it fails
- Forces us to think about what we want to develop and how do we want to use the interface we’re about to implement.
- Green - Make it pass (as fast as possible)
- If it’s simple, just type it
- If it’s harder, make a note and write the quickest solution that makes the test pass
- Refactor - Spend time to make the implementation correct.
Tests should be:
- Fast (encourages us to run them frequently, which increases confidence in the code)
- Independent (not influence each other)
- Repeatable (in any environment)
- Self-validating (a failing test should give enough info about what’s wrong1)
- Timely written (just before the production code)2
3A is a common pattern for structuring tests.
- Arrange -> Create objects / prepare the environment
- Act -> Simulate behaviour
- Assert -> Check the results
In a test this would look like this:
string = "ABc" result = string.upper() assert result == "ABC"