在Python中将参数从Suite提供给TestCase

发布于 2024-10-22 06:57:47 字数 1081 浏览 7 评论 0原文

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

From python documentation(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')

Here is, how invoke those testcase:

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

Is it possible to insert parameter custom_parameter into WidgetTestCase like:

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

?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

沉睡月亮 2024-10-29 06:57:47

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

WidgetTestCase.CustomParameter="some_address"

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

What I've done is in test_suite module just added

WidgetTestCase.CustomParameter="some_address"

The simplest solutions are the best :)

川水往事 2024-10-29 06:57:47

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

基本上,我所做的就是向 TestCase 添加一个 __init__ 方法,该方法定义一个“默认”参数和一个 __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 中获得自己的测试。

I've found a way to do this, but it's a bit of a cludge.

Basically, what I do is add, to the TestCase, an __init__ method which defines a 'default' parameter and a __str__ so that we can distinguish cases:

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

Then in suite(), I iterate over my test parameters, replacing the default parameter with one specific to each test:

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

where OtherWidgetTestCases are tests which don't need to be parameterised.

For instance I have a bunch of tests on real data for which a suite of tests need to be applied to each, but I also have some synthetic data sets, designed to test certain edge cases not normally present in the data, and I only need to apply certain tests to those, so they get their own tests in OtherWidgetTestCases.

书信已泛黄 2024-10-29 06:57:47

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

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 次测试

好的

正如您所看到的,场景在运行时转换为测试。

现在我还不确定这是否是一个好主意。我在测试中使用它,其中有很多以文本为中心的情况,这些情况对略有不同的数据重复相同的断言,这有助于我捕获小的边缘情况。但该要点中的课程确实有效,我相信它可以实现您所追求的目标。

请注意,通过一些技巧,测试用例可以被命名,甚至可以从文本文件或数据库等外部源中提取。它尚未记录,但在元类中进行一些挖掘应该可以帮助您入门。我的帖子此处上还有更多信息和示例。< /em>

编辑

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

This is something that has been on my mind recently. Yes it is very possible to do. I called it scenario testing, but I think parameterized may be more accurate. I put a proof of concept up as a gist here. In short it is a meta class that allows you to define a scenario and run the tests against it a bunch. With it your example can be something like this:

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)

When run, the meta class writes 2 seperate tests out so the output would be something like:

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


----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK

As you can see the scenarios are converted to tests at runtime.

Now I am not yet sure if this is even a good idea. I use it in tests where I have a lot of text centric cases that repeat the same assertions on slightly different data, which helps me to catch the little edge cases. But the classes in that gist do work and I believe it accomplishes what you are after.

Note that the with some trickery the test cases can be given names and even pulled from an external source like a text file or database. Its not documented yet but some digging around in the meta class should get you started. There is also some more info and examples on my post here.

Edit

This is an ugly hack that I do not support anymore. The implementation should have been done as a subclass of TestCase, not as a hacked meta class. Live and learn. An even better solution would be to use nose generators.

拍不死你 2024-10-29 06:57:47

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

I don't believe so, the signature for setUp needs to be what unittest is expecting, afaik, setUp is automagically called within the testcase's run method as setUp()... you're not going to be able to pass it unless you override run to pass in the var you want. But I think what you want defeats the purpose of unit testing. Don't try to use a DRY philosophy with this, each unit you're testing should be a part of a class or even part of a function/method.

行雁书 2024-10-29 06:57:47

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

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

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

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

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

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

I don't think this is a good idea. Unit tests should be thorough enough that you test all functionality in your cases so passing in different parameteres shouldn't be required.

You mention you're passing in a www address - this is almost certainly not a good idea. What happens if you try and run the tests on a machine where the 'net connection is down? Your tests should be:

  • Automatic - they will run on all machines and platforms where your app is supported, without user intervention. They shouldn't rely on external environment to pass. This means (amongst other things) that relying on a properly set up connection to the Internet is a bad idea. You can get around this by providing dummy data. Instead of passing in a URL to a resource, abstract away the data source and pass in a data-stream or whatever. This is especially easy in python since you can make use of python's duck-typing to present a stream-like object (python frequently uses a "file-like" object for this very reason!).

  • Thorough - your unit tests should have 100% code coverage, and cover all possible situations. You want to test your code with multiple sites? Instead, test your code with all the possible features that a site may include. Without knowing more about what your application does, I can't offer much advice in this point.

Now, it looks like you're tests are going to be heavily data-driven. There are many tools that allow you to define data-sets for unit tests and load them in the tests. Check out python test fixtures, for example.

I realise that this isn't the answer you're looking for, but I think you'll have more joy in the long-run if you follow these principles.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文