how to run tests automatically

In the previous chapters

  • I ran python3 -m unittest to see the test fail

  • I ran python3 -m unittest every time I made a change until the test passed

I run python3 -m unittest for each part of the Test Driven Development Cycle or any time there is a code change. I want the computer to automatically run the tests for me.


preview

This is one way to automatically run tests in a Python Test Driven Development project. By the end of the chapter you will know these commands better

cd
echo
tree
cat
uv run pytest-watcher
source .venv/bin/activate
deactivate
history

questions about how to run tests automatically

Questions to think about as I go through the chapter


open the project

  • I change directory to the person folder

    cd person
    

    the terminal shows I am in the person folder

    .../pumping_python/person
    
  • I use tree to see what the project looks like, as a reminder

    tree -a -L 2
    

    the terminal shows

    .
    ├── .git
       ├── config
       ├── description
       ├── FETCH_HEAD
       ├── HEAD
       ├── hooks
       ├── info
       ├── objects
       └── refs
    ├── .gitignore
    ├── pyproject.toml
    ├── .python-version
    ├── README.md
    ├── src
       └── person.py
    └── tests
        ├── __init__.py
        ├── __pycache__
        └── test_person.py
    
  • I can use pytest-watcher to run tests automatically. It is a Python program that automatically runs pytest any time a Python file changes in the folder it is looking at, this means it will run the tests for me every time I make a change.

    pytest is a Python package like unittest that is used for testing. It is not part of The Python Standard Library.

    I use uv to run pytest-watcher in the terminal

    uv run pytest-watcher
    

    the terminal is my friend, and shows

    Using CPython 3.X.Y
    Creating virtual environment at: .venv
    error: Failed to spawn: `pytest-watcher`
      Caused by: No such file or directory (os error 2)
    
  • I use tree to see what the project looks like now

    tree -a -L 2
    

    the terminal shows

    .
    ├── .git
       ├── config
       ├── description
       ├── FETCH_HEAD
       ├── HEAD
       ├── hooks
       ├── info
       ├── objects
       └── refs
    ├── .gitignore
    ├── pyproject.toml
    ├── .python-version
    ├── README.md
    ├── src
       └── person.py
    ├── tests
       ├── __init__.py
       ├── __pycache__
       └── test_person.py
    └── .venv
        ├── bin
        ├── CACHEDIR.TAG
        ├── .gitignore
        ├── lib
        ├── lib64 -> lib
        ├── .lock
        └── pyvenv.cfg
    

    uv made a virtual environment in a folder named .venv with files and folders.


what is a virtual environment?

A virtual environment is a separate folder where I can install Python packages that my project needs. This helps me keep things that belong to the project in one place, separate from other things on the computer.

It means I can have a separate virtual environment for every project with only the programs that the project needs. I do not have to keep every program I have ever used for projects that do not need them.


how to write text to a file

I want to make a file where I list all the Python packages that my project needs as a way to document it and have uv install the programs listed in the file

  • I can write text to a file with the echo program, it shows whatever it is given as an argument, on the screen. For example, if I type this in the terminal

    echo "hi, my name is Jacob"
    

    it shows

    hi, my name is Jacob
    
  • I can also use echo to add text to a file. I use it to make the requirements file with pytest as what is inside it

    echo "pytest" > requirements.txt
    
  • I use tree to see what the project looks like now

    tree -a -L 1
    

    the terminal shows

    .
    ├── .git
    ├── .gitignore
    ├── pyproject.toml
    ├── .python-version
    ├── README.md
    ├── requirements.txt
    ├── src
    ├── tests
    └── .venv
    

    requirements.txt is now in the person folder

  • I use the cat program to look at what is in requirements.txt

    cat requirements.txt
    

    the terminal shows

    pytest
    
  • I add pytest-watcher to the requirements file as well

    echo "pytest-watcher" >> requirements.txt
    
    • >> is an operator that is used to send output from a program to the given file, it adds to what is in the file without writing over it

    • pytest-watcher is a Python program that automatically runs pytest when I change code in the project

  • I use cat to look at what is in requirements.txt now

    cat requirements.txt
    

    the terminal shows

    pytest
    pytest-watcher
    

    life is good!


how to install Python packages with uv

  • I use uv to install pytest-watcher from the requirements file

    uv add --requirement requirements.txt
    
    • --requirement is an option that can be given to the add argument for Python packages in a given file

    • requirements.txt is the name of the given file. It helps to manage Python programs that are needed by the project. In this case I only have two programs. A project can have a big number of programs it needs and using one file with one command is easier than one command for each program

    the terminal is my friend, and shows setup and installation

    Resolved 9 packages in GHIms
    ░░░░░░░░░░░░░░░░░░░░ [0/7] Installing wheels...
    ...
    Installed 7 packages in JKLms
     + iniconfig==A.B.C
     + packaging==DE.F
     + pluggy==G.H.I
     + pygments==J.K.L
     + pytest==M.N.O
     + pytest-watcher==P.Q.R
     + watchdog==S.T.U
    
  • I run tree to see what changed in the project

    tree -a -L 1
    

    the terminal shows

    .
    ├── .git
    ├── .gitignore
    ├── pyproject.toml
    ├── .python-version
    ├── README.md
    ├── requirements.txt
    ├── src
    ├── tests
    ├── uv.lock
    └── .venv
    

    uv added uv.lock a file that has the exact versions of the Python programs that were installed.

  • I use cat to show what is now in pyproject.toml

    cat pyproject.toml
    

    the terminal is my friend, and shows

    [project]
    name = "person"
    version = "0.1.0"
    description = "Add your description here"
    readme = "README.md"
    requires-python = ">=3.XY"
    dependencies = [
        "pytest>=M.N.O",
        "pytest-watcher>=P.Q.R",
    ]
    

    it added pytest and pytest-watcher to the dependencies of the project.


how to activate a virtual environment

When I want to work in a virtual environment, I make sure I am in the parent folder of the virtual environment. In this case person is the parent. I activate the virtual environment in the terminal to use it

source .venv/bin/activate

the terminal is my friend, and shows

(person) .../pumping_python/person

(person) on the far left of the command line in the terminal shows that I am working in the virtual environment.


how to deactivate a virtual environment

I can leave the virtual environment by typing deactivate in the terminal

deactivate

the terminal goes back to the command line

.../pumping_python/person

(person) is no longer on the left side.


how to run tests automatically with uv and pytest-watcher

  • I open test_person.py from the tests folder

  • I change assert False is False to assert False is True in test_person.py

    # False is True
    assert False is True
    # assert False is False
    
    
    # Exceptions seen
    # AssertionError
    
  • I go back to the terminal to run the test again

    uv run pytest-watcher . --now
    

    the terminal is my friend, and shows an error without going back to the command line

    pytest-watcher version X.Y.Z
    Runner command: pytest
    Waiting for file changes in .../pumping_python/person
    =================== test session starts ====================
    platform ____ -- Python 3.A.B, pytest-C.D.E, pluggy-F.G.H
    rootdir: .../pumping_python/person
    configfile: pyproject.toml
    collected 0 items / 1 error
    
    ========================== ERRORS ==========================
    ___________ ERROR collecting tests/test_person.py ___________
    tests/test_person.py:2: in <module>
        assert False is True
    E   assert False is True
    ================= short test summary info ==================
    ERROR tests/test_person.py - assert False is True
    !!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!
    ===================== 1 error in I.JKs =====================
    [pytest-watcher]
    Current runner args: []
    Press w to show menu
    

how to open the test file in the editor from the terminal

  • I hold ctrl (Windows/Linux) or option/command (MacOS) on the keyboard, then click on tests/test_person.py to go back to test_person.py. I change True to False on line 2

    1# False is True
    2# assert False is True
    3assert False is False
    4
    5
    6# Exceptions seen
    7# AssertionError
    

    the terminal is my friend, and shows AssertionError

    [ptw] Detected modified: ./tests/test_person.py ->
    =================== test session starts ====================
    platform ____ -- Python 3.A.B, pytest-C.D.E, pluggy-F.G.H
    rootdir: .../pumping_python/person
    configfile: pyproject.toml
    collecting ... [ptw] Detected modified: ./tests/test_person.py ->
    [ptw] Detected modified: ./tests/test_person.py ->
    collected 0 items
    
    ================== no tests ran in 0.01s ===================
    
    [pytest-watcher]
    Current runner args: []
    Press w to show menu
    
    • pytest-watcher “saw” the change I made to test_person.py and ran the test again

    • the terminal shows no tests ran which is confusing since the only way I know the test passed, is because I saw it fail

I can write the rest of the code for the project and get results back quickly because the tests run when I change the code.

I want to write code that represents a person, after I learn what an assertion is.


how to stop the automated tests

I go to the terminal and use q on the keyboard to stop the tests, the terminal goes back to the command line.

.../pumping_python/person

close the project

  • I click in the terminal then add the new files and folders to git for tracking

    git add .
    

    the terminal goes back to the command line.

  • I add a git commit message

    git commit --all --message \
    'automate tests'
    

    the terminal shows a summary of the changes then goes back to the command line.

  • I close test_person.py

  • I change directory to the parent of person

    cd ..
    

    .. is for the parent of any directory I am in. the terminal shows

    .../pumping_python
    

    I am back in the pumping_python folder.


review


how to view all the commands I typed to automate running tests



How many questions can you answer after going through this chapter?


what is next?

You know

Would you like to know what causes AssertionError


rate pumping python

If this has been a 7 star experience for you, please CLICK HERE to leave a 5 star review of pumping python. It helps other people get into the book too.