unittest之TextTestRunner类详解

TextTestRunner

不知道如何翻译这个单词才好,我就叫它文本类测试用例运行器吧,大概就这个意思。

通过前两篇对TestCase和TestSuite类的详解,我们都知道他们都有一个自己的run方法,其实我们可以直接调用他们各自的run方法就可以执行我们的测试用例或测试集了,我们只需要初始化一个TestResult类或者其子类的实例传入到第一个参数即可,比如:

import sys
import unittest
class UserCase(unittest.TestCase):

    def testAddUser(self):
        print("add a user")

    def testDelUser(self):
        print("delete a user")

if __name__ == '__main__':
    result = unittest.TextTestResult(sys.stdout,'test result',1)
    testcase = UserCase('testAddUser')
    testcase.run(result)    #我们只需要传入一个result对象即可

那何必还需要一个TextTestRunner类呢,个人觉得主要是为了控制测试结果的输出,为什么这么说呢,大家可以自己动手实践一下,对比一下直接使用TestCase的run方法运行后的结果和通过TextTestRunner的run方法运行的结果输出有什么不同。扩展HTMLTestRunner大神,其扩展的主要也就是TestRunner部分(当然还有扩展TestResult)使其结果输出为HTML的报告,所以想要自定义的控制测试结果(即result)的输出,可以从扩展TestRunner这里入手。

我们先来看一下我们自己写代码时用TextTestRunner是怎么去执行用例的。

import unittest
class UserCase(unittest.TestCase):

    def testAddUser(self):
        print("add a user")

    def testDelUser(self):
        print("delete a user")

if __name__ == '__main__':
    runner = unittest.TextTestRunner()
    suite = unittest.TestSuite(map(UserCase,['testAddUser','testDelUser']))
    case = UserCase('testAddUser')

    runner.run(suite)
    runner.run(case)

从代码里面可以看到我们是通过TextTestRunner类实例的run方法去执行的用例或用例集。下面我们来分析一下run方法:

def run(self, test):
    "Run the given test case or test suite."
    result = self._makeResult()
    registerResult(result)
    result.failfast = self.failfast
    result.buffer = self.buffer
    startTime = time.time()
    startTestRun = getattr(result, 'startTestRun', None)
    if startTestRun is not None:
        startTestRun()
    try:
        test(result)
    finally:
        stopTestRun = getattr(result, 'stopTestRun', None)
        if stopTestRun is not None:
            stopTestRun()
    stopTime = time.time()
    timeTaken = stopTime - startTime
    result.printErrors()
    if hasattr(result, 'separator2'):
        self.stream.writeln(result.separator2)
    run = result.testsRun
    self.stream.writeln("Ran %d test%s in %.3fs" %
                        (run, run != 1 and "s" or "", timeTaken))
    self.stream.writeln()

    expectedFails = unexpectedSuccesses = skipped = 0
    try:
        results = map(len, (result.expectedFailures,
                            result.unexpectedSuccesses,
                            result.skipped))
    except AttributeError:
        pass
    else:
        expectedFails, unexpectedSuccesses, skipped = results

    infos = []
    if not result.wasSuccessful():
        self.stream.write("FAILED")
        failed, errored = map(len, (result.failures, result.errors))
        if failed:
            infos.append("failures=%d" % failed)
        if errored:
            infos.append("errors=%d" % errored)
    else:
        self.stream.write("OK")
    if skipped:
        infos.append("skipped=%d" % skipped)
    if expectedFails:
        infos.append("expected failures=%d" % expectedFails)
    if unexpectedSuccesses:
        infos.append("unexpected successes=%d" % unexpectedSuccesses)
    if infos:
        self.stream.writeln(" (%s)" % (", ".join(infos),))
    else:
        self.stream.write("\n")
    return result

其实这么长一段的代码,最重要的一行代码是:test(result),其中test是我们传入的TestCase类的实例或TestSuite类的实例,所以这句代码最终调用的就是TestCase类的run方法或TestSuite类的run方法,而这两个run方法就在我前两篇文章分析的内容里面,忘记的朋友可以回到前面再去阅读一番。

对于其他部分的代码,分析起来就太多了,基本都是处理result的内容(即测试结果数据的处理),这里也暂时不做详细的分析了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值