33.Python的单元测试工具—— unittest(高级)

  • unittest.TestCase类
    • 测试执行
      • setUp()
      • tearDown()
      • setUpClass(cls)与tearDownClass(cls)
      • skipTest(reason)
      • run(result=None)
      • debug()
    • 结果检查及错误上报
      • assertIsInstance(a, b)与assertNotIsInstance(a, b)
      • assertAlmostEqual与assertNotAlmostEqual
      • assertItemsEqual(a, b)
      • addTypeEqualityFunc(typeobj, function)
      • 检查程序中应该抛出的异常信息
      • fail(msg=None)
      • failureException(msg)
      • longMessage
      • maxDiff
    • 测试用例信息查询
      • countTestCases()
      • defaultTestResult()
      • id()
      • shortDescription()
      • addCleanup(function, *args, **kwargs)
      • doCleanups()
  • TestSuite类
    • addTest(test)
    • addTests(tests)
    • run(result)
    • debug()
    • countTestCases()

转载请注明原始出处:http://blog.csdn.net/a464057216/article/details/51889564

这篇博客详细介绍Python的unittest模块内部的类及方法的更多内容。

unittest.TestCase类

class unittest.TestCase(methodName='runTest')
这个类的实例表示一个测试用例,默认的methodNamerunTest,即最简单的测试用例类的定义只包含runTest方法的定义。如果同时定义了runTest方法和以test开头命名的方法,会忽略runTest方法。如果要指定执行某些方法,可以这样:

suite = unittest.TestSuite()
suite.addTest(Test('test_al'))
unittest.TextTestRunner(verbosity=2).run(suite)

TestCase类中定义的方法分为三大类:测试执行;结果检查及错误上报;查询测试用例信息。

测试执行

setUp()

在执行每个测试用例之前被执行,任何异常(除了unittest.SkipTestAssertionError异常以外)都会当做是error而不是failure,且会终止当前测试用例的执行。

tearDown()

执行了setUp()方法后,不论测试用例执行是否成功,都执行tearDown()方法。如果tearDown()的代码有异常(除了unittest.SkipTestAssertionError异常以外),会多算一个error。

setUpClass(cls)与tearDownClass(cls)

测试用例被执行前、后执行的方法,定义时必须加上classmethod装饰符,比如:

import unittest

class MyTestCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print 'set up class ran'

    def setUp(self):
        print 'set up test case ran'

    def test_equal(self):
        self.assertEqual(1, 1, '1 not equals 1')

    def test_true(self):
        self.assertTrue('LOO'.isupper(), 'LOO not upper')

    def tearDown(self):
        print 'tear down test case ran'

    @classmethod
    def tearDownClass(cls):
        print 'tear down class ran'

测试结果如下:

$ python -m unittest unit
set up class ran
set up test case ran
tear down test case ran
.set up test case ran
tear down test case ran
.tear down class ran

----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

skipTest(reason)

在某个测试用例函数的定义中调用skipTest(reason)会忽略这个测试用例的执行,在setUp()方法中调用,会忽略所有测试用例的执行。其实skipTest(reason)函数抛出的就是unittest.SkipTest异常。

run(result=None)

运行一个测试用例,将测试结果收集到result变量中,测试结果不返回给调用者。如果result参数的值为None,则测试结果在下面提到的defaultTestResult()方法的返回值中。比如:

import unittest

class Sample(unittest.TestCase):
    def test_a(self):
        assert 1 == 2, 'test print Errors'
        print 'test_a'

if __name__ == '__main__':
    r = unittest.TestResult()
    Sample('test_a').run(result=r)
    print r.__dict__

执行结果如下:

这里写图片描述

debug()

与run方法将测试结果存储到result变量中不同,debug方法运行测试用例将异常信息上报给调用者。

结果检查及错误上报

Method Checks that
assertEqual(a, b) a == b
assertNotEqual(a, b) a != b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a, b) a is b
assertIsNot(a, b) a is not b
assertIsNone(x) x is None
assertIsNotNone(x) x is not None
assertIn(a, b) a in b
assertNotIn(a, b) a not in b
assertIsInstance(a, b) isinstance(a, b)
assertNotIsInstance(a, b) not isinstance(a, b)
assertAlmostEqual(a, b) round(a-b, 7) == 0
assertNotAlmostEqual(a, b) round(a-b, 7) != 0
assertGreater(a, b) a > b
assertGreaterEqual(a, b) a >= b
assertLess(a, b) a < b
assertLessEqual(a, b) a <= b
assertRegexpMatches(s, r) r.search(s)
assertNotRegexpMatches(s, r) not r.search(s)
assertItemsEqual(a, b) sorted(a) == sorted(b) and works with unhashable objs

上面所有的方法都支持添加第三个字符串参数,用于出错时的信息展示。

assertIsInstance(a, b)与assertNotIsInstance(a, b)

assertIsInstance(a, b)和assertNotIsInstance(a, b)中的类型b,既可以是一个类型,也可以是类型组成的元组。

assertAlmostEqual与assertNotAlmostEqual

assertAlmostEqual(first, second, places=7, msg=None, delta=None)
assertNotAlmostEqual(first, second, places=7, msg=None, delta=None)

判断两个值是否约等于或者不约等于,places表示小数点后精确的位数。比如,如果精确到小数点后两位,1.112和1.113是相等的:

import unittest

class Test(unittest.TestCase):
    def test_al(self):
        self.assertAlmostEqual(1.111, 1.112, places=2)

33.Python的单元测试工具—— unittest(高级)_第1张图片

如果精确到后3位,则是不相等的:
33.Python的单元测试工具—— unittest(高级)_第2张图片
如果提供了delta参数,则不能同时提供places参数(这时比较两个变量的差值<=delta或者>delta)。

assertItemsEqual(a, b)

比较ab的元素相同,且不忽略重复的元素,比如[2, 3, 1]与[3, 2, 1]是items equal的,但是[2, 2, 1]和[2, 1]不是item equal的。

addTypeEqualityFunc(typeobj, function)

如果有自定义的类,这个函数可以为自定义的类提供相等性检查方法,比如:

import unittest

class Mars(object):
    def __init__(self):
        self.value = 2

    def change_to(self, value):
        self.value = value

    def get_value(self):
        return self.value

def looFunc(first, second, msg=None):
    if first.get_value() != second.get_value():
        raise unittest.TestCase.failureException(msg)

class MarsTest(unittest.TestCase):
    def __init__(self, methodName):
        super(MarsTest, self).__init__(methodName)
        self.addTypeEqualityFunc(Mars, looFunc)

    def test_my(self):
        a = Mars()
        b = Mars()
        b.change_to(6)
        self.assertEqual(a, b, 'a not equal b')

运行结果如下:
33.Python的单元测试工具—— unittest(高级)_第3张图片

检查程序中应该抛出的异常信息

Method Checks that
assertRaises(exc, fun, *args, **kwds) fun(*args, **kwds) raises exc
assertRaisesRegexp(exc, r, fun, *args,**kwds) fun(*args, **kwds) raises exc and the message matches regex r

检查异常的方法是没有错误信息提示参数的。如果期望的异常有多个,也可以给exc参数一个多个异常组成的元组,比如:

import unittest, random

def raise_exec1():
    raise Exception('mars')

def raise_exec2():
    raise random.choice([NameError('[3] failed'), TypeError('[1]')])

class MyTestCase(unittest.TestCase):
    def test_exec(self):
        self.assertRaises(Exception, raise_exec1)

    def test_exec2(self):
        self.assertRaisesRegexp((NameError, TypeError), r'\[\d\]\w*', raise_exec2)

如果只提供exc参数也是可以的,这时返回一个上线文管理器,可以配合with语句把要调用的函数放在上线文管理器中调用,并且unittest将被调用函数返回的异常赋值给上下文管理器的返回值的exception属性,比如:

import unittest

class marsException(Exception):
    error_code = 3

def raise_exec1():
    raise marsException('mars')

class MyTestCase(unittest.TestCase):
    def test_exec1(self):
        with self.assertRaises(marsException) as cm:
            raise_exec1()
        self.assertEqual(cm.exception.error_code, 3,
                'Error code error')

测试结果如下:

$ python -m unittest -v unit
test_exec1 (unit.MyTestCase) ... ok

----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

fail(msg=None)

无条件声明一个测试用例失败,msg是失败信息。

failureException(msg)

是unittest.TestCase的属性,用来表示失败的异常,默认被赋值为AssertionError。

longMessage

默认被赋值为False,如果赋值为True,可以在结果中包含更详细的diff信息。

maxDiff

默认长度80*8,用来控制diff显示的长度。

测试用例信息查询

countTestCases()

返回测试用例的个数,对于TestCase实例来说,这个返回值一直是1.

defaultTestResult()

如果在run()方法中未提供result参数,该函数返回一个包含本用例测试结果的TestResult对象。

id()

返回测试用例的编号,通常是如下格式:模块名.类名.函数名。可以用于测试结果的输出。

shortDescription()

返回测试用例的描述,即函数的docstring,如果没有,返回None。可以用于测试结果输出中描述测试内容。

addCleanup(function, *args, **kwargs)

添加针对每个测试用例执行完tearDown()方法之后的清理方法,添加进去的函数按照后进先出(LIFO)的顺序执行,当然,如果setUp()方法执行失败,那么不会执行tearDown()方法,自然也不会执行addCleanup()里添加的函数。

doCleanups()

无条件强制调用addCleanup()添加的函数,适用于setUp()方法执行失败但是需要执行清理函数的场景,或者希望在tearDown()方法之前执行这些清理函数。

TestSuite类

class unittest.TestSuite(tests=())
TestSuite类用于将测试用例分组,比如实际工作中需要将测试用例按照优先级分类。tests参数是一个可迭代的对象,每个对象可以是测试用例,也可以是测试套,比如:

import unittest

class A(unittest.TestCase):
    def test_a(self):
        print 'test_a'

class B(unittest.TestCase):
    def test_b(self):
        print 'test_b'

    def test_c(self):
        print 'test_c'

if __name__ == '__main__':
    suite1 = unittest.TestSuite(tests=[B('test_c'), A('test_a')])
    suite = unittest.TestSuite(tests=(suite1, B('test_b')))
    unittest.TextTestRunner(verbosity=2).run(suite)

运行结果如下:
33.Python的单元测试工具—— unittest(高级)_第4张图片
TestSuite类中定义了如下方法:

addTest(test)

添加测试用例,test参数可以是一个TestCase实例或者TestSuite实例。

addTests(tests)

tests参数是一个由测试用例或测试套组成的可迭代对象。

run(result)

运行测试套中包含的用例,将结果保存到result参数对应的TestResult对象中,比如:

import unittest

class A(unittest.TestCase):
    def test_a(self):
        print 'test_a'

class B(unittest.TestCase):
    def test_b(self):
        print 'test_b'

    def test_c(self):
        print 'test_c'

if __name__ == '__main__':
    suite1 = unittest.TestSuite(tests=[B('test_c'), A('test_a')])
    suite = unittest.TestSuite()
    suite.addTest(suite1)

    r = unittest.TestResult()
    suite.run(r)
    print r.__dict__

执行结果如下:
33.Python的单元测试工具—— unittest(高级)_第5张图片

debug()

与TestCase中的debug()中的功能相同,运行测试用例,如果有异常,将异常上报给调用者。

countTestCases()

返回测试套中测试用例的数量,比如:

import unittest

class A(unittest.TestCase):
    def test_a(self):
        print 'test_a'

class B(unittest.TestCase):
    def test_b(self):
        print 'test_b'

    def test_c(self):
        print 'test_c'

if __name__ == '__main__':
    suite1 = unittest.TestSuite(tests=[B('test_c'), A('test_a')])
    suite = unittest.TestSuite(tests=(suite1, B('test_b')))
    print suite.countTestCases()

运行结果为:3。

如果觉得我的文章对您有帮助,欢迎关注我(CSDN:Mars Loo的博客)或者为这篇文章点赞,谢谢!

你可能感兴趣的:(python)