Edamame
Edamame

Reputation: 25366

python unit tests structure - how to better structure project with multiple packages and many tests files?

I did some studies and it seems that many python projects with tests would have the structure like following:

my_project:
    - package_1
       - my_package_1_class_1.py
       - my_package_1_class_2.py
       - my_package_1_class_3.py

    - package_2
       - my_package_2_class_1.py
       - my_package_2_class_2.py
       - my_package_2_class_3.py
       - my_package_2_class_4.py

    - package_3
       - my_package_3_class_1.py
       - my_package_3_class_2.py

    - test
       - test_my_package_1_class_1.py
       - test_my_package_1_class_2.py
       - test_my_package_1_class_3.py
       - test_my_package_2_class_1.py
       - test_my_package_2_class_2.py
       - test_my_package_2_class_3.py
       - test_my_package_2_class_4.py
       - test_my_package_3_class_1.py
       - test_my_package_3_class_2.py

The testing files from all packages are in the same test folder. This is a bit different from the normal Java structure, which each package has a corresponding folder for its own tests.

I feel this python structure is getting messy when we try to put a lot of testing files from different packages into the same test folder ...

How would an experienced python architecture/programmer structure their projects with many packages and testing files? Thanks!

Upvotes: 4

Views: 2610

Answers (1)

Dirk Herrmann
Dirk Herrmann

Reputation: 5939

From a general (language independent) perspective I see two main criteria when it comes to the question where in the package structure to put the test files:

  1. Maintaining a clear barrier between production code and test code: Production code should be separated from test code. For some kinds of software this is not just a recommendation, but a strict requirement (for example in safety critical software) - even if the test code within the production code would be dead code or unreachable. But, a clear barrier can also be advantageous when designing tests: separation helps to first focus on tests on the public API. And, sometimes you want to deliver production code to the customer but not the unit-test code or vice-versa (depending on the contract). This is, obviously, the simpler to achieve the more production code and test code are separated.

  2. Mutual traceability between production code and related test code: Traceability is easy to achieve when production code and test code are versioned together. Typical commits to the repository could then contain production code changes and related changes to the tests. Putting production code and tests into different projects would be a disadvantage here - unless you can somehow ensure that both related projects are consistently versioned, such that it is always clear which versions belong together. If you would have to ensure this manually, it is likely to fail.

The solution you have shown clearly supports criterion #1, but the separation of the tests from their respective packages makes it more difficut to fulfill criterion #2. For Python, I find the option to put the tests into a subpackage more appealing. See for example https://python-packaging.readthedocs.io/en/latest/testing.html:

project/
    package_1/
        __init__.py
        package_1_class_1.py
        package_1_class_2.py
        package_1_class_3.py
        tests/
            __init__.py
            test_package_1_class_1.py
            test_package_1_class_2.py
            test_package_1_class_3.py
    package_2/
        package_2_class_1.py
        package_2_class_2.py
        package_2_class_3.py
        package_2_class_4.py
        tests/
            __init__.py
            test_package_2_class_1.py
            test_package_2_class_2.py
            test_package_2_class_3.py
            test_package_2_class_4.py
    package_3/
        __init__.py
        package_3_class_1.py
        package_3_class_2.py
        tests/
            __init__.py
            test_package_3_class_1.py
            test_package_3_class_2.py
    setup.py
    ...

For example, this allows you to easily later re-use the individual packages including their tests in different projects: Everything belonging to a package is in the same directory structure.

Upvotes: 3

Related Questions