unittest目录结构-无法导入src代码

问题描述 投票:0回答:1

我的项目中有以下文件夹结构:

my-project
   src/
       __init__.py
       script.py
   test/
       __init__.py
       test_script.py

理想情况下,我想要一个单独的文件夹来存放所有单元测试。我的

test_script.py
看起来像这样:

from src.script import my_object

class TestClass(unittest.TestCase):
    
    def test_script_object(self):
        # unit test here
        pass

if __name__ == 'main':
    unittest.main()

当我尝试运行脚本(使用

python test_script.py
)时,出现以下错误:

Traceback (most recent call last):
  File "test_script.py", line 4, in <module>
    from src.script import my_object
ModuleNotFoundError: No module named 'src'

我遵循了另一个线程的说明,我什至尝试将src

附加到系统路径(这迫使我改变在项目其余部分中导入的方式)。当我不尝试附加到 sys 路径时,我的两个 
__init__.py
 文件都是空的。

我使用的是python 3.8。

有人有什么建议吗?我是 python 单元测试的新手,所以也许有更好的结构或其他我不知道的约定。预先感谢您的帮助!

python python-3.x python-unittest
1个回答
4
投票
通常,任何要求您修改

sys.path

以运行测试的指令都会将您引向错误的方向。您的测试工具应该能够发现您的测试和应用程序代码,而无需进行此类黑客攻击。

我喜欢使用

pytest 来运行我的测试。我会这样构造你的例子:

my-project/ ├── src │   ├── conftest.py │   └── myproject │   ├── __init__.py │   └── script.py └── tests ├── __init__.py └── test_script.py
假设 

src/myproject/script.py

 看起来像这样:

def double(x: int): return x*2
并且

tests/test_script.py

看起来像这样:

import myproject.script def test_double(): res = myproject.script.double(2) assert res == 4
我可以通过简单地运行 

my-project

:
来从
pytest
目录运行测试

$ pytest ========================================== test session starts ========================================== platform linux -- Python 3.11.1, pytest-7.2.0, pluggy-1.0.0 rootdir: /home/lars/tmp/python/my-project collected 1 item tests/test_script.py . [100%] =========================================== 1 passed in 0.00s ===========================================
在此设置中,文件 

src/conftest.py

 允许 pytest 自动发现应用程序代码的位置。或者,您可以在 
pyproject.toml
 文件中指定,如下所示:

[tool.pytest.ini_options] pythonpath = [ "src" ]
如果您编写问题中所示的 
unittest

风格的测试,

pytest 也可以工作;如果 
tests/test_script.py
 看起来像这样,上面的行为将是相同的:

import unittest import myproject.script class TestScript(unittest.TestCase): def test_double(self): res = myproject.script.double(2) self.assertEqual(res, 4) if __name__ == '__main__': unittest.main()
(但我更喜欢 pytest 更简单的语法。)

可能有用的阅读:

  • 良好的集成实践

如果您确实想使用

unittest

,您
可以使用相同的目录布局,但您需要更新sys.path
才能正确运行。最简单的方法是:

PYTHONPATH=$PWD/src python -m unittest
这将自动发现您的所有测试并运行它们。您可以像这样运行单个测试:

PYTHONPATH=$PWD/src python -m tests.test_script
如果您使用更简单的目录布局,则可以避免需要修改

sys.path

my-project/ ├── myproject │   ├── __init__.py │   └── script.py └── tests ├── __init__.py └── test_script.py

pytest

 目录运行时,
python -m unittest
my-project
 都将正确发现并运行您的测试,而无需任何路径修改。

© www.soinside.com 2019 - 2024. All rights reserved.