Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用python unittest抽象测试用例_Python_Unit Testing_Testcase - Fatal编程技术网

使用python unittest抽象测试用例

使用python unittest抽象测试用例,python,unit-testing,testcase,Python,Unit Testing,Testcase,是否可以创建一个抽象的TestCase,它将有一些测试方法,但是不会调用这个TestCase,并且这些方法将只在子类中使用?我想我将在我的测试套件中有一个抽象的TestCase,它将为单个接口的几个不同实现子类化。这就是为什么所有的测试方法都是一些,只有一个,内部方法的变化。如何以优雅的方式完成它?如果您遵循在run\u unittest中显式列出所有测试类的约定(参见Python测试套件了解该约定的许多用法),那么不列出特定的类将是直接的 如果您想继续使用unittest.main,并且如果您

是否可以创建一个抽象的
TestCase
,它将有一些测试方法,但是不会调用这个
TestCase
,并且这些方法将只在子类中使用?我想我将在我的测试套件中有一个抽象的
TestCase
,它将为单个接口的几个不同实现子类化。这就是为什么所有的测试方法都是一些,只有一个,内部方法的变化。如何以优雅的方式完成它?

如果您遵循在run\u unittest中显式列出所有测试类的约定(参见Python测试套件了解该约定的许多用法),那么不列出特定的类将是直接的


如果您想继续使用unittest.main,并且如果您可以允许使用unittest2(例如,来自Python2.7),您可以使用它的协议来指定哪些类包含测试用例)。在早期版本中,您必须将TestLoader子类化并重写。

我不太明白您打算做什么-- 经验法则是“不要对测试很聪明”—— 把它们放在那里,写得很清楚

但是为了实现您想要的,如果您从unittest.TestCase继承,那么无论何时调用unittest.main(),您的“抽象”类都将被执行——我认为这是您想要避免的情况

只要这样做: 创建从“对象”继承的“抽象”类,而不是从TestCase继承的类。 对于实际的“具体”实现,只需使用多重继承: 从unittest.TestCase和抽象类继承

import unittest

class Abstract(object):
    def test_a(self):
        print "Running for class", self.__class__

class Test(Abstract, unittest.TestCase):
    pass

unittest.main()

更新:首先颠倒继承顺序-
抽象
,这样它的定义就不会被
测试用例
默认值覆盖,下面的注释中也指出了这一点。

多重继承在这里不是一个很好的选择,主要是因为以下两个原因:

  • TestCase
    中没有一个方法使用
    super()
    ,因此您必须首先列出类,才能使用
    setUp()
    tearDown()等方法
  • pylint将警告基类使用的
    self.assertEquals()
    etc未在
    self
    上定义
  • 下面是我提出的一个难题:将
    run()
    变成只对基类有效的no-op

    类TestBase(unittest.TestCase): 定义初始化(self,*args,**kwargs): super(TestBase,self)。\uuuuuu初始化(*args,**kwargs) self.helper=无 #Kludge警报:我们希望这个类在不运行的情况下携带测试用例 #通过单元测试框架,因此“run”方法被重写 #没什么。但是为了让子类能够在 #调用run时,构造函数将从TestCase重新绑定“run”。 如果是self.\uuuuuu class\uuuuuu!=测试库: #从父类重新绑定“run”。 self.run=unittest.TestCase.run.\uuuuu获取\uuuuuuu(self,self.\uuuuuu类) 其他: self.run=lambda self,*args,**kwargs:None def新助手(自我): 引发未实现的错误() def设置(自): 打印“为所有子类共享” self.helper=self.newHelper() def testFoo(self): 打印“为所有子类共享” #用self.helper测试某事 类Test1(TestBase): def新助手(自我): 返回帮助对象1() 类Test2(TestBase): def新助手(自我): 返回帮助对象2()
    恕我直言,尽管这可能违反某些惯例,但您可以将抽象测试用例定义为受保护的成员,以防止其执行。我在Django中实现了以下内容,并按要求工作。见下面的例子

    from django.test import TestCase
    
    
    class _AbstractTestCase(TestCase):
    
        """
        Abstract test case - should not be instantiated by the test runner.
        """
    
        def test_1(self):
            raise NotImplementedError()
    
        def test_2(self):
            raise NotImplementedError()
    
    
    class TestCase1(_AbstractTestCase):
    
        """
        This test case will pass and fail.
        """
    
        def test_1(self):
            self.assertEqual(1 + 1, 2)
    
    
    class TestCase2(_AbstractTestCase):
    
        """
        This test case will pass successfully.
        """
    
        def test_1(self):
            self.assertEqual(2 + 2, 4)
    
        def test_2(self):
            self.assertEqual(12 * 12, 144)
    

    Python unittest库具有,可用于实现您想要的功能:

    #使用AbstractTestCase类将此函数添加到模块中
    def加载测试(加载程序、测试):
    结果=[]
    对于测试中的测试用例:
    如果类型(test\u case.\u tests[0])是AbstractTestCase:
    持续
    result.append(测试用例)
    返回加载器。suiteClass(结果)
    
    到目前为止,每个人都错过了一个非常简单的方法。与一些答案不同的是,它适用于所有测试驱动程序,而不是在您切换它们时失败

    只需像往常一样使用继承,然后添加:

    del AbstractTestCase
    

    如果您真的想使用继承而不是混合,一个简单的解决方案是将抽象测试嵌套在另一个类中

    它避免了测试运行程序发现的问题,并且您仍然可以从另一个模块导入抽象测试

    import unittest
    
    class AbstractTests(object):
        class AbstractTest(unittest.TestCase)
            def test_a(self):
                print "Running for class", self.__class__
    
    class Test(AbstractTests.AbstractTest):
        pass
    

    想要做OP正在做的事情的另一个原因是创建一个高度参数化的基类,该基类实现了需要在多个环境/场景中重现的一组核心测试。我所描述的本质上是使用unittest创建一个参数化的fixture,一个la pytest

    假设您(像我一样)决定尽可能快地逃离任何基于多继承的解决方案,那么使用load_tests()从加载的套件中筛选出基类可能会出现以下问题:

    在标准TestLoader中,从类自动加载完成后调用load_测试。因为: *此自动从类加载将尝试使用标准签名init(self,name)和 *您可能希望这个基类具有非常不同的ctor签名,或者 *您可能希望跳过构建,然后出于其他原因删除基类实例

    。。您可能希望完全防止从基类自动加载测试实例

    编辑:是一种更优雅、简洁、独立的方式。我已经实现了“嵌套类技巧”,并确认它可以很好地防止TestLoader“找到”您的测试用例库

    我最初是通过修改TestLoader.loadTestsFromModule来完成的,只需跳过
    for name in dir(module):
        obj = getattr(module, name)
        # skip TestCase classes:
        # 1. without any test methods defined
        # 2. that are base classes
        #    (we don't allow instantiating TestCase base classes, which allows test designers
        #     to implement actual test methods in highly-parametrized base classes.)
        if isinstance(obj, type) and issubclass(obj, unittest.TestCase) and \
                self.getTestCaseNames(obj) and not isbase(obj, module):
            loaded_suite = self.loadTestsFromTestCase(obj)
            # ignore empty suites
            if loaded_suite.countTestCases():
                tests.append(loaded_suite)
    
    def isbase(cls, module):
        '''Returns True if cls is base class to any classes in module, else False.'''
        for name in dir(module):
            obj = getattr(module, name)
            if obj is not cls and isinstance(obj, type) and issubclass(obj, cls):
                return True
        return False
    
    class AbstractTest(TestCase):
        def setUp(self):
            pass
    
        def tearDown(self):
            pass
    
        def _test_1(self):
            # your test case here
    
    class ConcreteTest(AbstractTest)
    
        def test_1(self):
            self._test_1()
    
    class BaseTestCase(unittest.TestCase):
      @classmethod
      def setUpClass(cls):
        if cls is BaseTestCase:
          raise unittest.SkipTest("%s is an abstract base class" % cls.__name__)
        else:
          super(BaseTestCase, cls).setUpClass()