Automatically Rerun Pytest Tests on File Save

Automating tests is a crucial part of any development workflow, ensuring that your code remains reliable and free of regressions. In my journey as a developer, I’ve often found the need to rerun tests automatically whenever I make changes to my files. This not only saves time but also provides immediate feedback, allowing me to catch issues early in the development process. In this post, I’ll walk you through setting up Pytest to automatically rerun tests when you save changes to your files, including YAML configurations.

Thank me by sharing on Twitter 🙏

Getting Started with pytest-watch

To achieve automatic test reruns, I turned to the pytest-watch plugin, commonly referred to as ptw. This tool monitors your project files and triggers Pytest whenever it detects changes, streamlining the testing process significantly.

Installation and Basic Usage

First, installing pytest-watch is straightforward. Using pip, you can add it to your project’s virtual environment:

Bash
pip install pytest-watch

Once installed, initiating the watch process is as simple as running:

Bash
ptw

This command starts monitoring your project directory for any changes in .py files and reruns your tests automatically. However, to make this setup even more robust, especially when working with YAML files, some additional configuration is necessary.

Extending Watch to YAML Files

In many projects, YAML files are used for configurations, data schemas, or other essential settings. To ensure that changes to these files also trigger your tests, you need to configure ptw to watch for .yaml and .yml extensions alongside .py files.

Configuring File Extensions via Command Line

You can specify the file extensions directly in the command line using the --ext option:

Bash
ptw --ext=py,yaml,yml

This command instructs ptw to monitor .py, .yaml, and .yml files. Whenever any of these files are saved, ptw will automatically rerun your tests, ensuring that both your code and configurations are consistently validated.

Using a Configuration File for Consistency

To avoid typing the extensions every time you run ptw, creating a configuration file is a practical approach. By adding a .ptw file to your project’s root directory, you can define default settings that ptw will use each time it runs.

Create a .ptw file and include the following configurations:

INI
[pytest-watch]
ext = py,yaml,yml
clear = True
verbose = True
  • ext: Specifies the file extensions to monitor.
  • clear: Clears the terminal screen before each test run, making the output cleaner.
  • verbose: Increases the verbosity, providing detailed information about each test run.

With this configuration in place, running ptw without additional arguments will automatically use these settings:

Bash
ptw

This setup not only includes YAML files in the watch list but also enhances the readability and informativeness of your test runs.

Enhancing Workflow with Additional ptw Options

Beyond the basic setup, ptw offers a range of options that can further tailor your testing workflow to your specific needs. Here are some configurations that I’ve found particularly useful:

Ignoring Specific Directories

In large projects, there might be directories that you don’t want ptw to monitor, such as virtual environments or build directories. The --ignore option allows you to exclude these directories:

Bash
ptw --ext=py,yaml,yml --ignore=venv --ignore=build

This command ensures that changes in the venv and build directories don’t trigger unnecessary test runs, keeping the focus on relevant parts of your project.

Running Commands Before and After Tests

Automating additional tasks around your test runs can further streamline your workflow. For instance, you might want to run a linter before tests or execute a notification script after tests complete. The --beforerun and --afterrun options facilitate this:

Bash
ptw --ext=py,yaml,yml --beforerun="flake8 ." --afterrun="echo 'Tests Completed!'"
  • –beforerun: Executes flake8 to lint your code before running tests.
  • –afterrun: Prints a message indicating that tests have finished.

Debugging with Pytest’s Interactive Debugger

Encountering test failures is a natural part of development. To make debugging easier, the --pdb option integrates Pytest’s interactive debugger, allowing you to inspect the state of your application at the point of failure:

Bash
ptw --ext=py,yaml,yml --pdb

This setup halts the test run on failures and opens an interactive debugging session, providing immediate insight into what went wrong.

Adjusting Verbosity Levels

Depending on your preference for output detail, ptw allows you to adjust verbosity. Increasing verbosity can help in understanding the test run flow, while decreasing it can make the output cleaner:

  • Increase Verbosity: ptw --ext=py,yaml,yml -v
  • Decrease Verbosity: ptw --ext=py,yaml,yml -q

Handling Rapid File Changes with Spooling

In scenarios where multiple file changes occur in quick succession, such as during batch edits, it’s beneficial to introduce a slight delay before rerunning tests. The --spool option adds this buffer:

Bash
ptw --ext=py,yaml,yml --spool=500

This command adds a 500-millisecond delay, ensuring that ptw waits for file changes to stabilize before initiating a test run, thus preventing unnecessary multiple test executions.

Optimizing Test Runs for Large Suites

Working with a substantial number of tests can sometimes make reruns time-consuming. To mitigate this, consider the following strategies:

Using Test Markers

Pytest allows you to categorize tests using markers. By running only a subset of tests based on these markers, you can reduce the time taken for each test run:

Bash
ptw --ext=py,yaml,yml -- -m slow

This command runs only the tests marked with @pytest.mark.slow, which is useful for excluding longer-running tests during rapid development cycles.

Selecting Specific Test Directories

Instead of running the entire test suite, you can target specific directories or test files. This approach focuses the test runs on relevant areas, speeding up feedback:

Bash
ptw --ext=py,yaml,yml tests/unit/

By specifying the tests/unit/ directory, ptw monitors and runs tests only within this folder, making the process more efficient.

Leveraging a Comprehensive Configuration

To bring all these configurations together, you can structure your pytest.ini file to include multiple settings. Here’s an example that incorporates various options for an optimized testing workflow:

INI
[pytest-watch]
ext = py,yaml,yml
clear = True
verbose = True
ignore = venv,build
beforerun = flake8 .
afterrun = echo 'Tests Completed!'
pdb = True
spool = 300

This configuration ensures that ptw monitors the necessary file types, ignores irrelevant directories, runs a linter before tests, provides clear and verbose output, initiates debugging on failures, and handles rapid file changes gracefully.

Ensuring Smooth Operation

To maintain an efficient testing environment, it’s essential to address common issues that might arise:

ptw Not Detecting YAML File Changes

  • Check File Extensions: Ensure that your YAML files have the correct extensions (.yaml or .yml).
  • Verify Configuration: If using a .ptw file, confirm that the ext option includes both yaml and yml.
  • File Locations: Make sure that the YAML files are within the directories being watched. If you’re specifying particular directories, they should encompass all relevant YAML files.

Tests Not Running as Expected

  • Manual Test Execution: Run pytest manually to ensure that your tests pass and there are no configuration issues.
  • Review Plugin Compatibility: Some Pytest plugins might interfere with test discovery or execution. Disable them temporarily to identify conflicts.
  • Monitor ptw Output: Look for error messages or warnings in the terminal where ptw is running to diagnose issues.

Optimizing Test Performance

For larger test suites, consider parallelizing tests or using caching mechanisms to reduce execution time. Tools like pytest-xdist can run tests in parallel, significantly speeding up the testing process.

Final Thoughts

Setting up pytest-watch to automatically rerun tests on file saves, including YAML configurations, has transformed my development workflow. It provides immediate feedback, allowing me to focus on writing quality code without the repetitive task of manually rerunning tests. By leveraging the various configuration options available in ptw, I tailored the testing environment to fit my project’s specific needs, enhancing both efficiency and reliability.

Embracing automated testing tools like pytest-watch not only improves productivity but also contributes to maintaining a robust and error-free codebase. As projects grow in complexity, having such automated mechanisms in place becomes indispensable, ensuring that changes are continuously validated and that the development process remains smooth and effective.

Share this:

Leave a Reply