三件事:
- 始终从项目的根目录运行测试脚本。这个简单的规则不会造成任何损害,并且会简化您的场景
- 更喜欢绝对进口
-
-m
选项python
需要点形式的模块
将其应用到您的代码中
Modify 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
- use
nose
测试框架
处于项目的根目录
Install 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
正如你所看到的,nose 正在自己发现测试用例(搜索以test
)
让它更详细一点:
$ nosetests -v
test_animals.testpad ... ok
----------------------------------------------------------------------
Ran 1 test in 0.003s
OK
现在您知道进行了哪些测试。
要查看捕获的输出,请使用-s
switch:
$ 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()
Test it:
$ 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)
Add --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)
Use 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
方法不打印但返回声音)。
事实上,您可能会开始从测试用例编写代码,然后添加经过测试的模块,当您从一开始就开始考虑实际使用时,这通常会带来更好的设计。
选择性调用测试用例
鼻子非常适合搜索测试用例(通常以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