# Modules and submodules (unittest)

Let's say we have the following directory structure:

```python
main_module/
    ├── moduleA.py
    └── submodules/
        ├── submoduleB.py
        └── submoduleC.py
```

Inside [`moduleA.py`](http://moduleA.py), we define a function called `hello()`:

```python
# moduleA.py

def hello():
    print("Hello from moduleA!")
```

Inside [`submoduleB.py`](http://submoduleB.py), we define a function called `greet()`:

```python
# submoduleB.py

def greet():
    print("Greetings from submoduleB!")
```

Now, let's use `moduleA` and `submoduleB` together in a program:

```python
# main.py

import main_module.moduleA as moduleA
import main_module.submodules.submoduleB as submoduleB

moduleA.hello()  # Output: Hello from moduleA!
submoduleB.greet()  # Output: Greetings from submoduleB!
```

In this example, [`moduleA.py`](http://moduleA.py) is a module, and [`submoduleB.py`](http://submoduleB.py) is a submodule within the `main_module` package. We can import them using dot notation to access their functions and use them in our program. The program will output the respective messages defined in each module/submodule.

This illustrates how modules and submodules can be organized and imported to reuse code in a hierarchical manner.

**Lets look at a real example:**

hierarchy for the `unittest` package and its submodules:

```python
unittest/
    ├── __init__.py
    ├── case.py
    ├── loader.py
    ├── main.py
    ├── mock.py
    ├── result.py
    ├── runner.py
    ├── signals.py
    ├── suite.py
    └── util.py
```

* `unittest` (package): The top-level package that contains all the testing-related modules and submodules.
    
* `__init__.py`: An empty file that marks the directory as a package and allows importing from it. Not necessarily empty in this case.
    
* [`case.py`](http://case.py): Module containing the `TestCase` class, which is the base class for defining individual test cases. It provides a set of assertion methods and hooks for setting up and tearing down test fixtures.
    
* [`loader.py`](http://loader.py): Module providing test case discovery and loading mechanisms.
    
* [`main.py`](http://main.py): Module providing the main entry point for running tests.
    
* [`mock.py`](http://mock.py): Module containing classes and functions for creating and working with mock objects during testing.
    
* [`result.py`](http://result.py): Module containing classes for storing and reporting test results.
    
* [`runner.py`](http://runner.py): Module containing classes for running test suites and test cases.
    
* [`signals.py`](http://signals.py): Module containing classes for managing signals during test runs.
    
* [`suite.py`](http://suite.py): Module containing classes for managing collections of test cases and test suites.
    
* [`util.py`](http://util.py): Module containing various utility functions and classes used internally by the `unittest` framework.
    

In this hierarchy, the `TestCase` class is located in the [`case.py`](http://case.py) module, and the `Mock` class is located in the [`mock.py`](http://mock.py) module.

Since **TestCase class is implemented inside the case module**, If you have written python tests before, you would probably be wondering how we have been able to do this `unittest.TestCase`

In the `unittest` package, the `TestCase` class is defined in the [`case.py`](http://case.py) module. When you import the `unittest` package, the `TestCase` class is made available as an attribute of the `unittest` module. This is due to the way the `__init__.py` file of the `unittest` package is implemented.

The `__init__.py` file of a package can define what gets imported when the package is imported. In the case of the `unittest` package, the `__init__.py` file imports the `TestCase` class from the `case` module and makes it accessible as an attribute of the `unittest` module itself.

So, when you import `unittest`, you can access the `TestCase` class using the syntax `unittest.TestCase`. This is because the `TestCase` class is imported and made available within the `unittest` package's namespace.

**This will give you an idea of what might be found in the** `unittest/__init__.py`

```python
# Importing commonly used classes and functions for convenience
from .case import TestCase
from .loader import TestLoader
from .main import main
from .mock import patch
from .result import TestResult, TextTestResult
from .runner import TextTestRunner
from .signals import installHandler
from .suite import TestSuite

# Importing subpackages and modules within the unittest package
import unittest.mock
import unittest.signals
import unittest.util

# Other initialization code or configuration

# Exporting symbols to be accessible when importing the unittest package
__all__ = [
    'TestCase',
    'TestLoader',
    'main',
    'patch',
    'TestResult',
    'TextTestResult',
    'TextTestRunner',
    'installHandler',
    'TestSuite',
    # Other symbols to export if applicable
]

# Additional code or configurations
```

If you have the `unittest` package installed on your system, you can locate and examine the actual `__init__.py` file within the package to see the precise code that is used in your specific environment.

The `__all__` variable is a list that specifies the symbols (functions, classes, variables) that should be imported or made accessible when someone imports a module or a package
