如何在不安装包的情况下运行测试?

42 投票
4 回答
14717 浏览
提问于 2025-04-18 08:13

我有一个Python包和一些测试文件。这些文件的结构是按照这个链接的建议来安排的。

把测试放在一个单独的目录里,和实际的应用代码分开,这样做很有用,特别是当你有很多功能测试,或者出于其他原因想要把测试和应用代码分开的情况下(通常这是个好主意):

setup.py   # your distutils/setuptools Python package metadata
mypkg/
    __init__.py
    appmodule.py
tests/
        test_app.py

我遇到的问题是,当我运行测试命令py.test时,出现了一个错误。

ImportError: No module named 'mypkg'

我可以通过运行python setup.py install来解决这个问题,但这样做的结果是测试是针对已安装的包来运行的,而不是本地的包,这让开发变得非常麻烦。每次我做了修改想要运行测试时,都需要重新安装,否则我测试的就是旧代码。

我该怎么办呢?

4 个回答

-1

使用 from .. import mypkg 来导入这个包。为了让这个方法有效,你需要在测试目录和包含这个目录的地方添加(空的) __init__.py 文件。之后, py.test 会处理剩下的事情。

2

在我这边,开发的时候我更喜欢从IDE(集成开发环境)里运行测试(使用一个测试运行器扩展),而不是通过命令行。不过,在我推送代码或者发布之前,我会选择使用命令行来运行测试。

这里有一个方法可以解决这个问题,让你可以同时从IDE的测试运行器和命令行来运行测试。

我的设置如下:

  • IDE: Visual Studio Code

  • 测试工具: pytest

  • 扩展(测试运行器): https://marketplace.visualstudio.com/items?itemName=LittleFoxTeam.vscode-python-test-adapter

  • 工作目录结构(我的解决方案应该很容易适应你的情况):

    project_folder/
    
        src/
            mypkg/
                __init__.py
                appmodule.py
        tests/
             mypkg/
                appmodule_test.py
        pytest.ini           <- Use so pytest can locate pkgs from ./src 
        .env                 <- Use so VsCode and its extention can locate pkgs from ./src
    
  • .env:

     PYTHONPATH="${PYTHONPATH};./src;"
    
  • pytest.ini(使用pytest 7.1.2测试过):

     [pytest]
     pythonpath = . src
    
  • ./src/mypkg/appmodule.py:

     def i_hate_configuring_python():
         return "Finally..."
    
  • ./tests/mypkg/appmodule_test.py:

    from mypkg import app_module
    
    
    def test_demo(): 
        print(app_module.i_hate_configuring_python())
    

这样做应该就可以了。

18

开发时通常的做法是使用一个虚拟环境(virtualenv),然后在这个虚拟环境里运行 pip install -e . 命令(这和 python setup.py develop 基本上是一样的)。这样一来,你的源代码目录就会被当作一个已安装的包,放到系统路径(sys.path)里。

当然,还有很多其他方法可以把你的包放到系统路径里以便测试。如果你想了解更多,可以查看这个链接:确保 py.test 包含应用程序目录在 sys.path 中,里面有对这个问题更完整的解答。

31

我知道这个问题已经被关闭了,但我常用的一种简单方法是通过 python -m 来调用 pytest,从项目的根目录(也就是包的父目录)开始。

$ python -m pytest tests

这样做的原因是 -m 选项会把当前目录添加到 Python 的搜索路径中,因此 mypkg 会被识别为一个本地包(而不是已经安装的包)。

可以参考这个链接: https://docs.pytest.org/en/latest/usage.html#calling-pytest-through-python-m-pytest

撰写回答