Testing in Python
Writing good unit tests in Python with ease — Part 3
Part 3: Testing workflow tips
This article series is aimed at people working in the public sector (like me), academics and students, people new to their careers in the private sector and anyone else for whom testing code is not yet second nature. When I refer to “tests” or “testing” in this article the context is constrained to unit and component/modular tests. My experience is mostly derived from building analytical pipelines in Python using pandas
and pyspark
and testing in pytest
.
The series started as a written summary of a presentation given to the Office for National Statistics on Feb 26 2021. There is also an accompanying GitHub repo with some more advanced test parameterisation examples and other resources.
Here is a list of the articles in this series:
- Part 1: Why you should write unit tests
- Part 2: The basics of testing with pytest
- Part 3: Testing workflow tips (this article)
Here are the topics covered in this chapter:
Test Shells
If you can’t write your test straight away, write a test shell so you know to come back to it!
Snakes in the Grass 🐍
Mark your test shells using pytest.mark.skip(reason="test_shell")
so that you can see where you have missing tests from pytest
output at a glance.
Bash Bindings
Add these to your .bashrc
to quickly cycle through your recent pytest
commands in your bash history.
VS Code Shortcuts
I find the VS Code shortcuts extremely helpful for manipulating hard coded test data. They take a lot of the pain out of the process. I demo my favourite ones in this article.
VS Code Snippets
You can configure VS Code snippets for repeatable code patterns that occur in test scripts. Read more on snippets in the official docs and see some more of my own snippets defined in this JSON.
Rules that you can break
There are some rules I feel comfortable breaking in my test scripts. These are:
- Having max line length over 72 chars
- Not obeying all docstring conventions
- Not being DRY — at least not when starting out
As always, use your own judgement, and try to be consistent above all else.
Common pitfalls
It is probably worth mentioning a couple of common pitfalls that have caught me out a few times. If you can think of any more, please leave a comment and I’ll add to this list:
- Grouping tests by class but forgetting to add
self
to the parameters.
The error message for this is probably going to cause a little confusion as it treats whatever parameter name is passed first instead as the class — self
is just a conventional name for that parameter anyway, so pytest
assumes you’ve just given it a different name when you probably forgot it altogether.
Here’s an example of what the error output looks like:
- Forgetting to declare something as a fixture
Luckily the error message for this one is a bit more straightforward.
- Doing too much — cut your functions down! Did I say this already? The number one thing that is going to slow down your testing process is trying to test functions that are doing too much logic in one go. Consider writing a component test to cover the main expected behaviour of your program, then refactor a large function into multiple smaller units.
Wrap Up
- OK — now you’ve read the article, go write some tests.
- Check out the accompanying GitHub repo for some additional resources.
- If you liked something about this article or found it interesting, please leave a “clap”.
- If you disagreed with something or have some additional tips to share then please leave a comment.
I hope these articles will be a good reference for you on your testing journey. Bon chance!