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

文章目录

转载请注明原始出处: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方法运行测试用例将异常信息上报给调用者。

##结果检查及错误上报##

MethodChecks 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)

这里写图片描述

如果精确到后3位,则是不相等的:
这里写图片描述
如果提供了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')

运行结果如下:
这里写图片描述
###检查程序中应该抛出的异常信息###

MethodChecks 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)

运行结果如下:
这里写图片描述
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__

执行结果如下:
这里写图片描述
##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的博客)或者为这篇文章点赞,谢谢!

  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值