Boost Your Code Quality with Pytest & Tox
Last Updated on March 31, 2024 by Editorial Team
Author(s): ronilpatil
Originally published on Towards AI.
In the realm of software development, ensuring code quality isn’t just a goal, it’s a mandate. With the ever-increasing complexity of applications, the need for robust testing methodologies has never been more critical. Enter unit testing — the cornerstone of a solid quality assurance strategy.
In this blog, we’ll take our journey toward code confidence using two powerful tools — Pytest & Tox. Pytest, with its simplicity and flexibility, provides an elegant framework for writing and executing unit tests with ease. On the other hand, Tox enables us to create and manage local testing environments, ensuring consistency and reproducibility across different platforms and configurations.
If you haven’t gone through my previous series of blogs, I’ll recommend you to go through it.
Streamline ML Workflow with MLflow️ — I
PoA — Experiment Tracking U+1F504 U+007C Model Registry U+1F3F7️ U+007C Model Serving U+1F680
pub.towardsai.net
Streamline ML Workflow with MLflow — II
PoA — Experiment Tracking U+1F504 U+007C Model Registry U+1F3F7️ U+007C Model Serving
pub.towardsai.net
This is the next move in this series of blogs, here first I’ll explain “How can we create a local testing environment using Tox”, and then will test our code quality using Pytest.
Tox — Build QA Environment
First, install the tox using pip.
cmd: pip install tox
Once tox is installed, create tox.ini
configuration file. It defines various settings and options for running tests in multiple environments, such as different Python versions or with different dependencies. Below added tox.ini
config file for reference.
Here we will test our code on Python version 3.9 & 3.12. skipsdist = True
will skip the step of creating a distribution package during the testing process. Currently, our focus is to quickly iterate and test our code during development.
The [testenv]
section is a required section in the tox.ini
file and is used to define the default settings for test environments. When we define [testenv]
, Tox will automatically create a virtual environment for each environment listed in envlist
and apply the settings specified under [testenv]
. The name [testenv]
itself is not something we can change, it's a predefined section header that Tox recognizes. We can create as many [testenv]
sections as we need, each with its own set of dependencies and commands.
All the dependencies are specified using the deps
option under the [testenv]
section. The -r
flag indicates that Tox should read the dependencies from a requirements file.
The command to execute within the test environment is specified using commands
option under the [testenv]
section. In this case, it tells Tox to run Pytest with specific options (--verbose
for detailed output and --disable-warnings
to suppress warnings) on the test files located in the tests/
directory.
We can execute multiple test files or commands on different Python versions. Below, I added the GitHub repo link, you can check it out.
GitHub – Built an E2E MLFlow Pipeline
Contribute by ronylpatil
github.com
Pytest — The Matured Testing Framework
Instead of diving into theory, let’s jump to practical examples.
This is the simple testing code I’ve written to help you understand it better. I used a fixture
decorator on the top of add_num
the function to extend its functionality. And used params
an argument to test the function on various sets of parameters. Pytest will invoke the fixture once for each parameter value specified in the list. Inside the fixture function, the request.param
attribute allows you to access the current parameter value being used. I’ve written simple logic, but we may implement more complex ones based on our requirements.
You must refer to the official document for more details. Now, let's look at the actual code. Remember, here’s how your folder structure would look with a “testing” directory.
project_name/
U+007C
├── testing/ (This is where your tests go, we can use any name)
│ ├── conftest.py
│ ├── test_module1.py (file name must begin with test)
│ └── test_module2.py
│
├── other directories...
In the above code snippet, I’ve written 8 test functions. All of them are using fixtures, but you may be surprised I’ve neither created nor imported any fixture in the codebase, but still, I’m getting results!!! U+1F92F
Here’s the Trick U+1F383, You can define fixtures in conftest.py
that provide a common setup or data for your tests. These fixtures can be used by any test file within the same directory and its subdirectories without the need of explicit imports, just pass the fixture as a parameter to your test function That’s it!!!
And everywhere I've used assert
statements, that check whether a condition is true, and if not, it raises an AssertionError
. That’s it!
Below added conftest.py
for your reference.
Output Snapshot
Basic Commands
1. cmd: tox -r
-- recreate the tox virtual environments from scratch
-- use if requirements.txt updated
2. cmd: tox
-- runs test environments defined in the tox.ini file
3. cmd: tox -e py3.9
--- runs the tox environment specified for Python v3.9, instead of py3.9
--- can use any python version
4. cmd: pytest
--- search for test files and run test functions
5. cmd: pytest testing/
--- runs tests present within the specified directory named "testing"
6. cmd: pytest testing/xyz.py
--- run specific test file present in "testing" directory
7. cmd: pytest testing/xyz.py::test_build_features
--- test specific function present in xyz.py test file
Tox vs Pytest Commands
Tox run the test specified in tox.ini
across different Python versions and environments configured in tox.ini
It is used to automate the execution of Pytest tests across different Python versions and environments.
Pytest is a testing framework used specifically for running Python tests. It provides a simple and flexible way to write and execute tests for Python code. If you use the Pytest command, the code will be tested in the current virtual environment. To execute the test in the Tox environment, use Tox commands. Both Tox & Pytest have different purposes in the context of testing.
Conclusion
That’s all, guys, I hope you enjoyed the blog. If this blog sparked your curiosity or ignited new ideas, follow me on Medium, GitHub & connect on LinkedIn, and let’s keep the curiosity alive.
Your questions, feedback, and perspectives are welcomed and celebrated. Feel free to reach out with any queries or share your thoughts.
Thank youU+1F64C &,
Keep pushing boundariesU+1F680
Cheers to bug-free codingU+1F37B
Join thousands of data leaders on the AI newsletter. Join over 80,000 subscribers and keep up to date with the latest developments in AI. From research to projects and ideas. If you are building an AI startup, an AI-related product, or a service, we invite you to consider becoming a sponsor.
Published via Towards AI