最近终于把手头的项目搞完了,完了QA要求写单元测试。这个差不多是我第2个python项目,各种不熟啊,花了2周多写完代码,花了1周多写测试,额,准确的说是学写测试。基本上用的就是nose+mock,真是个好用的东西,现小结一下吧。
nose
nose是开源的测试库,比unittest更为强大,其运行顺序按setUp->test_func_1->test_func_2->...->tearDown
顺序执行。其中setUp是初始化定义各个参数的,tearDown是执行完各个测试函数再执行的,中间的test_func_*
就是自己要测试的函数。比如我们写了一个add()函数,那么如果对其进行测试就需要定义一个test_add()
函数。举个例子:
def setUp():
"""
@brief setUp - init
@return
"""
app = anyclass.create_app()
def tearDown():
"""
@brief tearDown - tear down
@return
"""
pass
def test_add():
"""
@brief test_add - test func
@return
"""
ret = anyclass._add(1, 2)
print ret
assert ret == 3
以上是一个最简单的例子,我们在test_add
中调用实际的类,传入参数,然后对输出进行判断,若等于3该测试用例通过,反之未通过。就是这么简单。
另外一个问题就是如何执行单元测试,只要在当前测试函数所在的目录下执行nosetests
就可以自动运行了,每个函数成功返回一个.
,失败返回F
。
mock
那mock是啥子东西,mock可以用来模拟不同的资源,比如我们要调用数据库进行增删改查,而创建一个数据库,写入真实数据进行操作未免代价太大,这时候mock就起作用了。广泛的说,mock可以代替那些不易操作的资源。来吧,上个例子。
def setUp():
"""
@brief setUp - init
@return
"""
app = anyclass.create_app()
def tearDown():
"""
@brief tearDown - tear down
@return
"""
pass
@mock.patch('A.put')
def test_func_B(mock_commands):
"""
@brief test_func_B - test func, this will call A.put
@return
"""
mock_commands.side_effect = [
(True, 'success'),
(False, 'not allowed')
]
ret = any_class.func_B
print ret
assert ret == 1
ret = any_class.func_B
print ret
assert ret == 2
上面这个例子中,setUp
和tearDown
不变,我们在test_dunc_B
中用了包裹函数@mock.patch('A.put')
。因为我们的func_B
里面会调用到A.put
这个函数,然后这个函数很难模拟(比如异步操作),所以我们直接用mock
进行模拟。mock_commands.side_effect
有两个元素,其中第一个元素表示第一次调用的返回结果,第二个元素表示第二次调用的返回结果,这些结果将返回给func_B
去使用,我们的ret
代表func_B
的返回结果,此处假设为1和2。这样,我们就可以进行一次完整的单元测试了。
Done!
参考
http://blog.chinaunix.net/uid-26722078-id-3758545.html
http://www.oschina.net/translate/unit-testing-with-the-python-mock-class
https://docs.python.org/3/library/unittest.mock.html
说明
转载请注明出处:http://vinllen.com/python-dan-yuan-ce-shi-nose-mockshi-yong-xiao-jie/