跳转到主要内容

Unittest扩展库

项目描述

简介

infi.unittest 是Python标准库中提供的标准 unittest 模块的一组扩展。它对原始实现进行了多项改进,如下所述。

安装

安装按照常规方式进行

python setup.py install

特性

测试参数

关于 unittest 最令人烦恼的事情之一是您无法轻松指定测试参数。如果您有一个要测试具有参数的API的测试,并且您想有多个情况,每个情况测试特定的值,这些值应该工作并且有含义,这可能会很烦人,并破坏DRY原则

>>> 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

infi.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)

请注意,即使是 super() 调用 setUp 也不需要担心参数 - 它会自动绑定。

抽象基类测试

有时,您可能希望包含一个“基测试”以方便代码重用。例如在以下情况下

>>> 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 本身,该基类具有不完整的 setUp 方案。

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

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

然后,基测试本身将不会直接运行。

Nose 集成

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

项目详细信息


下载文件

下载适用于您的平台的文件。如果您不确定选择哪个,请了解有关 安装软件包 的更多信息。

源分布

infi.unittest-1.1.0.tar.gz (8.9 kB 查看散列)

上传时间

支持者:

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面