测试

时间:2017-03-25 02:33:42

标签: python-3.x unit-testing pycharm anaconda pytest

像许多其他人一样,我在测试时遇到问题,返回错误“ImportError:No module named {module name}”。这通常是因为测试与正在测试的代码位于不同的目录中。修复包括确保文件夹中存在__init__语句,将测试与测试模块放在同一文件夹中,或者修改python路径的技巧。许多此类问题之一的一个例子是:PATH issue with pytest 'ImportError: No module named YadaYadaYada'

我得出的结论是,我的系统中的PYTHONPATH非常混乱,因为:

  • 即使与他们测试的模块放在一起,测试也无法正常工作

  • 与被测模块位于同一文件夹中的测试脚本实际上可以导入和使用模块,只要它们作为python可执行文件运行而不是由测试运行(例如pytest)! / p>

  • Kenneth Reitz的Hitchhiker's Python指南演示的操作系统路径修复,并使用从GitHub克隆的samplemod包,也不能在我的系统上运行!

演示前两个要点:这是我项目的目录:

pydnmr
├── CHANGELOG.txt
├── LICENSE.txt
├── README.rst
├── docs
│   └── placeholder.txt
├── pydnmr
│   ├── __init__.py
│   ├── dnmrmath.py
│   ├── dnmrplot.py
│   ├── main.py
│   ├── plottools.py
│   ├── test_dnmrmath.py
│   └── test_plot.py
├── requirements.txt
├── setup.py
└── tests  # unused
    ├── __init__.py
    ├── context.py
    └── test_plot.py

我最初尝试在tests文件夹中使用Reitz的方法,但没有用,所以我放弃了测试并将测试移动到与要测试的代码相同的目录(dnmrplot.py等)。测试文件,如果从命令行作为python脚本(python test_plot.py)运行,则导入模块并运行正常,但如果作为测试运行(pytest test_plot.py),则会出现导入错误。

以下是test_plot.py的代码:

import pytest
# noinspection PyUnresolvedReferences
import dnmrplot


def test_dnmrplot_2spin_type():

    WINDNMR_DEFAULT = (165.00, 135.00, 1.50, 0.50, 0.50, 0.5000)
    x, y = dnmrplot.dnmrplot_2spin(*WINDNMR_DEFAULT)
    print('x ', type(x), "y", type(y))
    assert type(x) == "<class 'numpy.ndarray'>"
    assert type(y) == "<class 'numpy.ndarray'>"


if __name__ == "__main__":
    import plottools as pt

    WINDNMR_DEFAULTS = (165.00, 135.00, 1.50, 0.50, 0.50, 50.00)
    spectrum = dnmrplot.dnmrplot_2spin(*WINDNMR_DEFAULTS)
    pt.popplot(*spectrum)

测试和作为__main__运行时执行的代码都需要相同的dnmrplot模块导入。将代码作为python可执行文件运行,但pytest会导致导入错误。

至于Reitz的解决方法:他在tests目录中添加了一个context.py文件(我在上面显示的test目录中也采用了它):

import sys
import os
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

import sample

但是,他的测试test_basic.py实际上并没有测试导入。我对其进行了修改,以便:

from .context import sample

import unittest


class BasicTestSuite(unittest.TestCase):
    """Basic test cases."""

    def test_absolute_truth_and_meaning(self):
        assert True

    # I Added the following to actually require accessing 'sample':

    def test_sample_hmm(self):
        response = sample.hmm()
        assert response == 'hmmm...'

if __name__ == '__main__':
    # unittest.main()  #Reitz' code
    print(sample.hmm())  # my code

当作为python脚本运行或作为测试运行时,它无法导入样本:

    def test_sample_hmm(self):
        response = sample.hmm()
>       assert response == 'hmmm...'
E       AssertionError: assert None == 'hmmm...'

test_basic.py:18: AssertionError
----------------------------- Captured stdout call -----------------------------
hmmm...
====================== 1 failed, 1 passed in 0.06 seconds ======================
$ python test_basic.py
Traceback (most recent call last):
  File "test_basic.py", line 3, in <module>
    from .context import sample
SystemError: Parent module '' not loaded, cannot perform relative import
$ cd ..
$ python tests/test_basic.py
Traceback (most recent call last):
  File "tests/test_basic.py", line 3, in <module>
    from .context import sample
SystemError: Parent module '' not loaded, cannot perform relative import

我已尝试通过命令行运行测试,包括测试文件内部和上部。我也试过在我的IDE PyCharm中运行测试。我已经尝试使用PyCharm将上层pydnmr文件夹设置为源根目录。我已经摆弄了Reitz的解决方法。我已经尝试将我的项目克隆到硬盘上完全不同的位置。在这一点上,我的假设是,在我的Mac上使用Anaconda安装和使用PyCharm之间,我的机器上有一些与PYTHONPATH混淆的东西,我需要一个驱魔人。

在OS X上使用Python 3.4,使用Anaconda安装和PyCharm。

任何帮助我找出导入问题的根源都将不胜感激。

1 个答案:

答案 0 :(得分:0)

问题的根源似乎是模块是用作导入还是用作脚本。这似乎解决了这种行为:

Relative imports in Python 3