在找出正确的,python 2.x首选方式进行相对导入时遇到一些麻烦,这样我就可以将测试脚本保存在一个子包中,让这些测试脚本能够测试我的库。
$ farm\testpad\testpad.py
Traceback (most recent call last):
File "C:\farm\testpad\testpad.py", line 4, in <module>
from ..animals.dog import dog
ValueError: Attempted relative import in non-package
$ python -m farm\testpad\testpad
C:\Python27\python.exe: No module named farm\testpad\testpad
在以下示例中,我需要修改哪些内容才能执行我想要的操作?拜托,感谢您给予的任何帮助。
e.g。
包结构:
farm/
__init__.py # empty
animals/
__init__.py # empty
dog.py
testpad/
__init__.py # empty
testpad.py
dog.py
import sys
import os
class dog():
def __init__(self, name):
self.name = name
def speak(self):
print "woof"
testpad.py
import os
import sys
from ..animals.dog import dog
# create a dog and test its speak action
def testpad():
d = dog("Allen")
d.speak()
if __name__ == "__main__":
testpad()
答案 0 :(得分:17)
三件事:
-m
python
选项需要虚线形式的模块将此应用于您的代码
testpad.py
import os
import sys
from farm.animals.dog import dog
# Create a dog and test its speak action
def testpad():
d = dog("Allen")
d.speak()
if __name__ == "__main__":
testpad()
python -m <module>
$ python -m farm.testpad.testpad
woof
nose
对于我的测试,我使用以下模式
test
或更好tests
nose
测试框架在项目的根目录
安装nose
:
$ pip install nose
创建命令的内容nosetests
重新组织您的代码
$ mkdir tests
$ mv farm/testpad/testpad.py tests/test_animals.py
$ rm -rf farm/testpad/
运行测试(目前只有一个)
简单的方法,这项工作,但试图保持输出最小:
$ nosetests
.
----------------------------------------------------------------------
Ran 1 test in 0.003s
OK
如您所见,鼻子正在自己发现测试用例(搜索以test
开头的任何内容)
让它更冗长:
$ nosetests -v
test_animals.testpad ... ok
----------------------------------------------------------------------
Ran 1 test in 0.003s
OK
现在你知道了,运行了什么测试。
要查看捕获的输出,请使用-s
开关:
$ nosetests -vs
test_animals.testpad ... woof
ok
----------------------------------------------------------------------
Ran 1 test in 0.003s
OK
向test_animals.py
import os
import sys
# create a dog and test its speak action
def test_dog():
from farm.animals.dog import dog
d = dog("Allen")
d.speak()
def test_cat():
from farm.animals.dog import cat
c = cat("Micy")
d.speak()
def test_rabbit():
from farm.animals.dog import rabbit
r = rabbit()
r.speak()
测试它:
$ nosetests -vs
test_animals.test_dog ... woof
ok
test_animals.test_cat ... ERROR
test_animals.test_rabbit ... ERROR
======================================================================
ERROR: test_animals.test_cat
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/javl/Envs/so/local/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(*self.arg)
File "/home/javl/sandbox/so/testpad/tests/test_animals.py", line 12, in test_cat
from farm.animals.dog import cat
ImportError: cannot import name cat
======================================================================
ERROR: test_animals.test_rabbit
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/javl/Envs/so/local/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(*self.arg)
File "/home/javl/sandbox/so/testpad/tests/test_animals.py", line 17, in test_rabbit
from farm.animals.dog import rabbit
ImportError: cannot import name rabbit
----------------------------------------------------------------------
Ran 3 tests in 0.004s
FAILED (errors=2)
添加--pdb
开关以跳转到调试器(如果您安装ipdbplugin
,则可以使用--ipdb
):
$ nosetests -vs --pdb
test_animals.test_dog ... woof
ok
test_animals.test_cat ... > /home/javl/sandbox/so/testpad/tests/test_animals.py(12)test_cat()
-> from farm.animals.dog import cat
(Pdb) l
7 from farm.animals.dog import dog
8 d = dog("Allen")
9 d.speak()
10
11 def test_cat():
12 -> from farm.animals.dog import cat
13 c = cat("Micy")
14 d.speak()
15
16 def test_rabbit():
17 from farm.animals.dog import rabbit
(Pdb)
使用h
或者找一些调试器教程,这是一个很棒的工具
真实的测试用例应断言行为符合预期。
当您打印到stdout时,我们可以使用模拟捕获输出(在Python 2.x中您必须安装它,在Python 3.x中from unittest import mock
):
$ pip install mock
并修改您的test_animals.py
:
from mock import patch
from StringIO import StringIO
# create a dog and test its speak action
@patch("sys.stdout", new_callable=StringIO)
def test_dog(mock_stdout):
from farm.animals.dog import Dog
d = Dog("Allen")
d.speak()
assert mock_stdout.getvalue() == "woof\n"
@patch("sys.stdout", new_callable=StringIO)
def test_cat(mock_stdout):
from farm.animals.cat import Cat
c = Cat("Micy")
c.speak()
assert mock_stdout.getvalue() == "mnau\n"
@patch("sys.stdout", new_callable=StringIO)
def test_rabbit(mock_stdout):
from farm.animals.rabbit import Rabbit
r = Rabbit("BB")
r.speak()
assert mock_stdout.getvalue() == "Playboy, Playboy\n"
test_mytaste.py
def test_dog():
from farm.animals.dog import Dog
d = Dog("Allen")
sound = d.speak()
assert sound == "woof", "A dog shall say `woof`"
def test_cat():
from farm.animals.cat import Cat
c = Cat("Micy")
sound = c.speak()
assert sound == "mnau", "A cat shall say `mnau`"
def test_rabbit():
from farm.animals.rabbit import Rabbit
r = Rabbit("BB")
sound = r.speak()
assert sound == "Playboy, Playboy", "A Rabbit shall say ..."
这需要你重构你的代码(类名从大写开始,speak
方法不打印但返回声音。)
事实上,您可能会从测试用例开始编写代码并稍后添加经过测试的模块,这通常会导致更好的设计,因为您从一开始就考虑实际使用。
nose非常适合搜索测试用例(通常以test
开头),但有时您可能会专注于特定测试或使用不同名称的python文件。您可以告诉nose
只使用一个测试文件:
$ nosetests -vs tests/test_mytaste.py
test_mytaste.test_dog ... ok
test_mytaste.test_cat ... ok
test_mytaste.test_rabbit ... ok
----------------------------------------------------------------------
Ran 3 tests in 0.002s
OK
或甚至定位nose
从中运行特定测试:
$ nosetests -vs tests/test_mytaste.py:test_dog
test_mytaste.test_dog ... ok
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK