how to make a python test driven development environment


This is one way to make a Python Test Driven Development environment


requirements

windows requirements

If you are using a Windows computer, try to install Linux with Windows Subsystem Linux

  • click start

  • then type PowerShell

  • right click and select Run as administrator

  • then install Windows Subsystem Linux in the terminal

    wsl --install --distribution debian
    

    Tip

    do not worry if you cannot install Windows Subsystem Linux, I have you covered

linux requirements

run these commands in a terminal to install Python in Linux

sudo apt update
sudo apt install python3 python3-venv --yes

how to manually make a python test driven development environment

  • Imagine I have to work on a project called magic. I open a terminal in the Integrated Development Environment (IDE) and use mkdir to make a folder/directory for the project

    mkdir magic
    

    then change directory to the project with the cd program

    cd magic
    

    this is where all code for the project will stay

  • I make a child folder for the source code

    mkdir src
    

    then add an empty file for the source code (the actual program)

    touch src/magic.py
    

    on Windows without Windows Subsystem Linux use New-Item

    New-Item src/magic.py
    

    touch/New-Item makes an empty file when given a name

  • I make a child directory for the tests

    mkdir tests
    

    then an empty file called __init__.py in the tests folder to tell Python that it is a python package, this will help it find the tests later

    touch tests/__init__.py
    

    Warning

    make sure to use 2 underscores (__) for __init__.py

    on Windows without Windows Subsystem Linux use New-Item

    New-Item tests/__init__.py
    

    I add one more empty file in the tests directory for the actual test

    touch tests/test_magic.py
    

    on Windows without Windows Subsystem Linux use New-Item

    New-Item tests/test_magic.py
    

    you can use any name as long as it starts with test_

  • these are the folders/directories and files in the project

    magic
      ╰──src
      |  ╰──magic.py
      ╰──tests
         ╰──__init__.py
         ╰──test_magic.py
    

    py at the end of a file name shows it is a Python module


test_failure

The Test Driven Development cycle is RED GREEN REFACTOR

  • RED: make it fail - write a failing test to make sure the test works

  • GREEN: make it pass - write only what is needed to make the failing test pass

  • REFACTOR: make it better - remove duplication

red: make it fail

  • I open magic/tests/test_magic.py in the Integrated Development Environment (IDE) and type the following

    the line numbers below are a guide, you do not need to copy them

    1import unittest
    2
    3
    4class TestMagic(unittest.TestCase):
    5
    6    def test_failure(self):
    7        self.assertFalse(True)
    

    Here is an explanation of the code in the file

  • I turn on the Auto Save feature in the Integrated Development Environment (IDE) to automatically save files when I make a change so I do not repeat myself by manually saving every time there is a change

  • then type this in the terminal to run the test

    python3 -m unittest
    

    on Windows without Windows Subsystem Linux

    use python instead of python3

    python -m unittest
    

    and it shows a failure

    F
    =============================================================
    FAIL: test_failure (tests.test_magic.TestMagic.test_failure)
    -------------------------------------------------------------
    Traceback (most recent call last):
    File ".../magic/tests/test_magic.py", line 7, in test_failure
        self.assertFalse(True)
    AssertionError: True is not false
    
    -------------------------------------------------------------
    Ran 1 test in A.XYZs
    
    FAILED (failures=1)
    

If you are typing along, CONGRATULATIONS! You just wrote a test.

This is the RED part of the Test Driven Development cycle. The message in the terminal is about the failure, here is an explanation from the bottom up

  • FAILED (failures=1) the number of failures

  • Ran 1 test in A.XYZs the number of tests run and how long it took

  • AssertionError: True is not false the Exception raised and its message, in this case AssertionError is raised because True is not False

  • self.assertFalse(True) the line of code that caused the failure

  • File ".../magic/tests/test_magic.py", line 7, in test_failure the line number and location of the file where the failure happened

    Tip

    Hold ctrl (windows/linux) or option (mac) on the keyboard and use the mouse to click on File ".../magic/tests/test_magic.py", line 7 with your mouse in the terminal, and the Integrated Development Environment (IDE) will open the file in the editor with the cursor at the line where the failure happened

  • Traceback (most recent call last): all the information shown after this line that is indented to the right shows the calls that led to the failure

  • FAIL: test_failure (tests.test_magic.TestMagic.test_failure) is a header with information in dot notation about the failing test method

    • tests.test_magic.TestMagic.test_failure is the location of the failing test

    • tests is the tests folder

    • test_magic is the test_magic.py file

    • TestMagic is the class defined on line 4

    • test_failure is the method defined on line 6

  • F indicates a failure

  • python3 -m unittest is the command to run tests with the unittest module

    • python3 is the major version of Python being used

    • -m is an option passed to Python to run the module given after the option as a script

  • I recommend you keep a list of Exceptions you meet to become familiar with them, it helps when you run into failures later. Time to add AssertionError to the list

    import unittest
    
    
    class TestMagic(unittest.TestCase):
    
        def test_failure(self):
            self.assertFalse(True)
    
    # Exceptions Encountered
    # AssertionError
    

green: make it pass

I change the input on line 7 from True to False

self.assertFalse(False)

then run the test again in the terminal

python3 -m unittest

on Windows without Windows Subsystem Linux use python instead of python3

python -m unittest

and it shows a passing test

.
------------------------------------------------------
Ran 1 test in A.XYZs

OK

cue CELEBRATION MUSIC AND DANCE! I am GREEN.

refactor: make it better

I ran python3 -m unittest to see the test fail, ran it again to see the test pass. I will have to run it again when I make a code change, to make sure tests that were passing are not failing and the new code does what I expect. This means it is run for each part of the Test Driven Development cycle or any time there is a code change. I do not want to type python3 -m unittest again, it is better for a program to run the tests so I do not repeat myself.


how to automatically run tests

how to make a virtual environment

  • I make a virtual environment with the venv module

    python3 -m venv .venv
    

    on Windows without Windows Subsystem Linux use python instead of python3

    python -m venv .venv
    
  • I activate the virtual environment to use it

    source .venv/bin/activate
    

    on Windows without Windows Subsystem Linux run PowerShell in Administrator mode and set the Execution Policy for the activation script to work

    Set-ExecutionPolicy RemoteSigned
    

    the terminal shows

    The execution policy helps protect you from scripts that you do not trust.
    Changing the execution policy might expose you to the security risks
    described in the about_Execution_Policies help topic at
    https:/go.microsoft.com/fwlink/?LinkID=135170.
    Do you want to change the execution policy?
    
    [Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "N"):
    

    Type Y to confirm the change and it will enable scripts that have been signed by a verified publisher to run on your computer, you can read more at Set-ExecutionPolicy

    To activate the virtual environment, go back to the terminal you were working in before the Execution Policy change and type

    .venv/scripts/activate
    

    or

    .venv/scripts/activate.ps1
    

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

    (.venv) .../magic $
    
  • I upgrade pip the python package manager to the latest version

    python3 -m pip install --upgrade pip
    

    on Windows without Windows Subsystem Linux use python instead of python3

    python -m pip install --upgrade pip
    
    • pip is a module from the python standard library, it is used to install python packages

    • install is an argument given to pip to install a given package name

    • --upgrade is an option given to the install argument for pip to upgrade the version of the python package given

    • pip is the package name given for pip to install, in this case it upgrades itself

  • I can use pip to see what packages are installed in the virtual environment

    pip list
    

    and the terminal shows

    Package Version
    ------- -------
    pip     x.y.z
    
  • I make a file in the magic directory with pytest-watch as its text

    echo pytest-watch > requirements.txt
    

    on Windows without Windows Subsystem Linux type this

    "pytest-watch" | Out-File requirements.txt -Encoding UTF8
    
    • echo is a program that writes its given arguments to the standard output (stdout)

    • > is an operator that is used to send output from a program to the given file

    • | is an operator that is used to send output from the left as input to the right

    • Out-File writes input text to a given file

    • pytest-watch is a Python program that automatically runs pytest when a Python file in the folder changes

    • pytest is a python package like unittest that is used for testing

    • requirements.txt is the name of a file where I can list python packages for pip to install, you can use any name

  • I install pytest-watch and its dependencies

    pip install --requirement requirements.txt
    
    • --requirement is another option that can be passed to the install argument for python packages in a given file

    • requirements.txt is the name of the file given

  • I use pip to see the packages that are now installed in the virtual environment

    pip list
    

    and the terminal shows

    Package      Version
    ------------ -------
    colorama     x.y.z
    docopt       x.y.z
    iniconfig    x.y.z
    packaging    x.y
    pip          x.y
    pluggy       x.y.z
    pytest       x.y.z
    pytest-watch x.y.z
    watchdog     x.y.z
    
  • The folder/directory structure now looks like this

    magic
      ╰──.venv
      ╰──src
      | ╰──magic.py
      ╰──tests
      |  ╰──__pycache__
      |  ╰──__init__.py
      |  ╰──test_magic.py
      ╰──requirements.txt
    
  • I run the tests from the terminal

    pytest-watch
    

    and it shows results without going back to the command line

    [TODAYS_DATE] Running: py.test
    ================== test session starts===================
    ...
    rootdir: .../magic
    collected 1 item
    
    tests/test_magic.py .                              [100%]
    
    =============== 1 passed in X.YZs =======================
    
  • when I change the input on line 7 in test_magic.py from False to True it shows AssertionError

    ====================================== FAILURES =======================================
    _______________________________ TestMagic.test_failure ________________________________
    
    self = <tests.test_magic.TestMagic testMethod=test_failure>
    
        def test_failure(self):
    >       self.assertFalse(True)
    E       AssertionError: True is not false
    
    tests/test_magic.py:7: AssertionError
    ============================== short test summary info ================================
    FAILED tests/test_magic.py::TestMagic::test_failure - AssertionError: True is not false
    ================================= 1 failed in X.YZs ===================================
    

    then I change it back to False to make it pass and can write the rest of the code for the project while the tests run automatically

    Tip

    press ctrl + c on the keyboard in the terminal to stop the tests at anytime


how to deactivate a virtual environment

type this in a terminal with an active virtual environment

deactivate

how to activate a virtual environment

Make sure you are in the folder/directory that has the virtual environment for example magic, and type this in the terminal

source .venv/bin/activate

on Windows without Windows Subsystem Linux

.venv/scripts/activate

or

.venv/scripts/activate.ps1

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

(.venv) .../magic $

how to automatically make a python test driven development environment

You made it this far and have become the greatest programmer in the world. To follow The Do Not Repeat Yourself (DRY) Principle, I would write a program that has all the commands it took to get here, then I can use it to make a Test Driven Development Environment anytime I want and not have to remember each step of the process

  • I exit the tests in the terminal by pressing ctrl + c on the keyboard

  • and leave the virtual environment

    deactivate
    
  • then change directory to the parent of magic

    cd ..
    
  • and make an empty file with a name that describes what the program does so it is easy to remember later, for example makePythonTdd.sh

    touch makePythonTdd.sh
    
  • I use the history program to list the commands I typed and use them as a reference for the program

    history
    
  • then open the file in the Integrated Development Environment (IDE), and copy the commands I need to make a Test Driven Development Environment

    #!/bin/bash
    mkdir magic
    cd magic
    mkdir src
    touch src/magic.py
    mkdir tests
    touch tests/__init__.py
    touch tests/test_magic.py
    python3 -m venv .venv
    source .venv/bin/activate
    python3 -m pip install --upgrade pip
    echo pytest-watch > requirements.txt
    python3 -m pip install --requirement requirements.txt
    pytest-watch
    

    #!/bin/bash is a shebang line that tells the computer to use bash to run the program. You can change it to #!/bin/zsh if you have zsh installed

  • This program will always make a project called magic. I add a variable to make it possible to make a project for any name I give when the program is called and use it to replace magic in the program

    #!/bin/bash
    PROJECT_NAME=$1
    mkdir $PROJECT_NAME
    cd $PROJECT_NAME
    mkdir src
    touch src/$PROJECT_NAME.py
    mkdir tests
    touch tests/__init__.py
    touch tests/test_$PROJECT_NAME.py
    python3 -m venv .venv
    source .venv/bin/activate
    python3 -m pip install --upgrade pip
    echo pytest-watch > requirements.txt
    python3 -m pip install --requirement requirements.txt
    pytest-watch
    

    $1 is for the first argument given when the program is called, you can use it in place of $PROJECT_NAME

  • I use the echo program to add text for the first failing test to test_$PROJECT_NAME.py

    the line numbers below are a guide, you do not need to copy them

     1#!/bin/bash
     2PROJECT_NAME=$1
     3mkdir $PROJECT_NAME
     4cd $PROJECT_NAME
     5mkdir src
     6touch src/$PROJECT_NAME.py
     7mkdir tests
     8touch tests/__init__.py
     9
    10echo "import unittest
    11
    12
    13class Test$PROJECT_NAME(unittest.TestCase):
    14
    15    def test_failure(self):
    16        self.assertFalse(True)
    17
    18
    19# Exceptions Encountered
    20# AssertionError
    21" > tests/test_$PROJECT_NAME.py
    22
    23python3 -m venv .venv
    24source .venv/bin/activate
    25python3 -m pip install --upgrade pip
    26echo pytest-watch > requirements.txt
    27python3 -m pip install --requirement requirements.txt
    28pytest-watch
    
  • then make the program executable

    chmod +x makePythonTdd.sh
    

    chmod is a program that changes the mode of the given file

  • I can make a Test Driven Development environment when I call the program with a name for the PROJECT_NAME variable. For example, when I type

    ./makePythonTdd.sh calculator
    

    in the terminal in the folder where makePythonTdd.sh is saved, the computer will make a Test Driven Development environment for a project called calculator, you can continue this in how to make a calculator


how to automatically make a python test driven development environment on Windows without WSL

Warning

This is for Windows without Windows Subsystem Linux

  • I make a file called makePythonTdd.ps1 by using the New-Item command in PowerShell

    New-Item makePythonTdd.ps1
    
  • and open the file in the Integrated Development Environment’s Editor then add the following

    the line numbers below are a guide, you do not need to copy them

     1$PROJECT_NAME=$args[0]
     2mkdir $PROJECT_NAME
     3cd $PROJECT_NAME
     4mkdir src
     5New-Item "src/$PROJECT_NAME.py"
     6mkdir tests
     7New-Item tests/__init__.py
     8
     9"import unittest
    10
    11
    12class Test$($PROJECT_NAME)(unittest.TestCase):
    13
    14    def test_failure(self):
    15        self.assertFalse(True)
    16
    17
    18# Exceptions Encountered
    19# AssertionError
    20" | Out-File "tests/test_$PROJECT_NAME.py" -Encoding UTF8
    21
    22python -m venv .venv
    23.venv/scripts/activate.ps1
    24python -m pip install --upgrade pip
    25"pytest-watch" | Out-File requirements.txt -Encoding UTF8
    26python -m pip install --requirement requirements.txt
    27pytest-watch
    
    • $args[0] is the first argument given when the program is called. You can use it in place of $PROJECT_NAME

    • Out-File writes input text to a given file

  • I can make a Test Driven Development environment when I call the program with a name for the $PROJECT_NAME variable. For example, when I type

    ./makePythonTdd.ps1 calculator
    

    in the terminal in the directory where makePythonTdd.ps1 is saved, the computer will make a Test Driven Development environment for a project called calculator, you can continue this in how to make a calculator


review

One of the advantages of programming is that I can take some steps and make them a one line command for the computer to do for me. You have seen a way to make a Python Test Driven Development Environment, and have a program to do it for you on any Linux, Windows or MacOS computers.

Would you like to test making a calculator?