Boost Your Code Quality with Pytest & Tox

Enhance Your Code Quality with “The Matured Testing Framework — Pytest & Tox”

ronilpatil
Towards AI

--

Image by Author

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.

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.

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/
|
├── 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!!! 🤯

Here’s the Trick 🎃, 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

Image by Author

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 you🙌 &,
Keep pushing boundaries🚀
Cheers to bug-free coding🍻

--

--