关于单元测试:Python包?

Python Packages?

好吧,我认为无论我做错了什么,它可能都是显而易见的,但我无法弄清楚。 我已阅读并重新阅读有关软件包的教程部分,我唯一可以想到的是,这不起作用,因为我正在直接执行它。 这是目录设置:

1
2
3
4
5
6
7
8
9
eulerproject/
  __init__.py
  euler1.py
  euler2.py
  ...
  eulern.py
  tests/
    __init__.py
    testeulern.py

以下是testeuler12.py(我编写的第一个测试模块)的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import unittest
from .. import euler12

class Euler12UnitTests(unittest.TestCase):


    def testtriangle(self):
       """
        Ensure that the triangle number generator returns the first 10
        triangle numbers.

       """

        self.seq = [1,3,6,10,15,21,28,36,45,55]
        self.generator = euler12.trianglegenerator()
        self.results = []
        while len(self.results) != 10:
            self.results.append(self.generator.next())
        self.assertEqual(self.seq, self.results)

    def testdivisors(self):
       """
        Ensure that the divisors function can properly factor the number 28.

       """

        self.number = 28
        self.answer = [1,2,4,7,14,28]
        self.assertEqual(self.answer, euler12.divisors(self.number))


if __name__ == '__main__':

    unittest.main()

现在,当我从IDLE和目录中的命令行执行此操作时,我收到以下错误:

1
2
3
4
Traceback (most recent call last):
  File"C:\Documents and Settings\jbennet\My Documents\Python\eulerproject\tests\testeuler12.py", line 2, in <module>
    from .. import euler12
ValueError: Attempted relative import in non-package

我认为问题是因为我直接运行它,我不能做相对导入(因为__name__更改,我对包描述的模糊理解是__name__是它如何告诉它是什么包的一部分 in),但在那种情况下你们有什么建议如何导入从测试代码中存储1级的"生产"代码?


我有同样的问题。我现在使用nose来运行我的测试,并正确处理相对导入。

是的,这整个相对重要的东西令人困惑。


一般来说,你的PYTHONPATH上会有一个目录,其名称是你的包名。例如:

1
2
3
4
5
6
7
8
eulerproject/
    euler/
        __init__.py
        euler1.py
        ...
        tests/
            ...
    setup.py

然后,您可以在系统范围内安装,也可以确保在调用脚本时设置PYTHONPATH=/path/to/eulerproject/:$PYTHONPATH

这样的绝对导入将起作用:

1
from euler import euler1

编辑:

根据Python文档,"用作Python应用程序主模块的模块应始终使用绝对导入。" (引用)

因此,另一个答案中提到的像nose这样的测试工具可以工作,因为它导入包而不是从命令行运行它们。

如果您想手动执行操作,则可运行脚本需要位于包层次结构之外,如下所示:

1
2
3
4
5
6
7
8
9
eulerproject/
    runtests.py
    euler/
        __init__.py
        euler1.py
        ...
        tests/
            __init__.py
           testeulern.py

现在,runtests.py可以执行from euler.tests.testeulern import TestCasetesteulern.py可以执行from .. import euler1