单元测试unittest

unittest官方文档:unittest官方文档
推荐:unittest讲解

一、unittest框架

首先介绍一下unittest框架和执行测试用例相关的几个模块:

1、TestCase()类

TestCase类的实例表示unittest中的逻辑测试单元,此类旨在用作基类(即每个测试用例都必须继承unittest.TestCase),具体测试由具体的子类实现。该类实现了测试运行器所需的接口,以允许它驱动测试,

以及测试代码可用于检查和报告各种故障的方法。每个实例都将运行unittest的一个名为methodName的基本方法。

2、setUp()方法

该方法的主要作用是用来初始化测试环境,它在测试用例执行之前立即调用,除了AssertionError或SkipTest,通过该方法产生的任何异常都将被认为是错误的。

只有测试成功执行,才会被调用,默认什么都不做。

3、tearDown()方法

该方法的主要作用是在测试用例执行完毕后记录测试结果并恢复测试环境,即使出现异常,也会调用此方法。

4、run()方法

该方法的作用是运行测试用例,将测试结果收集到TestResult中作为传递的对象。

如果省略结果或者用None创建临时结果对象(通过调用defaultTestResult()方法),结果对象会返回给run()的调用者。

5、defaultTestResult()方法

该方法返回应该用于此测试用例类的测试结果作为实例(如果没有其他结果,实例应返回给run()方法)。

6、TestSuite()类

该类代表单个测试用例和测试套件的集合。它提供了运行测试所需的接口以使其可以像其他测试一样运行。TestSuite实例和遍历套件相同,单独运行每个测试用例。

TestSuite的行为和TestCase非常相似,但它并未实际执行测试,而是用于将测试用例聚合到一起,下面的2个方法用于向TestSuite实例中添加测试用例:

addTest():添加测试用例到TestCase或TestSuite套件中;

addTests():将迭代TestCase和TestSuite实例中的所有测试用例添加到此测试组件,相当于调用addTest()的每个元素。

7、TestLoader()类

所述TestLoader类被用来创建类和模块的测试套件。通常不需要创建该类的实例。unittest框架提供了一个可以共享的实例unittest.defaultTestLoader。

8、discover()方法

discover(start_dir, pattern =‘test *.py’, top_level_dir = None )

start_dir:要测试的模块名或测试用例目录;

pattern=‘test*.py’:表示用例文件名的匹配原则,下面的例子中匹配文件名为以“test”开头的“.py”文件,星号“*”表示任意多个字符;

top_level_dir=None:测试模块的顶层目录,如果没有顶层目录,默认为None;

该方法通过从指定的开始目录递归到子目录中查找所有测试模块,并返回包含它们的TestSuite对象,只有与模式匹配测试文件和可导入的模块名称才会被加载。

所有测试模块必须可以从项目的顶层导入,如果起始目录不是顶层目录,则顶层目录必须单独指定。

如果一个测试文件的名称符合pattern,将检查该文件是否包含 load_tests() 函数,如果 load_tests() 函数存在,则由该函数负责加载本文件中的测试用例。

如果不存在,就会执行loadTestsFromModule(),查找该文件中派生自TestCase 的类包含的 test 开头的方法。

9、TestResult()类

该类用于记录哪些测试成功或失败的信息。一个TestResult对象存储一组测试的结果,在TestCase和TestSuite中保证结果正确记录。

测试框架unittest需要访问TestResult作为报告目的运行一组测试所生成的对象,为此目的TestResult和TestRunner.run()方法返回一个实例 。

二、应用

在应用之前先了解几个概念:

  • TestCase 也就是测试用例
  • TestSuite 多个测试用例集合在一起,就是TestSuite
  • TestLoader是用来加载TestCase到TestSuite中的
  • TestRunner是来执行测试用例的,测试的结果会保存到TestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息
1、单元测试

对于测试来讲,不管是功能测试,自动化测试,还是单元测试。一般都会预设一个正确的预期结果,而在测试执行的过程中会得到一个实际的结果。测试的成功与否就是拿实际的结果与预期的结果进行比较。这个比的过程实际就是断言(assert)。

在unittest单元测试框架中提供了丰富的断言方法,例如assertEqual()、assertIn()、assertTrue()、assertIs()等,而pytest单元测试框架中并没提供特殊的断言方法,而是直接使用python的assert进行断言。

2、导入模块unittest
import unittest  #导入unittest模块
import HTMLTestRunner #导入HTMLTestRunner 报告模板模块
3、运行一个简单的unittest
import unittest   #单元测试模块

class TestCalc(unittest.TestCase):
    def test1(self):    #函数名要以test开头,否则不会被执行
        self.assertEqual(1,1)

    def test2(self):
        self.assertEqual(1,2)

unittest.main() #会运行当前python文件里面的所有测试用例
4、利用TestSuite批量执行测试用例

实际开发中测试文件可能有好几个,一个一个执行效率太低,因此是使用TestSuite批量执行测试文件能大大提高测试效率。
有以下几个步骤:

  • 创建测试套件(用例集)对象
  • 先把所有的测试用例都放到用例集
  • 运行这些测试用例
  • 产生报告
(1)利用HTMLTestRunner模块生成测试报告
  • 安装并导入HTMLTestRunner 模块,该模块是可以生成报告的模块。

  • 运行代码时,要以Run xx.py方式运行,不能以unittest方式运行,否则不会生成报告。

import unittest   #单元测试模块
import HTMLTestRunner  #用来生成报告的模块

class TestCalc(unittest.TestCase):
    def testcc(self):    #函数名要以test开头,否则不会被执行
        '''这是第一个测试用例'''       #用例描述,在函数下,用三个单引号里面写用例描述
        self.assertEqual(1,1)
        print('第一个用例')

    def testaa(self):
        '''这个是第二个测试用例'''
        self.assertEqual(1,2)
        print('第二个用例')

    def testdd(self):
        '''用例描述3'''
        print('第三个用例')

    def testbb(self):
        '''用例描述4'''
        print('第四个用例')

suite = unittest.TestSuite()  #定义一个测试集合
suite.addTest(unittest.makeSuite(TestCalc))  #把写的用例加进来(将TestCalc类)加进来
runner = HTMLTestRunner.HTMLTestRunner(output='./reports/report_name.html',title='unittest用例标题',description='这是用例描述')
runner.run(suite)  #运行用例(用例集合)

在浏览器打开生成的test.html文件
在这里插入图片描述
setup()/teardown()与setUpClass/tearDownClass

import unittest   #单元测试模块
import HTMLTestRunner  #用来生成报告的模块

class TestCalc(unittest.TestCase):
    def setUp(self):  #每个用例运行之前运行的
        print('setup是啥时候运行的')

    def tearDown(self): #每个用例运行之后运行的
        print('teardown是啥时候运行的')

    @classmethod
    def setUpClass(cls):  #在所有用例执行之前运行的
        print('我是setUpclass,我位于所有用例的开始')

    @classmethod
    def tearDownClass(cls): #在所有用例都执行完之后运行的
        print('我是tearDownClass,我位于多有用例运行的结束')

    def testcc(self):    #函数名要以test开头,否则不会被执行
        '''这是第一个测试用例'''       #用例描述,在函数下,用三个单引号里面写用例描述
        self.assertEqual(1,1)
        print('第一个用例')

    def testaa(self):
        '''这个是第二个测试用例'''
        self.assertEqual(1,1)
        print('第二个用例')

    def testdd(self):
        '''用例描述3'''
        print('第三个用例')

    def testbb(self):
        '''用例描述4'''
        print('第四个用例')

unittest.main() #会运行当前python文件里面的所有测试用例

在这里插入图片描述

(2)利用BeautifulReport模板生成测试报告
import unittest   #单元测试模块
from BeautifulReport import BeautifulReport as bf  #导入BeautifulReport模块,这个模块也是生成报告的模块,但是比HTMLTestRunner模板好看

class TestCalc(unittest.TestCase):
    def setUp(self):  #每个用例运行之前运行的
        print('setup是啥时候运行的')

    def tearDown(self): #每个用例运行之后运行的
        print('teardown是啥时候运行的')

    @classmethod
    def setUpClass(cls):  #在所有用例执行之前运行的
        print('我是setUpclass,我位于所有用例的开始')

    @classmethod
    def tearDownClass(cls): #在所有用例都执行完之后运行的
        print('我是tearDownClass,我位于多有用例运行的结束')

    def testcc(self):    #函数名要以test开头,否则不会被执行
        '''这是第一个测试用例'''       #用例描述,在函数下,用三个单引号里面写用例描述
        self.assertEqual(1,1)
        print('第一个用例')

    def testaa(self):
        '''这个是第二个测试用例'''
        self.assertEqual(1,1)
        print('第二个用例')

    def testdd(self):
        '''用例描述3'''
        print('第三个用例')

    def testbb(self):
        '''用例描述4'''
        print('第四个用例')

suite = unittest.TestSuite()  #定义一个测试集合
suite.addTest(unittest.makeSuite(TestCalc))  #把写的用例加进来(将TestCalc类)加进来
run = bf(suite) #实例化BeautifulReport模块
run.report(filename='test',description='这个描述参数是必填的')

报告页面如下图:
在这里插入图片描述

5、addTest()实例

举个例子来说,如果测试用例有下面这些:
在这里插入图片描述
使用addTest()方法执行测试用例,示例代码如下:

# coding=utf-8
import unittest

# 加载测试用例
import test_user
import test_mobile
import test_mobcode
import test_txtcode
import test_pwd
import test_signup
import test_login
import test_vipcenter
import test_search

# 将测试用例添加到测试集合
suite = unittest.TestSuite()
suite.addTest(test_user.UserTest("test_user"))           # 用户名
suite.addTest(test_mobile.MobileTest("test_mobile"))     # 手机号码
suite.addTest(test_mobcode.MobCodeTest("test_mobcode"))  # 手机验证码
suite.addTest(test_txtcode.TxtCodeTest("test_txtcode"))  # 图形验证码
suite.addTest(test_pwd.PasswordTest("test_pwd"))         # 密码
suite.addTest(test_signup.SignUpTest("test_signup"))     # 注册功能
suite.addTest(test_login.LoginTest("test_loggin"))       # 登录功能
suite.addTest(test_vipcenter.VipTest("test_vip"))        # 会员中心
suite.addTest(test_search.SearchTest("test_search"))     # 搜索功能

# 运行测试用例
runner = HTMLTestRunner.HTMLTestRunner(output='./reports/report_name.html',title='unittest用例标题',description='这是用例描述')
runner.run(suite)  #运行用例(用例集合)

可以看出需要进行很多的用例导入和添加操作,如果用例成百上千条,那么这将是一场灾难!!!

6、discover()使用实例

还是上面的那些测试用例,这次使用discover()方法批量执行用例,示例代码如下:

# coding=utf-8
import unittest
from unittest import defaultTestLoader

# 测试用例存放路径
case_path = './Testcase/case'   

# 获取所有测试用例
def get_allcase():
    discover = unittest.defaultTestLoader.discover(case_path, pattern="test*.py")
    suite = unittest.TestSuite()
    suite.addTest(discover)
    return suite

if __name__ == '__main__':
    # 运行测试用例
    runner = HTMLTestRunner.HTMLTestRunner(output='./reports/report_name.html',title='unittest用例标题',description='这是用例描述')
    runner.run(get_allcase())

也可以写成:

# coding=utf-8
import unittest
from unittest import defaultTestLoader

# 测试用例存放路径
case_path = './Testcase/case'   

# 获取所有测试用例
def get_allcase():
    discover = unittest.defaultTestLoader.discover(case_path, pattern="test*.py")
    return discover

if __name__ == '__main__':
    # 运行测试用例
    runner = HTMLTestRunner.HTMLTestRunner(output='./reports/report_name.html',title='unittest用例标题',description='这是用例描述')
    runner.run(get_allcase())

相比于addTest()方法,discover()方法更方便高效,也可以提高测试反馈速率。

PS:使用discover()方法,切记测试用例中需要执行的测试方法必须以test开头,否则无法加载!!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值