8

来自 python 文档(http://docs.python.org/library/unittest.html):

import unittest

class WidgetTestCase(unittest.TestCase):
    def setUp(self):
        self.widget = Widget('The widget')

    def tearDown(self):
        self.widget.dispose()
        self.widget = None

    def test_default_size(self):
        self.assertEqual(self.widget.size(), (50,50),
                         'incorrect default size')

    def test_resize(self):
        self.widget.resize(100,150)
        self.assertEqual(self.widget.size(), (100,150),
                         'wrong size after resize')

这是,如何调用这些测试用例:

def suite():
    suite = unittest.TestSuite()
    suite.addTest(WidgetTestCase('test_default_size'))
    suite.addTest(WidgetTestCase('test_resize'))
    return suite

是否可以将参数 custom_parameter 插入到 WidgetTestCase 中,例如:

class WidgetTestCase(unittest.TestCase):
    def setUp(self,custom_parameter):
        self.widget = Widget('The widget')
        self.custom_parameter=custom_parameter

?

4

5 回答 5

6

我所做的是在刚刚添加的 test_suite 模块中

WidgetTestCase.CustomParameter="some_address"

最简单的解决方案是最好的:)

于 2011-08-29T21:31:08.423 回答
3

这是我最近一直在想的事情。是的,这是很有可能做到的。我称之为场景测试,但我认为参数化可能更准确。我在这里提出了一个概念证明作为要点。简而言之,它是一个元类,允许您定义一个场景并针对它运行测试。有了它,您的示例可以是这样的:

class WidgetTestCase(unittest.TestCase):
    __metaclass__ = ScenarioMeta
    class widget_width(ScenerioTest):
        scenarios = [
            dict(widget_in=Widget("One Way"), expected_tuple=(50, 50)),
            dict(widget_in=Widget("Another Way"), expected_tuple=(100, 150))
        ]
        def __test__(self, widget_in, expected_tuple):
            self.assertEqual(widget_in.size, expected_tuple)

运行时,元类会写出 2 个单独的测试,因此输出将类似于:

$ python myscerariotest.py -v
test_widget_width_0 (__main__.widget_width) ...好的
test_widget_width_1 (__main__.widget_width) ...好的


-------------------------------------------------- --------------------
在 0.001 秒内运行 2 次测试

好的

如您所见,场景在运行时转换为测试。

现在我还不确定这是否是一个好主意。我在测试中使用它,我有很多以文本为中心的案例,这些案例在略有不同的数据上重复相同的断言,这有助于我捕捉小的边缘案例。但是那个要点中的课程确实有效,我相信它可以完成你所追求的。

请注意,通过一些技巧,可以为测试用例指定名称,甚至可以从文本文件或数据库等外部源中提取测试用例。它尚未记录在案,但是在元类中进行一些挖掘应该可以帮助您入门。我在这里的帖子中还有一些更多信息和示例。

编辑

这是一个丑陋的黑客,我不再支持。该实现应该作为 TestCase 的子类完成,而不是作为被黑客入侵的元类。活到老,学到老。一个更好的解决方案是使用鼻子生成器

于 2011-03-21T05:43:38.353 回答
3

我找到了一种方法来做到这一点,但这有点麻烦。

基本上,我所做的是在 TestCase 中添加一个__init__定义“默认”参数和 a 的方法,__str__以便我们可以区分情况:

class WidgetTestCase(unittest.TestCase):

    def __init__(self, methodName='runTest'):
        self.parameter = default_parameter
        unittest.TestCase.__init__(self, methodName)

    def __str__(self):
        ''' Override this so that we know which instance it is '''
        return "%s(%s) (%s)" % (self._testMethodName, self.currentTest, unittest._strclass(self.__class__))

然后在 suite() 中,我迭代我的测试参数,将默认参数替换为每个测试特定的参数:

def suite():
    suite = unittest.TestSuite()

    for test_parameter in test_parameters:
        loadedtests = unittest.TestLoader().loadTestsFromTestCase(WidgetTestCase)
        for t in loadedtests:
            t.parameter = test_parameter
        suite.addTests(loadedtests)

    suite.addTests(unittest.TestLoader().loadTestsFromTestCase(OtherWidgetTestCases))
    return suite

OtherWidgetTestCases不需要参数化的测试在哪里。

例如,我有一堆对真实数据的测试,需要对每个测试应用一套测试,但我也有一些合成数据集,旨在测试数据中通常不存在的某些边缘情况,我只需要对这些应用某些测试,以便他们在OtherWidgetTestCases.

于 2011-03-21T17:38:08.823 回答
0

我不这么认为,setUp 的签名需要是 unittest 所期望的,afaik,setUp 在测试用例的 run 方法中自动调用为 setUp() ...你将无法通过它,除非你覆盖 run 以传入您想要的 var。但我认为你想要的违背了单元测试的目的。不要尝试使用 DRY 哲学,您正在测试的每个单元都应该是类的一部分,甚至是函数/方法的一部分。

于 2011-03-17T09:36:27.390 回答
0

我不认为这是一个好主意。单元测试应该足够彻底,以便您测试案例中的所有功能,因此不需要传递不同的参数。

你提到你正在传递一个 www 地址 - 这几乎肯定不是一个好主意。如果您尝试在“网络连接断开”的机器上运行测试会发生什么?你的测试应该是:

  • 自动 - 它们将在支持您的应用程序的所有机器和平台上运行,无需用户干预。他们不应该依赖外部环境来通过。这意味着(除其他外)依赖正确设置的 Internet 连接是一个坏主意。您可以通过提供虚拟数据来解决此问题。与其将 URL 传递给资源,不如抽象出数据源并传入数据流或其他任何东西。这在 python 中特别容易,因为您可以利用 python 的鸭子类型来呈现类似流的对象(出于这个原因,python 经常使用“类似文件”的对象!)。

  • 彻底——你的单元测试应该有 100% 的代码覆盖率,并涵盖所有可能的情况。您想在多个站点上测试您的代码吗?相反,请使用站点可能包含的所有可能功能来测试您的代码。在不了解您的应用程序的功能的情况下,我无法在这一点上提供太多建议。

现在,看起来您的测试将是大量数据驱动的。有许多工具允许您为单元测试定义数据集并将它们加载到测试中。例如,查看 python 测试装置。

我意识到这不是您要寻找的答案,但我认为如果您遵循这些原则,从长远来看,您会获得更多快乐。

于 2011-03-21T19:51:20.290 回答