unittest扩展库

infi.unittest的Python项目详细描述


简介

infi.unittest是python标准库提供的标准unittest模块的一组扩展。它比原来的实现提供了一些改进,如下所述。

注意

infi.unittest不支持Python2.6及更低版本,因为在2.7中对unittest模块进行了重大的修改。对不起的。

安装

安装以普通方式进行:

python setup.py install

功能

试验参数

关于unittest最烦人的事情之一是您不能轻松地指定测试参数。如果您有一个测试来测试一个带有参数的api,并且您需要几个案例,每个案例都测试一个特定的值,该值应该有效并且有意义,那么这可能会很烦人,并且会打破干巴巴的原则:

>>> import unittest
>>> class MyTest(unittest.TestCase):
...     def test__api_call_with_yellow(self):
...         self._test_api_call('yellow')
...     def test__api_call_with_orange(self):
...         self._test_api_call('orange')
...     def _test_api_call(self, color):
...         some_api(color) # test here... yuck!

使用infi.unittest时,您会得到一种更好的方法:

>>> from infi.unittest import TestCase
>>> from infi.unittest import parameters
>>> class MyTest(TestCase):
...     @parameters.iterate('color', ['orange', 'yellow'])
...     def test__api_call(self, color):
...         some_api(color) # yay!

上面将为每个可能的值构造一个测试用例,从而为每个值分离用例。也可以使用多个值,将可能性相乘:

>>> class MyTest(TestCase):
...     @parameters.iterate('a', [1, 2, 3])
...     @parameters.iterate('b', [4, 5, 6])
...     def test__some_api(self, a, b):
...         pass

迭代可以在返回要迭代的序列的函数(或任何可调用对象)上完成:

>>> def get_options():
...     return [1, 2, 3]
>>> class MyTest(TestCase):
...     @parameters.iterate('a', get_options)
...     def test__something(self, a):
...         pass
对于布尔标志,存在一种在选项之间迭代的更简单的方法:

>>> class MyTest(TestCase):
...     @parameters.toggle('a', 'b', 'c')
...     def test__something(self, a, b, c):
...         pass # will be called with all combinations of True/False for a, b, c

夹具参数

有时您想要编写一组测试,其中用于运行它们的fixture需要在选项上迭代。例如,如果我们想在旧样式类和新样式类上测试实用程序方法:

>>> class OldStyle:
...     pass
>>> class NewStyle(object):
...     pass
>>> class TestOldStyle(TestCase):
...     def setUp(self):
...         super(TestOldStyle, self).setUp()
...         self.tested_obj = OldStyle()
...     def test__1(self):
...         # do something with self.tested_obj
...         pass
...     def test__2(self):
...         # do something with self.tested_obj
...         pass
>>> class TestNewStyle(TestCase):
...     def setUp(self):
...         super(TestNewStyle, self).setUp()
...         self.tested_obj = NewStyle()
...     def test__1(self):
...         # do something with self.tested_obj
...         pass
...     def test__2(self):
...         # do something with self.tested_obj
...         pass

一个聪明的人,虽然不是很漂亮,但这样做的方式是继承:

>>> class _BaseTest(TestCase):
...     def test__1(self):
...         # do something with self.tested_obj
...         pass
...     def test__2(self):
...         # do something with self.tested_obj
...         pass
>>> class OldStyleTest(_BaseTest):
...     def setUp(self):
...         super(OldStyleTest, self).setUp()
...         self.tested_obj = OldStyle()
>>> class NewStyleTest(_BaseTest):
...     def setUp(self):
...         super(NewStyleTest, self).setUp()
...         self.tested_obj = NewStyle()

这很糟糕,有些发现方法也会尝试运行basetest(尽管前缀是下划线)。infi.unittest巧妙地解决了这个问题:

>>> class Test(TestCase):
...     @parameters.iterate('obj', [NewStyle(), OldStyle()])
...     def setUp(self, obj):
...         super(Test, self).setUp()
...         self.tested_obj = obj
...     def test__1(self):
...         # do something with self.tested_obj
...         pass
...     def test__2(self):
...         # do something with self.tested_obj
...         pass

unittest甚至可以跨继承进行乘法运算。这意味着下面的代码将最终测试[1,2,3]和[4,5,6]之间的笛卡尔积

>>> class BaseTest(TestCase):
...     @parameters.iterate('param', [1, 2, 3])
...     def setUp(self, param):
...         super(BaseTest, self).setUp()
...         self.base_param = param
>>> class DerivedTest(BaseTest):
...     @parameters.iterate('param', [4, 5, 6])
...     def setUp(self, param):
...         super(DerivedTest, self).param()
...         self.derived_param = param
...     def test(self):
...         self.do_something_with(self.base_param, self.derived_param)

请注意,即使对setup的super()调用也不需要对参数进行处理,它会自动绑定。

抽象基础测试

有时您希望包含一个“基本测试”来促进代码重用。例如在以下情况下:

>>> class FileTestBase(TestCase):
...     def test__has_write_method(self):
...         self.assertTrue(hasattr(self.file, "write"))
...     def test__has_read_method(self):
...         self.assertTrue(hasattr(self.file, "read"))
>>> class RegularFileTest(FileTestBase):
...     def setUp(self):
...         super(RegularFileTest, self).setUp()
...         self.file = open("somefile", "wb")
>>> class SocketFileTest(FileTestBase):
...     def setUp(self):
...         super(SocketFileTest, self).setUp()
...         self.file = connect_to_some_server().makefile()

在这种情况下,一个常规的测试发现机制会着火,因为它会试图运行filetestbase本身,它有一个不完整的设置方案。

infi.unittest为此提供了一个简单的快捷方式。只需标记基类如下:

>>> from infi.unittest import abstract_base_test
>>> @abstract_base_test
... class FileTestBase(TestCase):
...     pass

基本测试本身也不会直接运行。

注意

nose作为此技术的问题。有一个解决办法,但它涉及到一个鼻子实用功能的实时补丁,所以有可能会打破更新,或根本不工作在某些情况下。在这个问题解决之前(https://github.com/nose-devs/nose/issues/502),鼻梁支撑应该被认为是实验性的。

鼻积分

infi.unittest打破了与优秀的nose:http://code.google.com/p/python nose/>;工具的兼容性,因此它提供了一个nose插件来处理其测试。插件会自动为您启用,因此您不必将–with infi标志传递给nosetests。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
在IE10中重新加载另一个帧时,internet explorer Java小程序失败/消失   ThreadLocal变量的java性能   java系统。出来println不是打印输出   java从JAXB类获取元素属性   java组织。天啊。科尔巴。包裹。InvalidName:IDL:omg。org/CORBA/ORB/InvalidName:1.0   java有没有办法让非事务连接抛出异常?   java是否有任何方法可以使用JdbcTemplate和查询/条件Fluent API   javajpa级联类型。刷新不工作?   未考虑java Maven依赖关系管理   java MySQL MBR包含抛出MySQLExceptionError的语句   java验证整数并将其设为5位数   java发现了循环依赖的问题   java Hibernate left join fetch到使用@ManyToMany关联映射的softdeleted实体生成无效查询?   JavaH:commandButton多个操作:下载文件并呈现ajax表   Google Contacts API在Java、C#、Python或Ruby中是否有一个Hello World示例?