how to make a Python Test Driven Development environment automatically


preview

Here is the program I have by the end of the chapter to automatically make a python test driven development environment.

It is only 25 lines of code (with spaces)

 1#!/bin/bash
 2uv init more_magic
 3cd more_magic
 4mkdir src
 5mv main.py src/more_magic.py
 6mkdir tests
 7touch tests/__init__.py
 8
 9echo "import unittest
10
11
12class TestMoreMagic(unittest.TestCase):
13
14    def test_failure(self):
15        self.assertFalse(True)
16
17
18# Exceptions seen
19# AssertionError
20" > tests/test_more_magic.py
21
22echo "pytest" > requirements.txt
23echo "pytest-watcher" >> requirements.txt
24uv add --requirement requirements.txt
25uv run pytest-watcher . --now

It is only 24 lines of code (with spaces)

 1uv init more_magic
 2cd more_magic
 3mkdir src
 4Move-Item "main.py" "src/more_magic.py"
 5mkdir tests
 6New-Item tests/__init__.py
 7
 8"import unittest
 9
10
11class TestMoreMagic(unittest.TestCase):
12
13    def test_failure(self):
14        self.assertFalse(True)
15
16
17# Exceptions seen
18# AssertionError
19" | Out-File "tests/test_more_magic.py" -Encoding UTF8
20
21"pytest" | Out-File requirements.txt -Encoding UTF8
22"pytest-watcher" >> requirements.txt
23uv add --requirement requirements.txt
24uv run pytest-watcher . --now

questions about making a Python Test Driven Development Environment automatically

Questions to think about as I go through the chapter


how to make a shell script

  • I go to the terminal and use touch to make an empty file with a name that is easy to remember later. I want the name to also describe the program that will automatically make a Test Driven Development environment for me

    touch makePythonTdd.sh
    
    New-Item makePythonTdd.ps1
    

    the terminal goes back to the command line

  • I name this project magic_again

  • I open the file I just made in the editor of the Integrated Development Environment (IDE)

    Tip

    I can open a file from the terminal in the Integrated Development Environment (IDE) with the name of the program and the name of the file. That means if I type this in the terminal

    code makePythonTdd.sh
    

    Visual Studio Code opens makePythonTdd.sh in the editor

    code makePythonTdd.ps1
    

    Visual Studio Code opens makePythonTdd.ps1 in the editor

  • I add the commands I use to make a Python Test Driven Development environment for a project to the file in the editor

     1#!/bin/bash
     2uv init magic_again
     3cd magic_again
     4mkdir src
     5mv main.py src/magic_again.py
     6mkdir tests
     7touch tests/__init__.py
     8touch tests/test_magic_again.py
     9echo "pytest" > requirements.txt
    10echo "pytest-watcher" >> requirements.txt
    11uv add --requirement requirements.txt
    12uv run pytest-watcher . --now
    

    #!/bin/bash is called a shebang line, it tells the computer to use bash to run this program

     1uv init magic_again
     2cd magic_again
     3mkdir src
     4mv main.py src/magic_again.py
     5mkdir tests
     6New-Item tests/__init__.py
     7New-Item tests/test_magic_again.py
     8"pytest" | requirements.txt -Encoding UTF8
     9"pytest-watcher" >> requirements.txt
    10uv add --requirement requirements.txt
    11uv run pytest-watcher . --now
    
  • test_magic_again.py will be empty if I make it this way. I want the file to have the text for the first failing test so I do not have to open the editor to add the text for it in each project.

    I use echo in place of touch to make the makePythonTdd.sh program add text to test_magic_again.py when it makes the file in the tests folder, the same way I use echo to add text to the requirements.txt file

     1#!/bin/bash
     2uv init magic_again
     3cd magic_again
     4mkdir src
     5mv main.py src/magic_again.py
     6mkdir tests
     7touch tests/__init__.py
     8echo "" > tests/test_magic_again.py
     9echo "pytest" > requirements.txt
    10echo "pytest-watcher" >> requirements.txt
    11uv add --requirement requirements.txt
    12uv run pytest-watcher . --now
    

    I use Out-File in place of New-Item to make the makePythonTdd.ps1 program add text to test_magic_again.py when it makes the file in the tests folder, the same way I use Out-File to add text to the requirements.txt file

     1uv init magic_again
     2cd magic_again
     3mkdir src
     4Move-Item main.py src/magic_again.py
     5mkdir tests
     6New-Item tests/__init__.py
     7"" | Out-File tests/test_magic_again.py -Encoding UTF8
     8"pytest" | Out-File requirements.txt -Encoding UTF8
     9"pytest-watcher" >> Out-File requirements.txt
    10uv add --requirement requirements.txt
    11uv run pytest-watcher . --now
    
  • I add the text of the first failing test inside the quotes (“”) I just added to the files, the way I do when I add "pytest" as text to requirements.txt

    Attention

    Indentation is important in Python, I use 4 spaces as convention in this book, see the Python Style Guide for more

     1#!/bin/bash
     2uv init magic_again
     3cd magic_again
     4mkdir src
     5mv main.py src/magic_again.py
     6mkdir tests
     7touch tests/__init__.py
     8
     9echo "import unittest
    10
    11
    12class TestMagicAgain(unittest.TestCase):
    13
    14    def test_failure(self):
    15        self.assertFalse(True)
    16
    17
    18# Exceptions seen
    19# AssertionError
    20" > tests/test_magic_again.py
    21
    22echo "pytest" > requirements.txt
    23echo "pytest-watcher" >> requirements.txt
    24uv add --requirement requirements.txt
    25uv run pytest-watcher . --now
    
     1uv init magic_again
     2cd magic_again
     3mkdir src
     4Move-Item main.py src/magic_again.py
     5mkdir tests
     6New-Item tests/__init__.py
     7
     8"import unittest
     9
    10
    11class TestMagicAgain(unittest.TestCase):
    12
    13    def test_failure(self):
    14        self.assertFalse(True)
    15
    16
    17# Exceptions seen
    18# AssertionError
    19" | Out-File "tests/test_magic_again.py" - Encoding UTF8
    20
    21"pytest" | Out-File requirements.txt -Encoding UTF8
    22"pytest-watcher" | Out-File requirements.txt -Encoding UTF8
    23uv add --requirement requirements.txt
    24uv run pytest-watcher . --now
    

how to run a shell script

I go back to the terminal to run the program

makePythonTdd.sh

the terminal is my friend, and shows

command not found: makePythonTdd.sh

I have to tell the computer where the file is

./makePythonTdd.sh

./ is shorthand for this directory which in this case is pumping_python where makePythonTdd.sh is saved. The computer checks a few directories when a command is given. Those directories are where commands like mkdir, cd, tree and echo are saved. the terminal is my friend, and shows

permission denied: ./makePythonTdd.sh

I have to make the file executable for the computer to be be able to run the program.

makePythonTdd.ps1

the terminal is my friend, and shows

command not found: makePythonTdd.ps1

I have to tell the computer where the file is

.\makePythonTdd.ps1

.\ is shorthand for this directory which in this case is pumping_python where makePythonTdd.ps1 is saved. the terminal is my friend, and shows

============================= FAILURES =============================
___________________ TestMagicAgain.test_failure ____________________

self = <tests.test_magic_again.TestMagicAgain testMethod=test_failure>

    def test_failure(self):
>       self.assertFalse(True)
E       AssertionError: True is not false

tests/test_magic_again.py:7: AssertionError
==================== short test summary info =======================
FAILED tests/test_magic_again.py::TestMagicAgain::test_failure - AssertionError: True is not false
======================== 1 failed in X.YZs =========================

Success! I just made a program that can make the magic_again project anytime I want and it automatically does the steps I did manually.

Click Here to skip to How to use makePythonTdd.ps1 to make a different project


how to view the permissions of a file

I use ls to check the permissions of the file

ls -l makePythonTdd.sh

-l is the option to show the long listing format which includes permissions for the file

the terminal is my friend, and shows

-rw-r--r-- 1 abcdef ghijk XX Month  Y ZA:BC makePythonTdd.sh

Note

the first 10 characters above (-rw-r--r--) are grouped

-    rw-    r--    r--

the groups that have 3 characters show read, write and execute permissions with

  • r for can read

  • w for can write to, and

  • x for can execute

  • - for CANNOT

here is what it means for makePythonTdd.sh

  • the first group with just 1 character tells if this is a file or directory : - means this is a file, it is NOT a directory

  • the second group has 3 characters, and is for the owner of the file: rw- means the owner of the file can read (r), write to (w), and CANNOT (-) execute the file

  • the next group also has 3 characters, and is for the group of the owner of the file: r-- means the group can read (r), CANNOT (-) write to, and CANNOT (-) execute the file

  • the last group has 3 characters and is for other users: r-- means other users can read (r), CANNOT (-) write to, and CANNOT (-) execute the file

I want to add execute permissions so I can run (execute) the file


how to make a shell script run as a command

  • I change the mode of the file to add executable permissions

    chmod +x makePythonTdd.sh
    

    chmod is a program that changes the mode (permissions) of the given file, the terminal goes back to the command line

  • I list the permissions again with ls

    ls -l makePythonTdd.sh
    

    the terminal is my friend, and shows

    -rwxr-xr-x 1 abcdef ghijk XX Month  Y ZA:BC makePythonTdd.sh
    

    Note

    • - means this is a file, it is NOT a directory

    • rwx means the owner of the file can read (r), write to (w) and execute (x) the file

    • r-x means the group of the owner of the file can read (r), CANNOT (-) write to, and can execute (x) the file

    • and the second r-x means other users can read (r), CANNOT (-) write to, and can execute (x) the file

  • I try the command again

    ./makePythonTdd.sh
    

    the terminal is my friend, and shows

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

    Success! I just made a program that can make the magic_again project anytime I want and it automatically does the steps I used to do.


how to use makePythonTdd to make a different project

  • I hold ctrl on the keyboard, and click on tests/test_magic_again.py to open it in the editor then make the test pass

  • I close test_magic_again.py in the editor

  • I click in the terminal, and use q on the keyboard to leave the tests, the terminal shows

    .../pumping_python
    

    I am back in the pumping_python directory

  • I want to use makePythonTdd to make another project with a different name. I change magic_again to the name of the new project in the editor

    Note

    The lines that are changing in the code are highlighted

     1#!/bin/bash
     2uv init more_magic
     3cd more_magic
     4mkdir src
     5mv main.py src/more_magic.py
     6mkdir tests
     7touch tests/__init__.py
     8
     9echo "import unittest
    10
    11
    12class TestMoreMagic(unittest.TestCase):
    13
    14    def test_failure(self):
    15        self.assertFalse(True)
    16
    17
    18# Exceptions seen
    19# AssertionError
    20" > tests/test_more_magic.py
    21
    22echo "pytest" > requirements.txt
    23echo "pytest-watcher" >> requirements.txt
    24uv add --requirement requirements.txt
    25uv run pytest-watcher . --now
    
    • I run makePythonTdd.sh in the terminal to make a project named more_magic

      ./makePythonTdd.sh
      
     1uv init more_magic
     2cd more_magic
     3mkdir src
     4Move-Item "main.py" "src/more_magic.py"
     5mkdir tests
     6New-Item tests/__init__.py
     7
     8"import unittest
     9
    10
    11class TestMoreMagic(unittest.TestCase):
    12
    13    def test_failure(self):
    14        self.assertFalse(True)
    15
    16
    17# Exceptions seen
    18# AssertionError
    19" | Out-File "tests/test_more_magic.py" -Encoding UTF8
    20
    21"pytest" | Out-File requirements.txt -Encoding UTF8
    22"pytest-watcher" >> requirements.txt
    23uv add --requirement requirements.txt
    24uv run pytest-watcher . --now
    
    • I run makePythonTdd.ps1 in the terminal to make a project named more_magic

      ./makePythonTdd.ps1
      

    the terminal is my friend, and shows AssertionError

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

    I make the test pass

  • I click in the terminal, then use q on the keyboard to leave the tests, the terminal is my friend, and shows

    .../pumping_python
    

    I am back in the pumping_python directory

  • I close test_more_magic.py in the editor

The program works and can automatically make a Python Test Driven Development environment the way I want every time. What a beautiful life.


review

Computer Programming allows me to take some steps and make them a one line command for the computer to do for me. You have seen one way I can make a Python Test Driven Development environment, with a program to do it on any Linux, Windows or MacOS computers.

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


code from the chapter

Do you want to see all the CODE I typed in this chapter?


what is next?

you have gone through a few things

Would you like to use makePythonTdd.sh to make a Python Test Driven Development environment to test that an Exception is raised?


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