Python单元测试在运行所有测试后运行函数

17

我需要通过ssh在Python上测试某些内容。我不想为每个测试建立ssh连接,因为这太费时间了,所以我写了这个:

class TestCase(unittest.TestCase):
    client = None
    def setUp(self):
        if not hasattr(self.__class__, 'client') or self.__class__.client is None:
            self.__class__.client = paramiko.SSHClient()
            self.__class__.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            self.__class__.client.connect(hostname=consts.get_host(), port=consts.get_port(), username=consts.get_user(),
                                password=consts.get_password())

    def test_a(self):
        pass

    def test_b(self):
        pass

    def test_c(self):
        pass

    def disconnect(self):
        self.__class__.client.close()

和我的赛跑者

if __name__ == '__main__':
    suite = unittest.TestSuite((
        unittest.makeSuite(TestCase),
    ))
    result = unittest.TextTestRunner().run(suite)
    TestCase.disconnect()
    sys.exit(not result.wasSuccessful())

在这个版本中,我遇到了错误 TypeError: unbound method disconnect() must be called with TestCase instance as first argument (got nothing instead)。那么在所有测试通过后,我该如何调用disconnect呢?
敬礼。

3个回答

25

如果您想为所有测试保留相同的连接,那么应该使用setUpClasstearDownClass。同时,您还需要将disconnect方法设置为静态方法,这样它就属于类而不是类的实例。

class TestCase(unittest.TestCase):

     def setUpClass(cls):
         cls.connection = <your connection setup>

     @staticmethod
     def disconnect():
         ... disconnect TestCase.connection

     def tearDownClass(cls):
         cls.disconnect()

10
在Python 3中,类函数需要使用@classmethod修饰符。 - Løiten

9
你可以通过定义unittest.TestResult类的startTestRunstopTestRun来实现。而setUpClasstearDownClass会在每个测试类(即每个测试文件)中运行,所以如果你有多个文件,则这些方法将针对每个文件运行。
通过在tests/__init__.py中添加以下代码,我成功地做到了这一点。这段代码对于所有测试仅运行一次(无论测试类和测试文件的数量)。
def startTestRun(self):
    """
    https://docs.python.org/3/library/unittest.html#unittest.TestResult.startTestRun
    Called once before any tests are executed.

    :return:
    """
    DockerCompose().start()


setattr(unittest.TestResult, 'startTestRun', startTestRun)


def stopTestRun(self):
    """
    https://docs.python.org/3/library/unittest.html#unittest.TestResult.stopTestRun
    Called once after all tests are executed.

    :return:
    """
    DockerCompose().compose.stop()


setattr(unittest.TestResult, 'stopTestRun', stopTestRun)

那么你如何确保TestSuite使用你自定义的TestResult呢? - Joseph Woolf
我看到了这个答案,只是想澄清一下setattr仅在def stopTestRun下面的类中使用。 - Ben

1

对于基本(初学者)情况,似乎有一个简单的解决方案:

def tmain():
    setup()
    unittest.main(verbosity=1, exit=False)
    clean()

这个技巧是使用"exit=False",让函数tmain一直运行到结束。setup()和clean()可以是任何函数,用于执行其名称所示的操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接