unittest

源码路径:python安装目录Lib\unittest,主要包含__init__.py,__main__.py,case.py,loader.py,main.py,result.py,runner.py,signals.py,suite.py,utils.py文件。

2、自带的unittest测试用例案例

import unittest

class IntegerArithmeticTestCase(unittest.TestCase):

    def testAdd(self):  ## test method names begin 'test*'

        self.assertEqual((1 + 2), 3)

        self.assertEqual(0 + 1, 1)

    def testMultiply(self):

        self.assertEqual((0 * 10), 0)

        self.assertEqual((5 * 8), 40)

if __name__ == '__main__':

        unittest.main()

3、执行流程概述

1)unittest.main(),进入main.py文件,可以看到main = TestProgram,说明实际上调用了main.py中的TestProgram类的构造函数。

def __init__(self, module='__main__', defaultTest=None, argv=None,

                testRunner=None, testLoader=loader.defaultTestLoader,

                exit=True, verbosity=1, failfast=None, catchbreak=None,

                buffer=None):

    if isinstance(module, basestring):

        self.module = __import__(module)

        for part in module.split('.')[1:]:

            self.module = getattr(self.module, part)

    else:

        self.module = module

    if argv is None:

        argv = sys.argv

    self.exit = exit

    self.failfast = failfast

    self.catchbreak = catchbreak

    self.verbosity = verbosity

    self.buffer = buffer

    self.defaultTest = defaultTest

    self.testRunner = testRunner

    self.testLoader = testLoader

    self.progName = os.path.basename(argv[0])

    self.parseArgs(argv)

    self.runTests()

2)testLoader=loader.defaultTestLoader,在load.py文件中可以看到defaultTestLoader = TestLoader(),说明实际上

3)self.parseArgs(argv),执行自己类的parseArgs方法,在parseArgs中会执行自己类的createTests方法

def createTests(self):

    if self.testNames is None:

        self.test = self.testLoader.loadTestsFromModule(self.module)

    else:

        self.test = self.testLoader.loadTestsFromNames(self.testNames,

                                                      self.module)

这里的testName为空,所以会执行testLoader.loadTestsFromModule(self.module),进入loader.py的loadTestsFromModule:

def loadTestsFromModule(self, module, use_load_tests=True):

    """Return a suite of all tests cases contained in the given module"""

    tests = []

    for name in dir(module):

        obj = getattr(module, name)

        if isinstance(obj, type) and issubclass(obj, case.TestCase):

            tests.append(self.loadTestsFromTestCase(obj))

    load_tests = getattr(module, 'load_tests', None)

    tests = self.suiteClass(tests)

    if use_load_tests and load_tests is not None:

        try:

            return load_tests(self, tests, None)

        except Exception, e:

            return _make_failed_load_tests(module.__name__, e,

                                          self.suiteClass)

    return tests

这里是把self.loadTestsFromTestCase(obj)得到suite追加到tests列表中,然后把tests也转化为suite,并且返回。(这里面包含了所有的TestCase)

4)然后执行self.runTests()

def runTests(self):

    if self.catchbreak:

        installHandler()

    if self.testRunner is None:

        self.testRunner = runner.TextTestRunner

    if isinstance(self.testRunner, (type, types.ClassType)):

        try:

            testRunner = self.testRunner(verbosity=self.verbosity,

                                        failfast=self.failfast,

                                        buffer=self.buffer)

        except TypeError:

            # didn't accept the verbosity, buffer or failfast arguments

            testRunner = self.testRunner()

    else:

        # it is assumed to be a TestRunner instance

        testRunner = self.testRunner

    self.result = testRunner.run(self.test)

    if self.exit:

        sys.exit(not self.result.wasSuccessful())

在runTests()中会执行testRunner.run(self.test),也就是说会去执行run.py中的run方法,并把原先获取的TestSuite对想传入。

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

在run中,通过一个for循环依次调用TestCase的run方法去执行具体的测试用例(这里要注意的是,如果test还是TestSuite类型,会继续递归调用)。

unittest中最核心的四部分是:TestCase,TestSuite,TestRunner,TestFixture

(1)一个TestCase的实例就是一个测试用例。测试用例就是指一个完整的测试流程,包括测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown)。元测试(unit test)的本质也就在这里,一个测试用例是一个完整的测试单元,通过运行这个测试单元,可以对某一个问题进行验证。

(2)而多个测试用例集合在一起,就是TestSuite,而且TestSuite也可以嵌套TestSuite。

(3)TestLoader是用来加载TestCase到TestSuite中的。

(4)TextTestRunner是来执行测试用例的,其中的run(test)会执行TestSuite/TestCase中的run(result)方法

(5)测试的结果会保存到TextTestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息。


综上,整个流程就是首先要写好TestCase,然后由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,整个过程集成在unittest.main模块

2、unittest之装饰器(@classmethod)

1)unittest里面setUp可以在每次执行用例前执行,这样有效的减少了代码量,但是有个弊端,比如打开浏览器操作,每次执行用例时候都会重新打开,这样就会浪费很多时间。

于是就想是不是可以只打开一次浏览器,执行完用例再关闭呢?这就需要用到装饰器(@classmethod)来解决了。

2)用setUp与setUpClass区别

setup():每个测试case运行前运行

teardown():每个测试case运行完后执行

setUpClass():必须使用@classmethod 装饰器,所有case运行前只运行一次

tearDownClass():必须使用@classmethod装饰器,所有case运行完后只运行一次

3、skip装饰器

skip装饰器一共有三个

unittest,skip(reason):无条件跳过

unittest.skipIf(condition, reason):当condition为True时跳过

unittest.skipUnless(condition, reason):当condition为False时跳过

你可能感兴趣的:(unittest)