当前位置:   article > 正文

单元测试框架:unittest入门

unittest

一、unittest 组件

1、TestCase(测试用例):一个testcase的实例就是一个测试用例;unittest 中执行测试的最小单元,通过验证 unittest 提供的 assert 方法来验证一组特定的操作和输入以后得到的响应;unittest 提供了一个名为 TestCase 的基础类,可以用来创建测试用例;
2、TestSuite(测试套件):多个测试用例集合在一起,TestLoader是用来加载TestCase到TestSuite中的;一个测试套件是多个测试用例的集合,是针对被测程序的对应的功能和模块创建的一组测试,一个测试套件内的测试用例将一起执行;
3、TestLoader(测试收集):按目录及命名规则收集可用的testcase,并返回一个testsuite对象
4、TextTestRunner(测试执行器):用来执行测试用例的;测试执行器负责测试执行调度并且生成测试结果给用户;测试执行器可以使用图形界面、文本界面或者特定的返回值来展示测试执行结果;
5、TestReport(测试报告):测试报告展示所有执行用例的成功或者失败状态的汇总;包括失败的测试步骤的预期结果和实际结果,还有整体运行状况和运行时间的汇总;
6、fixture(测试夹具):测试用例环境的搭建和销毁;测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown);使用测试夹具,可以定义在单个或多个测试执行之前的准备工作和测试执行之后的清理工作;

二、unittest中的测试用例定义的规范:unittest.TestCase

1、定义一个类,这个类必须要继承unittest.TestCase这个类;
2、测试类中,一个以test开头的方法,就是一条测试用例;

import unittest
class TestDemo1(unittest.TestCase):
    def test_01add(self):
        # 第一步:准备用例数据
        params = {'a': 11, 'b': 22, 'method': '+'}
        expected = 33
        # 第二步:调用功能函数(调用接口),获取实际结果
        result = counter(**params)
        # 第三步:比对预期结果和实际结果是否一致(断言)
        # assert expected == result
        self.assertEqual(expected, result)# 比上面的assert打印更多信息   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

测试用例内部报错只会影响该测试用例本身是否成功,不会影响程序整体运行。

三、编写自动化测试用例的步骤

1、准备用例数据;
2、调用功能函数(调用接口),获取实际结果;
3、比对预期结果和实际结果是否一致(断言);

四、关于断言

1、Python中内置了一个关键字assert,专门用来进行断言的,断言assert后面的条件语句是否为true;如:assert 'res' == 'expected'
2、unittest中封装好了很多的断言方法:如:self.assertEqual():断言两个值是否相等;
3、断言方法:
(1)断言两个值是否相等:self.assertEqual(11, 22),即【a==b】
(2)断言两个值不相等:self.assertNotEqual(11, 22),即【a!=b】
(3)断言数据的布尔值是否为True【python中非0为True, 数据的值为0、数据的长度为0、None的布尔值为False】:self.assertTrue('python'),即【bool(x) is True】
(4)断言数据的布尔值是否为False:self.assertFalse(''),即【bool(x) is False】
(5)成员运算符断言:self.assertIn('错误','账号错误'),即【a in b】
(6)非成员断言:self.assertNotIn('错误', '登录成功'),即【a not in b】

五、测试套件:unittest.TestSuite、unittest.TestLoader

1、套件的定义:

suite = unittest.TestSuite()
  • 1

2、创建一个用例加载器:

load = unittest.TestLoader()
  • 1

3、往套件中添加用例:
(1)添加测试类到测试套件load.loadTestsFromTestCase

from py.demo1_testcase import TestDemo1    
suite.addTest(load.loadTestsFromTestCase(TestDemo1))
  • 1
  • 2

(2)添加测试模块到测试套件load.loadTestsFromModule

from py import demo1_testcase
suite.addTest(load.loadTestsFromModule(demo1_testcase))
  • 1
  • 2

(3) 最常用:添加一个测试的目录load.discover;测试用例目录下面的用例模块必须要使用test开头(也可以通过参数pattern指定查找用例模块的规则,如:pattern='test*.py')

suite.addTest(load.discover('testcases'))
  • 1

又或者,

suite.addTest(load.discover(r'C:\project\py\testcases',pattern='hg_*',top_level_dir=r'C:\project\py\testcases'))
  • 1

top_level_dir最好不要传值,挺复杂的

总结:以上三个步骤可以简写为一行(实际使用):

suite = unittest.TestLoader().discover('testcases')
  • 1

也可以是:

suite = unittest.defaultTestLoader.discover('testcases')
  • 1

discover传参的四种写法:
(1)绝对路径下文件夹内多个文件:discover(r'C:\project\py\testcases')
(2)相对路径下文件夹内多个文件:discover('testcases')
(3)绝对路径下的文件:discover(r'C:\project\py\testcases', 'test_8.py')
(4)相对路径下的文件:discover('testcases', 'test_8.py')

六、测试运行程序:unittest.TextTestRunner

1、加载测试用例到测试套件

suite = unittest.defaultTestLoader.discover(r'C:\project\py\testcases')
  • 1

2、创建一个测试运行程序

runner = unittest.TextTestRunner()
runner.run(suite)
  • 1
  • 2

runner = unittest.TextTestRunner(verbosity=2)中verbosity可传参为0、1、2;
为0时什么也没有,为1时如下图1,为2时如下图2,为其他时和为2时一致,默认传参为1:
图1:
unittest-图1
图2:
unittest-图2
3、文本格式的测试报告生产(unittest自带的文本测试报告)

# 就是把控制台的输出存到了report.txt
with open('report.txt','w',encoding='utf-8') as f:
    runner = unittest.TextTestRunner(stream=f)
    runner.run(suite)
  • 1
  • 2
  • 3
  • 4

七、使用第三方的扩展库来生成测试报告:BeautifulReport

from BeautifulReport import BeautifulReport

suite = unittest.defaultTestLoader.discover(r'testcases','test_demo03.py')
br = BeautifulReport(suite)
br.report(description='漂亮报告', filename='report.html', report_dir='./reports')
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述
界面显示的用例描述,取自于每一个测试用例所对应的函数的文档字符串注释,如下图3、图4所示:
图3:
在这里插入图片描述
图4:
在这里插入图片描述

八、测试夹具(测试用例的前后置方法):setUpClass、tearDownClass、setUp、tearDown

1、setUpClass:测试类级别的前置方法,每个测试类中的用例全部开始执行之前会执行(只会执行一次)
2、tearDownClass:测试类级别的后置方法,每个测试类中的用例全部执行完成之后会执行(只会执行一次)
3、setUp:用例级别的前置方法,每条用例开始执行之前都会执行
4、tearDown:用例级别的后置方法,每条用例执行完成之后都会执行

import unittest

class TestDome5(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        print('---setUpClass------')
    @classmethod
    def tearDownClass(cls) -> None:
        print('---tearDownClass------')
        
    def setUp(self) -> None:
        print('---setUp------')
    def tearDown(self) -> None:
        print('---tearDown------')
        
    def test_01(self):
        print('------------test--01---------------')
    def test_02(self):
        print('------------test--02---------------')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

运行结果:
在这里插入图片描述

九、数据驱动测试:DDT

DDT:Data Driver Test:数据驱动测试

ddt使用的步骤:
1、from ddt import ddt, data
2、在测试类上面使用@ddt (@是装饰器的语法)
3、在测试用例方法上面@data,并传入测试数据
4、ddt会根据data中传递的参数,来生成用例(每个参数生成一条测试用例)
5、在测试方法中定义个参数来接收data中传递过来的用例数据

import unittest
from ddt import ddt, data

@ddt
class TestDemo(unittest.TestCase):
	
	# *[1,2,3,4,5,6]为列表拆包
    @data(*[1,2,3,4,5,6])
    def test_login(self, item):
        print(item)
        
if __name__ == '__main__':
    unittest.main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/759324
推荐阅读
相关标签
  

闽ICP备14008679号