what is a module?


A Python module is any file that ends in .py. Any folder that contains an __init__.py is also a Python module.


preview

I have these tests by the end of the chapter

 1import src.module_00
 2import src.module_01
 3import src.module_02
 4import src.module_03
 5import src.module_04
 6import src.module_05
 7import src.doe
 8import src.doe.john
 9import src.doe.jane
10import magic
11
12
13# Exceptions seen
14# AssertionError
15# ModuleNotFoundError

start the project

  • I name this project module_not_found_error

  • I open a terminal

  • I change directory to the module_not_found_error project in the pumping_python folder

    cd module_not_found_error
    

    the terminal shows

    cd: no such file or directory: module_not_found_error
    

    there is no folder with the name module_not_found_error in this folder.

  • I use the uv Python Package Manager to setup the project

    uv init module_not_found_error
    

    the terminal shows

    Initialized project `module-not-found-error`
    at `.../pumping_python/module_not_found_error`
    
  • I change directory to the module_not_found_error folder

    cd module_not_found_error
    

    the terminal shows

    .../pumping_python/module_not_found_error
    
  • I make a child folder in the module_not_found_error folder where I will keep the main Python modules separate from the other files

    mkdir src
    

    the terminal goes back to the command line.

  • I use the mv program to move main.py to the src folder

    mv main.py src/main.py
    

    the terminal goes back to the command line.

  • I make a child folder to keep the tests separate from the other files

    mkdir tests
    

    the terminal goes back to the command line.

  • I use touch to add an empty file to the tests folder

    touch tests/module_not_found_error.py
    

    the terminal goes back to the command line.

  • I open module_not_found_error.py from the tests folder

    Tip

    I can open a file from the terminal with ctrl (Windows/Linux) or command (MacOS) on the keyboard and a click with the mouse on the name of the file

  • I add the first failing test to module_not_found_error.py in the tests folder

    1assert False is True
    
  • I use the `unittest module`_ to run tests

    python3 -m unittest
    

    the terminal shows

    ------------------------------------------------------
    Ran 0 tests in 0.000s
    
    NO TESTS RAN
    
  • I close module_not_found_error.py

    Danger

    if you do not close module_not_found_error.py, there will be 3 files in the tests folder after the next step (instead of 2), because the Auto Save feature (enabled earlier) will save the original file if it is still open after you change its name.

  • I use the mv program to change the name of module_not_found_error.py in the tests folder to test_module_not_found_error.py

    mv tests/module_not_found_error.py \
    tests/test_module_not_found_error.py
    

    the terminal goes back to the command line.

    Tip

    The \ + enter/return allows me to write one long line on multiple lines in the terminal. Without it I have to write everything as one line because the terminal runs whatever line I have written when I hit enter/return on the keyboard.

  • I try to run the test again

    python3 -m unittest
    

    the terminal still shows NO TESTS RAN.

  • I make the tests directory a Python package

    Danger

    use 2 underscores (__) before and after init for __init__.py not _init_.py

    touch tests/__init__.py
    
    New-Item tests/__init__.py
    

    the terminal goes back to the command line.

  • I try to run the test again

    python3 -m unittest
    

    the terminal is my friend, and shows AssertionError

      File ".../pumping_python/module_not_found_error/tests/test_module_not_found_error.py",
        line 1, in <module>
        assert False is True
               ^^^^^^^^^^^^^
    AssertionError
    
    
    ------------------------------------------------------
    Ran 1 test in X.YZs
    
    FAILED (errors=1)
    
  • I hold ctrl (Windows/Linux) or option/command (MacOS) on the keyboard and use the mouse to click on File ".../pumping_python/module_not_found_error/tests/test_module_not_found_error.py", line 1 in the terminal, and the Integrated Development Environment (IDE) opens the file with the cursor at the line where the failure happened.

  • I add AssertionError to the list of Exceptions seen, in test_module_not_found_error.py

    1assert False is True
    2
    3
    4# Exceptions seen
    5# AssertionError
    
  • I change True to False

    1# assert False is True
    2assert False is False
    3
    4
    5# Exceptions seen
    6# AssertionError
    
  • I run the test again

    python3 -m unittest
    

    the test passes. Time to test modules

  • I add the new files and folders to git for tracking

    git add .
    

    the terminal goes back to the command line.

  • I add a git commit message

    git commit --all --message \
    'setup project'
    

    the terminal shows a summary of the changes then goes back to the command line.


test_module_not_found_error

RED: make it fail


  • I remove the assert statements then add an import statement for a module at the top of the file

    1import src.module_00
    2
    3
    4# Exceptions seen
    5# AssertionError
    
  • I run the test again

    python3 -m unittest
    

    the terminal is my friend, and shows ModuleNotFoundError

      File ".../pumping_python/module_not_found_error/
                tests/test_module_not_found_error.py",
        line 1, in <module>
        import src.module_00
    ModuleNotFoundError: No module named 'src.module_00'
    
    
    ----------------------------------------------------------------------
    Ran 1 test in 0.000s
    
    FAILED (errors=1)
    

    because when import src.module_00 runs, Python tries to bring in an object (everything in Python is an object) for the module_00.py file from the src folder.

  • I add ModuleNotFoundError to the list of Exceptions seen in test_module_not_found_error.py

    4# Exceptions seen
    5# AssertionError
    6# ModuleNotFoundError
    

what causes ModuleNotFoundError?

ModuleNotFoundError is raised when Python cannot find a module (a file that ends in .py) with the name given in an import statement


GREEN: make it pass


  • I go back to the terminal

  • I use the mv program to change the name of main.py in the src folder to module_00.py

    mv src/main.py src/module_00.py
    

    the terminal goes back to the command line

  • I run the test again

    python3 -m unittest
    
    • the test passes because when import src.module_00 runs, Python brings in an object for the module_00.py file from the src folder so I can use it in test_module_not_found_error.py

    • the terminal shows NO TESTS RAN which is confusing since the only way I know the test passed, is because I saw it fail


REFACTOR: make it better


  • I add an import statement for src.module_01 to test_module_not_found_error.py

    1import src.module_00
    2import src.module_01
    3
    4
    5# Exceptions seen
    6# AssertionError
    7# ModuleNotFoundError
    
  • I run the test again

    python3 -m unittest
    

    the terminal is my friend, and shows ModuleNotFoundError

    ModuleNotFoundError: No module named 'src.module_01'
    
  • I make a new file named module_01.py in the src folder

    touch src/module_01.py
    

    the terminal goes back to the command line.

  • I run the test

    python3 -m unittest
    

    the test passes because import src.module_01 brings in an object for the module_01.py file from the src folder so I can use it in test_module_not_found_error.py.

  • I add an import statement for src.module_02 to test_module_not_found_error.py

    1import src.module_00
    2import src.module_01
    3import src.module_02
    4
    5
    6# Exceptions seen
    7# AssertionError
    8# ModuleNotFoundError
    
  • I go to the terminal to run the test

    python3 -m unittest
    

    the terminal is my friend, and shows ModuleNotFoundError

    ModuleNotFoundError: No module named 'src.module_02'
    
  • I make a new file named module_02.py in the src folder

    touch src/module_02.py
    

    the terminal goes back to the command line.

  • I run the test again

    python3 -m unittest
    

    the test passes because import src.module_02 brings in an object (everything in Python is an object) for the module_02.py file from the src folder so I can use it in test_module_not_found_error.py.

  • I add an import statement for src.module_03 to test_module_not_found_error.py

    1import src.module_00
    2import src.module_01
    3import src.module_02
    4import src.module_03
    5
    6
    7# Exceptions seen
    
  • I go to the terminal to run the test

    python3 -m unittest
    

    the terminal is my friend, and shows ModuleNotFoundError

    ModuleNotFoundError: No module named 'src.module_03'
    
  • I make a new file named module_03.py in the src folder

    touch src/module_03.py
    

    the terminal goes back to the command line.

  • I run the test again

    python3 -m unittest
    

    the test passes because import src.module_03 brings in an object for the module_03.py file from the src folder so I can use it in test_module_not_found_error.py.

  • I add an import statement for src.module_04 to test_module_not_found_error.py

    1import src.module_00
    2import src.module_01
    3import src.module_02
    4import src.module_03
    5import src.module_04
    6
    7
    8# Exceptions seen
    
  • I go to the terminal to run the test

    python3 -m unittest
    

    the terminal is my friend, and shows ModuleNotFoundError

    ModuleNotFoundError: No module named 'src.module_04'
    
  • I make a new file named module_04.py in the src folder

    touch src/module_04.py
    

    the terminal goes back to the command line.

  • I run the test again

    python3 -m unittest
    

    the test passes because import src.module_04 brings in an object (everything in Python is an object) for the module_04.py file from the src folder so I can use it in test_module_not_found_error.py.

  • I add an import statement for src.module_05 to test_module_not_found_error.py

    1import src.module_00
    2import src.module_01
    3import src.module_02
    4import src.module_03
    5import src.module_04
    6import src.module_05
    7
    8
    9# Exceptions seen
    
  • I go to the terminal to run the test

    python3 -m unittest
    

    the terminal is my friend, and shows ModuleNotFoundError

    ModuleNotFoundError: No module named 'src.module_05'
    
  • I make a new file named module_05.py in the src folder

    touch src/module_05.py
    

    the terminal goes back to the command line.

  • I run the test again

    python3 -m unittest
    

    the test passes because import src.module_05 brings in an object for the module_05.py file from the src folder so I can use it in test_module_not_found_error.py.

  • I add an import statement for src.doe to test_module_not_found_error.py

     1import src.module_00
     2import src.module_01
     3import src.module_02
     4import src.module_03
     5import src.module_04
     6import src.module_05
     7import src.doe
     8
     9
    10# Exceptions seen
    
  • I go to the terminal to run the test

    python3 -m unittest
    

    the terminal is my friend, and shows ModuleNotFoundError

    ModuleNotFoundError: No module named 'src.doe'
    
  • I make a new folder named doe in the src folder

    mkdir src/doe
    

    the terminal goes back to the command line.

  • I run the test again

    python3 -m unittest
    
    • the test passes because import src.doe brings in an object for the doe folder that is in the src folder so I can use it in test_module_not_found_error.py

    • this worked even though I did not add an __init__.py file to the folder

  • I add an import statement for src.doe.john to test_module_not_found_error.py

     1import src.module_00
     2import src.module_01
     3import src.module_02
     4import src.module_03
     5import src.module_04
     6import src.module_05
     7import src.doe
     8import src.doe.john
     9
    10
    11# Exceptions seen
    
  • I go to the terminal to run the test

    python3 -m unittest
    

    the terminal is my friend, and shows ModuleNotFoundError

    ModuleNotFoundError: No module named 'src.doe.john'
    
  • I make a new file named john.py in the doe folder in the src folder

    touch src/doe/john.py
    

    the terminal goes back to the command line.

  • I run the test again

    python3 -m unittest
    

    the test passes because import src.doe.john brings in an object for the john.py file from the doe folder that is in the src folder so I can use it in test_module_not_found_error.py.

  • I add an import statement for src.doe.jane to test_module_not_found_error.py

     1import src.module_00
     2import src.module_01
     3import src.module_02
     4import src.module_03
     5import src.module_04
     6import src.module_05
     7import src.doe
     8import src.doe.john
     9import src.doe.jane
    10
    11
    12# Exceptions seen
    
  • I go to the terminal to run the test

    python3 -m unittest
    

    the terminal is my friend, and shows ModuleNotFoundError

    ModuleNotFoundError: No module named 'src.doe.jane'
    
  • I make a new file named jane.py in the doe folder in the src folder

    touch src/doe/jane.py
    

    the terminal goes back to the command line.

  • I run the test again

    python3 -m unittest
    

    the test passes because import src.doe.jane brings in an object for the jane.py file from the doe folder that is in the src folder so I can use it in test_module_not_found_error.py.

  • I add an import statement for magic to test_module_not_found_error.py

     1import src.module_00
     2import src.module_01
     3import src.module_02
     4import src.module_03
     5import src.module_04
     6import src.module_05
     7import src.doe
     8import src.doe.john
     9import src.doe.jane
    10import magic
    11
    12
    13# Exceptions seen
    14# AssertionError
    15# ModuleNotFoundError
    
  • I go to the terminal to run the test

    python3 -m unittest
    

    the terminal is my friend, and shows ModuleNotFoundError

    ModuleNotFoundError: No module named 'magic'
    
  • I make a new file named magic.py in the main folder of the project (module_not_found_error)

    touch magic.py
    

    the terminal goes back to the command line.

  • I run the test again

    python3 -m unittest
    

    the test passes because import magic brings in an object for the magic.py that is in the module_not_found_error folder so I can use it in test_module_not_found_error.py.

  • I add the new files and folder to git for tracking

    git add .
    
  • I add a git commit message in the terminal

    git commit --all --message \
    'test ModuleNotFoundError'
    

    the terminal shows a summary of the changes then goes back to the command line.


close the project

  • I close test_module_not_found_error.py

  • I go back to the terminal

  • I change directory to the parent of module_not_found_error

    cd ..
    

    the terminal is my friend, and shows

    .../pumping_python
    

    I am back in the pumping_python directory.


review


how to view all the commands I typed to test ModuleNotFoundError


  • I type history in the terminal to see all the commands I typed for this project

    history
    

    the terminal shows

    the history program shows all the commands I typed in the terminal

    • I ran python3 -m unittest to see the test fail

    • I ran python3 -m unittest every time I made a change until the test passed

    • I will run python3 -m unittest again when I add any code, to make sure tests that passed before do not fail and that the new code I add does what I want

    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 ever again, I want the computer to do it for me.


code from the chapter

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


what is next?

You know

Would you like to see how to run tests automatically?


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.