python单元测试结构-如何使用多个包和多个测试文件更好地构造项目?

python单元测试结构-如何使用多个包和多个测试文件更好地构造项目?,python,unit-testing,Python,Unit Testing,我做了一些研究,似乎许多带有测试的python项目的结构如下所示: 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

我做了一些研究,似乎许多带有测试的python项目的结构如下所示:

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
所有包中的测试文件都位于同一测试文件夹中。这有点不同于普通的Java结构,每个包都有一个对应的文件夹用于自己的测试

当我们试图将来自不同包的大量测试文件放入同一个测试文件夹中时,我觉得这个python结构变得很混乱

一个有经验的python架构/程序员如何用许多包和测试文件来构建他们的项目?谢谢

从一般(独立于语言)的角度来看,当涉及到在包结构中放置测试文件的位置时,我看到两个主要标准:

  • 在生产代码和测试代码之间保持清晰的界限:生产代码应与测试代码分开。对于某些类型的软件,这不仅仅是一个建议,而是一个严格的要求(例如在安全关键软件中)——即使生产代码中的测试代码是死代码或无法访问。但是,在设计测试时,一个清晰的屏障也是有利的:分离有助于首先关注公共API上的测试。而且,有时您希望向客户交付生产代码,而不是单元测试代码,反之亦然(取决于合同)。显然,这是实现越简单,分离的生产代码和测试代码就越多

  • 生产代码和相关测试代码之间的相互可追溯性:当生产代码和测试代码一起版本化时,可追溯性很容易实现。然后,对存储库的典型提交可能包含生产代码更改和对测试的相关更改。在这里,将生产代码和测试放在不同的项目中是一个缺点——除非您能够以某种方式确保两个相关项目的版本是一致的,这样就可以始终清楚哪些版本属于同一个项目。如果您必须手动确保这一点,它很可能会失败

  • 您所展示的解决方案清楚地支持标准#1,但将测试从各自的包中分离出来会使实现标准#2更加困难。对于Python,我发现将测试放入子包的选项更具吸引力。例如,见:

    例如,这允许您以后轻松地重用各个包,包括它们在不同项目中的测试:属于包的所有内容都在相同的目录结构中

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