unittest单元测试框架

认识unittest

Python语言下的单元测试框架,如doctest、unittest、pytest、nose等

unittest框架(原名PyUnit框架)为Python语言自带的单元测试框架

认识单元测试

重要的概念

test fixture、test case、test suite和test runner,只有理解了这几个概念才能理解单元测试的基本特征。

1.Test Case

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

2.Test Suite

一个功能的验证往往需要多个测试用例,可以把多个测试用例集合在一起来执行,这就产生了测试套件TestSuite的概念。Test Suite用来组装单个测试用例。可以通过addTest加载TestCase到TestSuite中,从而返回一个TestSuite实例。

3.Test Runner

测试的执行也是单元测试中非常重要的一个概念,一般单元测试框架中都会提供丰富的执行策略和执行结果。在unittest单元测试框架中,通过TextTestRunner类提供的run()方法来执行test suite/test case。test runner可以使用图形界面、文本界面,或返回一个特殊的值等方式来表示测试执行的结果。

4.Test Fixture

对一个测试用例环境的搭建和销毁,就是一个fixture,通过覆盖TestCase的**setUp()tearDown()**方法来实现。有什么用呢?比如说在这个测试用例中需要访问数据库,那么可以在setUp()中通过建立数据库连接来进行初始化,在tearDown()中清除数据库产生的数据,然后关闭连接等。

tearDown的过程很重要,要为下一个test case留下一个干净的环境。

断言方法

在UnitTest中封装了一些成熟断言,可以直接调用

序号方法和描述
1void assertEquals(boolean expected, boolean actual)
检查两个变量或者等式是否平衡
2void assertFalse(boolean condition)
检查条件是假的
3void assertNotNull(Object object)
检查对象不是空的
4void assertNull(Object object)
检查对象是空的
5void assertTrue(boolean condition)
检查条件为真
6void fail()
在没有报告的情况下使测试不通过

组织单元测试用例

创建MyTest()类的好处显而易见,对于测试类和测试方法来说,应将注意力放在具体用例的编写上,无须关心setUp()和tearDown()所做的事情。不过,前提条件是setUp()和tearDown()所做的事情是每个用例都需要的。

discover更多测试用例

TestLoader类中提供的discover()方法可以解决这个问题。

    TestLoader
    discover(start_dir,pattern='test*.py',top_level_dir=None)
    
start_dir:要测试的模块名或测试用例目录。
pattern='test*.py':表示用例文件名的匹配原则。此处匹配文件名以“test”开头的“.py”类型的文件,星号“*”表示任意多个字符。
top_level_dir=None:测试模块的顶层目录,如果没有顶层目录,默认为None
import unittest
# 定义测试用例的目录为当前目录
test_dir = './'
discover = unittest.defaultTestLoader.discover(test_dir, pattern='test*.py')
if __name__ == '__main__':
    runner = unittest.TextTestRunner()
    runner.run(discover)

discover()方法会自动根据测试目录(test_dir)匹配查找测试用例文件(test*.py),并将查找到的测试用例组装到测试套件中,因此,可以直接通过run()方法执行discover,大大简化了测试用例的查找与执行。

关于unittest还需要知道的

用例执行的顺序

unittest框架默认根据ASCII码的顺序加载测试用例,数字与字母的顺序为:0-9,A-Z,a-z。

并没有按照用例从上到下的顺序执行。

通过TestSuite类的addTest()方法,可以按照一定的顺序来加载。

执行多级目录的用例

跳过测试和预期失败

 @unittest.skip(reason)

无条件地跳过装饰的测试,说明跳过测试的原因。

 @unittest.skipIf(condition, reason)

跳过装饰的测试,如果条件为真时。

 @unittest.skipUnless(condition, reason)

跳过装饰的测试,除非条件为真。

 @unittest.expectedFailure()

测试标记为失败。不管执行结果是否失败,统一标记为失败。

test.py

import unittest
"""
    共创建了4条测试用例。
    第一条测试用例通过@unittest.skip()装饰,直接跳过不执行。
    
    第二条用例通过@unittest.skipIf()装饰,
        当条件为真时不执行,3>2条件为真(True),跳过不执行。
        
    第三条用例通过@unittest.skipUnless()装饰,
        当条件为真时执行,判断3>2条件为真(True),第三条用例执行。
        
    第四条用例通过@unittest.expectedFailure装饰,
        不管执行结果是否失败,统一标记为失败,但不会抛出错误信息。
"""

class MyTest(unittest.TestCase):
    def setUp(self):
        pass
    def tearDown(self):
        pass
    @unittest.skip("直接跳过测试")
    def test_skip(self):
        print("test aaa")
    @unittest.skipIf(3 > 2, "当条件为True时跳过测试")
    def test_skip_if(self):
        print('test bbb')
    @unittest.skipUnless(3 > 2, "当条件为True时执行测试")
    def test_skip_unless(self):
        print('test ccc')
    @unittest.expectedFailure
    def test_expected_failure(self):
        self.assertEqual(2, 3)
if __name__ == '__main__':
    unittest.main()
    
    #Python Shell:OK (skipped=2, expected failures=1)

fixtures

fixtures的概念,可以形象地把它看作是夹心饼干外层的两片饼干,这两片饼干就是setUp/tearDown,中间的心就是测试用例。

除此之外,unittest还提供了更大范围的fixtures,例如对于测试类和模块的fixtures。

import unittest
def setUpModule():
    print("test module start >>>>>>>>>>>>>>")
def tearDownModule():
    print("test module end >>>>>>>>>>>>>>")
class Test(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print("test class start =======>")
    @classmethod
    def tearDownClass(cls):
        print("test class end  =======>")
    def setUp(self):
        print("test case start -->")
    def tearDown(self):
        print("test case end -->")
    def test_case(self):
        print("test case1")
    def test_case2(self):
        print("test case2")
if __name__ == '__main__':
    unittest.main()
    
#Python Shell
test module start >>>>>>>>>>>>>>
test class start =======>
test case start -->
test case1
test case end -->
test case start -->
test case2
test case end -->
test class end  =======>
test module end >>>>>>>>>>>>>>

setUpModule/tearDownModule: 在整个模块的开始与结束时被执行。

setUpClass/tearDownClass: 在测试类的开始与结束时被执行。

setUp/tearDown: 在测试用例的开始与结束时被执行。

需要注意的是,setUpClass/tearDownClass的写法稍微有些不同。首先,需要通过**@classmethod进行装饰,其次方法的参数为cls**。其实,cls与self并没有什么特别之处,都只表示类方法的第一个参数,只是大家约定俗成,习惯于这样来命名,当然也可以用abc来代替。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值