如何在 Python unittest 框架中简洁地实现多个类似的单元测试? [英] How do I concisely implement multiple similar unit tests in the Python unittest framework?

查看:18
本文介绍了如何在 Python unittest 框架中简洁地实现多个类似的单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为一系列共享许多不变量的函数实施单元测试.例如,使用两个矩阵调用该函数会生成一个已知形状的矩阵.

I'm implementing unit tests for a family of functions that all share a number of invariants. For example, calling the function with two matrices produce a matrix of known shape.

我想编写单元测试来测试此属性的整个函数系列,而不必为每个函数编写单独的测试用例(特别是因为以后可能会添加更多函数).

I would like to write unit tests to test the entire family of functions for this property, without having to write an individual test case for each function (particularly since more functions might be added later).

一种方法是迭代这些函数的列表:

One way to do this would be to iterate over a list of these functions:

import unittest
import numpy

from somewhere import the_functions
from somewhere.else import TheClass

class Test_the_functions(unittest.TestCase):
  def setUp(self):
    self.matrix1 = numpy.ones((5,10))
    self.matrix2 = numpy.identity(5)

  def testOutputShape(unittest.TestCase):
     """Output of functions be of a certain shape"""
     for function in all_functions:
       output = function(self.matrix1, self.matrix2)
       fail_message = "%s produces output of the wrong shape" % str(function)
       self.assertEqual(self.matrix1.shape, output.shape, fail_message)

if __name__ == "__main__":
  unittest.main()

我从 深入 Python 中得到了这个想法.在那里,它不是正在测试的函数列表,而是已知输入-输出对的列表.这种方法的问题在于,如果列表中的任何元素未通过测试,后面的元素就不会得到测试.

I got the idea for this from Dive Into Python. There, it's not a list of functions being tested but a list of known input-output pairs. The problem with this approach is that if any element of the list fails the test, the later elements don't get tested.

我查看了 unittest.TestCase 的子类化,并以某种方式提供了要测试的特定函数作为参数,但据我所知,这阻止了我们使用 unittest.main(),因为无法将参数传递给测试用例.

I looked at subclassing unittest.TestCase and somehow providing the specific function to test as an argument, but as far as I can tell that prevents us from using unittest.main() because there would be no way to pass the argument to the testcase.

我还研究了通过使用带有 lamdba 的 setattr 将testSomething"函数动态附加到测试用例,但测试用例无法识别它们.

I also looked at dynamically attaching "testSomething" functions to the testcase, by using setattr with a lamdba, but the testcase did not recognize them.

如何重写它,以便扩展测试列表仍然微不足道,同时仍确保运行每个测试?

How can I rewrite this so it remains trivial to expand the list of tests, while still ensuring every test is run?

推荐答案

您可以使用元类来动态插入测试.这对我来说很好用:

You could use a metaclass to dynamically insert the tests. This works fine for me:

import unittest

class UnderTest(object):

    def f1(self, i):
        return i + 1

    def f2(self, i):
        return i + 2

class TestMeta(type):

    def __new__(cls, name, bases, attrs):
        funcs = [t for t in dir(UnderTest) if t[0] == 'f']

        def doTest(t):
            def f(slf):
                ut=UnderTest()
                getattr(ut, t)(3)
            return f

        for f in funcs:
            attrs['test_gen_' + f] = doTest(f)
        return type.__new__(cls, name, bases, attrs)

class T(unittest.TestCase):

    __metaclass__ = TestMeta

    def testOne(self):
        self.assertTrue(True)

if __name__ == '__main__':
    unittest.main()

这篇关于如何在 Python unittest 框架中简洁地实现多个类似的单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆