how to make a python test driven development environment¶
This is one way to make a Python Test Driven Development environment
requirements¶
download and install Python
get an Integrated Development Environment (IDE). Here are a few options
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 projectmkdir 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
I make a child directory for the tests
mkdir tests
then an empty file called
__init__.py
in thetests
folder to tell Python that it is a python package, this will help it find the tests latertouch 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 testtouch 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 followingthe 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
import unittest
imports the unittest module from the python standard library, it is used for testingclass TestMagic
class
is the Python keyword for making classes, which are a collection of attributes and methods for a purposeTestMagic
is the name of this class and will hold the test. You can use any name as long as it starts withTest
unittest.TestCase is a class defined in the unittest module which has methods for testing
class TestMagic(unittest.TestCase)
defines thatTestMagic
inherits from unittest.TestCase which allows me use its methods
def test_failure
def is the Python keyword for making methods (functions)
test_failure
is the name of this method, you can use any name as long as it starts withtest_
self
is used to access attributes and methods of theTestMagic
class and by extension the unittest.TestCase class instead of usingTestMagic().
orunittest.TestCase().
self.assertFalse(True)
is an assertionassertFalse is a method in the unittest.TestCase class that checks if its input is False
True is given as the input
I expect this line to fail because True is not False, there is a problem if it does not fail
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 changethen type this in the terminal to run the test
python3 -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 failuresRan 1 test in A.XYZs
the number of tests run and how long it tookAssertionError: True is not false
the Exception raised and its message, in this case AssertionError is raised because True is not Falseself.assertFalse(True)
the line of code that caused the failureFile ".../magic/tests/test_magic.py", line 7, in test_failure
the line number and location of the file where the failure happenedTip
Hold
ctrl
(windows/linux) oroption
(mac) on the keyboard and use the mouse to click onFile ".../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 happenedTraceback (most recent call last):
all the information shown after this line that is indented to the right shows the calls that led to the failureFAIL: test_failure (tests.test_magic.TestMagic.test_failure)
is a header with information in dot notation about the failing test methodF
indicates a failurepython3 -m unittest
is the command to run tests with theunittest
modulepython3
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 ofpython3
python -m venv .venv
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 scriptvenv is a module from the python standard library, it is used to make a virtual environment with a given name. A virtual environment is a separate folder where python packages needed by the project will be installed
.venv
is the name given, you can use any name
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-ExecutionPolicyTo 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 ofpython3
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 theinstall
argument for pip to upgrade the version of the python package givenpip
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 textecho 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 rightOut-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 theinstall
argument for python packages in a given filerequirements.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
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 keyboardand 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 installedThis 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 replacemagic
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 calledcalculator
, 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 PowerShellNew-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 calledcalculator
, 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?