目前,我有许多类似的单元测试TestCases。每个TestCase都包含数据(输入值+预期输出值)和逻辑(调用SUT并将实际输出与预期输出进行比较)。

我想将数据与逻辑分离。因此,我想要一个仅包含逻辑的基类和一个仅包含数据的派生类。到目前为止,我想到了这一点:

import unittest

class MyClass():
    def __init__(self, input):
        self.input = input
    def get_result(self):
        return self.input * 2

class TestBase(unittest.TestCase):
    def check(self, input, expected_output):
        obj = self.class_under_test(input)
        actual_output = obj.get_result()
        self.assertEqual(actual_output, expected_output)

    def test_get_result(self):
        for value in self.values:
            self.check(value[0], value[1])

class TestMyClass(TestBase):
    def __init__(self, methodName='runTest'):
        unittest.TestCase.__init__(self, methodName)
        self.class_under_test = MyClass
        self.values = [(1, 2), (3, 6)]

unittest.main(exit = False)

但这失败,并显示以下错误:
AttributeError: 'TestBase' object has no attribute 'values'

两个问题:
  • 我的“设计”好吗?
  • 要使它正常工作还需要什么?
  • 最佳答案

    这种设计(或多或少)很好-一个“打cup”是当unittest查看所有TestCase类并在它们上运行以“test”开头的方法时。此时,您有一些选择。

    一种方法是将被测类和值指定为该类的属性。在这里,如果可能的话,您将希望这些值是不可变的...

    class TestBase(unittest.TestCase):
    
        def check(self, input, expected_output):
            obj = self.class_under_test(input)
            actual_output = obj.get_result()
            self.assertEqual(actual_output, expected_output)
    
        def check_all(self):
            for value in self.values:
                self.check(value[0], value[1])
    
    class TestMyClass1(TestBase):
        values = ((1, 2), (3, 4))
        class_under_test = MyClass1
    
        def test_it(self):
            self.check_all()
    
    class TestMyClass2(TestBase):
        values = (('a', 'b'), ('d', 'e'))
        class_under_test = MyClass2
    
        def test_it(self):
            self.check_all()
    

    09-06 06:05