how to make a python test driven development environment¶
This is one way to make a Python Test Driven Development environment
requirements¶
get an Integrated Development Environment (IDE). Here are a few options
windows requirements¶
If you are using a Windows computer, try
If installing Windows Subsystem Linux does not work, you can use how to make a python test driven development environment on Windows without Windows Subsystem Linux instead
linux/Windows Subsystem Linux requirements¶
Open a terminal then type this to update the Linux package manager
sudo apt update
type this in the terminal to install Python
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 and it’s name is
magic. I open a terminal in the Integrated Development Environment (IDE) and use mkdirmkdir magicthis makes a folder/directory for the project where its files will stay
I use cd
cd magic
this changes directory to the
magicfolder/directory I just madeI make a child folder/directory for the source code (the actual program)
mkdir srcI use touch to make an empty file
touch src/magic.pythis adds an empty file for the source code (the actual program)
I make a child directory
mkdir teststhis is where I will add tests for the project
I use touch to add an empty file called
__init__.pyin thetestsfolderAttention
make sure to use 2 underscores (__) for
__init__.pytouch tests/__init__.pythis tells Python that
testsis a python package, it will help it find the tests I write laterI use touch to add one more empty file in the
testsdirectory for the actual testtouch tests/test_magic.pyTip
I can use any name for the file 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
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 click on
magic/tests/test_magic.pyin the Integrated Development Environment (IDE) to open it in the editor, then type the followingNote
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
import unittestimports the unittest module from the python standard library, it is used for testingclass TestMagicclassis the Python keyword for making classes, which are a group of attributes and methods that belong together, see classes for moreTestMagicis the name of this class and will hold the testTip
I can use any name as long as it starts with
Testunittest.TestCase is a class from the unittest module which has methods for testing
class TestMagic(unittest.TestCase)definesTestMagicas a “child” of unittest.TestCase which means I can use its methods and attributes
def test_failuredef is the Python keyword for making methods (functions), see functions for more
test_failureis the name of this method for my testsTip
I can use any name as long as it starts with
test_self.allows me to use attributes and methods of theTestMagicclass which is a “child” of 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. If it does not fail, then Python and I have a problem
I turn on the
Auto Savefeature in the Integrated Development Environment (IDE) to automatically save files when I make a change so I do not repeat myself by having to hit save(ctrl+s)every time I make a changeI type this in the terminal to run the test
python3 -m unittest
the terminal shows AssertionError
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, I like to read these from the bottom up, here is an explanation of each line
FAILED (failures=1)the number of failuresRan 1 test in A.XYZsthe number of tests it ran and how long they tookAssertionError: True is not falsethe Error/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_failurethe line number of the code that caused the failure and the location of the file where it isTip
Hold
ctrl(windows/linux) oroption(mac) on the keyboard and use the mouse to click onFile ".../magic/tests/test_magic.py", line 7in 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 methodFshows a failurepython3 -m unittestis the command to run tests with theunittestmoduleI recommend you keep a list of Errors/Exceptions you meet to become familiar with them, it helps when you run into failures later. I add AssertionError to the list
1import unittest 2 3 4class TestMagic(unittest.TestCase): 5 6 def test_failure(self): 7 self.assertFalse(True) 8 9 10# Exceptions Encountered 11# AssertionError
green: make it pass¶
I change the input on line 7 from True to False
self.assertFalse(False)
then I run the test again in the terminal
python3 -m unittest
and the test passes
.
------------------------------------------------------
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, I 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 that the new code I added does what I expect.
This means I have to run python3 -m unittest 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
python3is the Python program-mis 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
.venvis the name givenNote
.venvis Python convention, I can use any name I want
I activate the virtual environment to use it
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, for example(.venv) .../magic $
I upgrade pip the python package manager to the latest version
python3 -m pip install --upgrade pip
pip is a module from the python standard library, it is used to install python packages
installis an argument given to pip to install a given package name--upgradeis an option/switch given to theinstallargument for pip to upgrade the version of the python package givenpipis the package name I am giving pip to install, in this case it upgrades itself
I use pip to see what packages are installed in the virtual environment
pip list
the terminal shows
Package Version ------- ------- pip x.y
I use echo to make a file in the
magicdirectory with pytest-watch as its textecho pytest-watch > requirements.txt
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 filepytest-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.txtis the name of a file where I can list python packages for pip to installNote
requirements.txtis Python convention, I can use any name I want
I install pytest-watch and the programs it needs
pip install --requirement requirements.txt
--requirementis another option that can be passed to theinstallargument for python packages in a given filerequirements.txtis the name of the file givenNote
requirements.txtis Python convention, I can use any name I want
I use pip to see what packages are now installed in the virtual environment
pip list
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 Pygments 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.pyfrom False to True, the terminal 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 ===================================
I change True back to False in
test_magic.pyto make it pass. I can now write the rest of the code for the project while the tests run automaticallyTip
press
ctrl+con the keyboard in the terminal to stop the tests at anytime
how to deactivate a virtual environment¶
When I want to leave a virtual environment, I type this in the terminal to deactivate it
deactivate
how to activate a virtual environment¶
When I want to work in a virtual environment, I change directory to 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, for example
(.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 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 every step of the process
I exit the tests in the terminal by pressing
ctrl+con the keyboardI leave the virtual environment
deactivate
I use cd to change directory to the parent of
magiccd ..
I use touch to 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.shI use the history program
historythe terminal shows all the commands I have typed so far, and I use them to write the program
I click on
makePythonTdd.shto open it in the Integrated Development Environment (IDE), then type the commands I need to make a Test Driven Development Environment in the editorNote
the line numbers below are a guide, you do not need to copy them
1#!/bin/bash 2mkdir magic 3cd magic 4mkdir src 5touch src/magic.py 6mkdir tests 7touch tests/__init__.py 8touch tests/test_magic.py 9python3 -m venv .venv 10source .venv/bin/activate 11python3 -m pip install --upgrade pip 12echo pytest-watch > requirements.txt 13python3 -m pip install --requirement requirements.txt 14pytest-watch
#!/bin/bashis a shebang line that tells the computer to use bash to run the programThe problem with this program is it will always make a project called
magic. I need it to be able to make any project I want. I add a variable to replacemagicso I can give it any name when I want to make a projectNote
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 9touch tests/test_$PROJECT_NAME.py 10python3 -m venv .venv 11source .venv/bin/activate 12python3 -m pip install --upgrade pip 13echo pytest-watch > requirements.txt 14python3 -m pip install --requirement requirements.txt 15pytest-watch
$1is for the first argument given when the program is called, I can use it in place of$PROJECT_NAMEfor examplecommand argument
in the code above,
commandwill bemakePythonTdd.shand$1will get the value ofargumentI use the echo program to add text for the first failing test to
test_$PROJECT_NAME.py1#!/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
I type this in the terminal to make sure the program I just wrote is 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_NAMEvariable. For example, when I type this in the terminal in the folder wheremakePythonTdd.shis saved,./makePythonTdd.sh calculatorthe 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?