how to make a Python Test Driven Development environment automatically with variables

Since I am the greatest programmer in the world, I should not be doing as much repetition as I have done so far. I have to make it better.

Here are steps I take with makePythonTdd to make the environment for every project on a computer with MacOS, Linux or Windows with Windows Subsystem for Linux

  1. I give the project a name

  2. I open makePythonTdd

  3. I change the name of the project to the new project name

  4. I run makePythonTdd

  5. I open the test file in the editor from the terminal

  6. I make the test pass

  7. I start working on the project


preview

makePythonTdd.sh
 1#!/bin/bash
 2PROJECT_NAME=$1
 3uv init $PROJECT_NAME
 4cd $PROJECT_NAME
 5mkdir tests
 6touch tests/__init__.py
 7
 8echo "import unittest
 9
10
11class Test$PROJECT_NAME(unittest.TestCase):
12
13    def test_failure(self):
14        self.assertFalse(True)
15
16
17# Exceptions seen
18# AssertionError
19" > tests/test_$PROJECT_NAME.py
20
21echo "pytest" > requirements.txt
22echo "pytest-watcher" >> requirements.txt
23uv add --requirement requirements.txt
24uv run pytest-watcher . --now
makePythonTdd.ps1
 1$PROJECT_NAME=$args[0]
 2uv init $PROJECT_NAME
 3cd $PROJECT_NAME
 4mkdir tests
 5New-Item tests/__init__.py
 6
 7"import unittest
 8
 9
10class Test$($PROJECT_NAME)(unittest.TestCase):
11
12    def test_failure(self):
13        self.assertFalse(True)
14
15
16# Exceptions seen
17# AssertionError
18" | Out-File "tests/test_$PROJECT_NAME.py" -Encoding UTF8
19
20"pytest" | Out-File requirements.txt -Encoding UTF8
21"pytest-watcher" >> requirements.txt
22uv add --requirement requirements.txt
23uv run pytest-watcher . --now

how to use a variable in a shell script

The makePythonTdd works and always makes a Python Test Driven Development environment the way I want it. The problem is I have to change the name of the project in a few places every time I use the program to make a project.

I want the program to take the name of the project once and use the name to make the

This way I give one command for the program with the name of the project and have it do all the steps for me except

  • give the project a name

  • make the test pass and

  • work on the project

As a reminder, it will always make this structure

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

I can use a variable for the name of the project

  • I open makePythonTdd.sh

  • I add PROJECT_NAME to represent any project name I use to make a project

    1#!/bin/bash
    2PROJECT_NAME="pro_magic"
    
  • I open makePythonTdd.ps1

  • I add $PROJECT_NAME to represent any project name I use to make a project

    1$PROJECT_NAME="pro_magic"
    
  • A variable is a name used for a value that can change. For example, we use the word

    • woman to represent any woman

    • man to represent any man

    • child to represent any child

    • parent to represent anyone with a child.

  • I use PROJECT_NAME to represent any project name

  • I name this project pro_magic because I am a professional

  • I change the name of the project to the variable (PROJECT_NAME) I just added so that I only have to make a change in one place

  • I run makePythonTdd.sh in the terminal to make the pro_magic project

    ./makePythonTdd.sh
    
  • I run makePythonTdd.ps1 in the terminal to make the pro_magic project

    .\makePythonTdd.ps1
    
  • the terminal is my friend, and shows AssertionError

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

    this program does not make the class name in the CapWords format (TestProMagic) so it is in snake_case (Testpro_magic), there has to be a better way.

  • I hold ctrl on the keyboard, then click on tests/test_pro_magic.py in the terminal to open it

  • I change True to False in the assertion

    7        self.assertFalse(False)
    

    the test passes.

  • I click in the terminal where the tests are running

  • I use q on the keyboard to leave the tests. The terminal goes back to the command line.

  • I run tree to see what I have in the pro_magic folder

tree -a -L 1 pro_magic
tree pro_magic
  • the terminal shows

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

The program does what I want, and I only need to give the project name in one place. It would be nice if I do not have to go into the file to give it the project name.


how to call a shell script with arguments

I want to be able to call the program and give it a name for the project from the command line.

I can do this with $1 in bash. $1 is for the first argument given after the name of a program when it is called. For example

I can do this with $args[0] in PowerShell. $args[0] is for the first argument given after the name of a program when it is called. For example

command argument

in the code above, command is the name of the program and $1 is argument

in the code above, command is the name of the program $args[0] is argument

Here are a few other examples

mkdir folder_name
touch file_name
echo "echo"
  • mkdir is the command, and $1 is folder_name

  • touch is the command, and $1 is file_name

  • echo is the command, and $1 is "echo"

  • mkdir is the command, and $args[0] is folder_name

  • touch is the command, and $args[0] is file_name

  • echo is the command, and $args[0] is "echo"


  • I change pro_magic to $1 in makePythonTdd.sh

    1#!/bin/bash
    2PROJECT_NAME=$1
    3uv init $PROJECT_NAME
    
  • I try the program again, this time with a name for the project in the terminal

    ./makePythonTdd.sh pro_magic_plus
    
  • I change pro_magic to $args[0] in makePythonTdd.ps1

    1$PROJECT_NAME=$args[0]
    2uv init $PROJECT_NAME
    
  • I try the program again, this time with a name for the project in the terminal

    .\makePythonTdd.ps1 pro_magic_plus
    
  • the terminal is my friend, and shows

    ========================= FAILURES =========================
    ____________ Testpro_magic_plus.test_failure _______________
    
    self = <tests.test_pro_magic_plus.Testpro_magic_plus testMethod=test_failure>
    
        def test_failure(self):
    >       self.assertFalse(True)
    E       AssertionError: True is not false
    
    tests/test_pro_magic_plus.py:7: AssertionError
    ================= short test summary info ==================
    FAILED tests/test_pro_magic_plus.py::Testpro_magic_plus::test_failure - AssertionError: True is not false
    ==================== 1 failed in X.YZs =====================
    
  • I hold ctrl on the keyboard in the terminal and click on tests/test_pro_magic_plus.py to open it, then make the test pass

  • I use q on the keyboard to leave the tests. The terminal goes back to the command line.

  • I run tree to see what I have in the pro_magic_plus folder

    tree -aL 1 pro_magic_plus
    
    tree pro_magic_plus
    

    the terminal is my friend, and shows

    pro_magic_plus
    ├── .git
    ├── .gitignore
    ├── pyproject.toml
    ├── .pytest_cache
    ├── .python-version
    ├── README.md
    ├── requirements.txt
    ├── src
    ├── tests
    ├── uv.lock
    └── .venv
    
  • I can now make a Test Driven Development environment with makePythonTdd when I give it a name for the PROJECT_NAME variable. For example, when I type this in the terminal

    ./makePythonTdd.sh exceptions
    
    .\makePythonTdd.ps1 exceptions
    

    it does all the steps then shows AssertionError

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

the computer makes a Python Test Driven Development environment for a project called exceptions and runs the first failing test. I continue this in how to test that an Exception is raised


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 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.


code from the chapter

Do you want to see the CODE for makePythonTdd.sh?


what is next?

Would you like to test handling Exceptions?


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.