当前位置: 首页 > article >正文

Python-UnitTest框架

一、UnitTest基本介绍

1、是什么?

UnitTest是python自带的专门用于单元测试的。一般单元测试是开发做的。(框架:解决一类事情的功能集合)

自带的框架:不需要额外安装,只要安装了python就可以使用 第三方框架:想要使用,需要先安装后使用(pytest)

对于测试来说,使用unittest框架来管理运行多个测试用例的。

2、作用
  • 能够组织多个用例去执行
  • 提供丰富的断言方法(让程序代码代替人工自动判断预期结果和实际结果是否相符合
  • 能够生成测试报告
3、核心要素(组成)
  • TestCase(最核心的模块)

    TestCase(测试用例),注意这个测试用例是unittest框架的组成部分,不是手工和自动化中我们所说的用例(Test Case) 主要作用: 每个 TestCase(测试用例)都是一个代码文件,在这个代码文件中,来书写真正的用例代码
    
  • TestSuite(测试套件)

    TestSuite(测试套件),用来管理 组装(打包)多个TestCase(测试用例)的。也是一个代码文件
  • TestRunner(测试执行)

    TestRunner(测试执行、测试运行),用来执行TestSuite(测试套件)的
  • TestLoader(测试加载)

    TestLoader(测试加载),功能是对TestSuite(测试套件)功能的补充
  • Fixture(测试夹具)

    Fixture(测试夹具),书写在TestCase(测试用例)代码中,是一种代码结构,在每个方法执行前后都会执行的内容 例如:登录的测试用例(把相同且重复的内容放到TestCase中,只写一遍,但每次用例方法的执行,都会自动执行Fixture中的代码) 1.打开浏览器 2.输入网址

二、TestCase(测试用例)

  1. 是一个代码文件,在代码文件中,用来书写真正的用例代码。
  2. 代码文件的名字必须按照标识符的规则来书写,可以将代码的作用在文件的开头使用注释说明
  3. 步骤:
  • ① 导包(unittest) ——import unittest

  • ② 自定义测试类

    class 类名(unittest.TestCase): pass
    
  • ③ 在测试类中书写测试方法

    def test_方法名(self): 用例的代码
  • ④ 执行用例

示例

''' 代码的目的:学习TestCase(测试用例)模块的书写方法 ''' # 1. 导包 import unittest # 2.自定义测试类,需要继承unittest模块中的TestCase类 class TestDemo(unittest.TestCase): # 3.书写测试方法,即 用例代码,目前没有真正的用例代码,使用print代替 # 书写要求,测试方法必须以test_ 开头(本质是以test开头) def test_method1(self): print("测试方法1") def test_method2(self): print("测试方法2") # 4.执行用例(方法) # 4.1 将光标放到类名后面,会执行类里所有方法 # 4.2 放到方法名后面,只执行当前的方法```

  1. 代码书写常见错误:
  • 代码文件命名不规范
  • 代码运行没结果(右键运行没有unittests for 的提示)
  • 没有找到用例(测试方法中不是以test_开头的,或者单词写错了)

三、TestSuite和TestRunner的书写

TestSuite管理、打包、组装TestCase文件

TestRunner执行TestSuite (套件)
步骤:

  • ① 导包(unittest)

  • ② 实例化(创建对象)套件对象

    suite = unittest.TestSuite()
    
  • ③ 使用套件对象添加用例方法

    suite.addTest(unittest.makeSuite(测试类名))或 suite.addTest(测试类名('方法名'))
    
  • ④ 实例化运行对象

    runner= unittest.TextTestRunner()
    
  • ⑤ 使用运行对象去执行套件对象

    runner.run(suite)
    

示例

''' 学习TestSuite和TestRunner的使用 ''' # 1.导包(unittest) import unittest # 2.实例化(创建对象)套件对象 from testCase1 import TestDemo1 from testCase2 import TestDemo2 suite = unittest.TestSuite() # 3.使用套件对象添加用例方法 #方式一,套件对象.addTest(测试类名(‘方法名’))#建议测试类名和方法名直接去复制,不要手写 suite.addTest(TestDemo1('test_method1')) suite.addTest(TestDemo1('test_method2')) suite.addTest(TestDemo2('test_method1')) suite.addTest(TestDemo2('test_method2')) #方式二,将一个测试类中的所有方法进行添加, #套件对象.addTest(unittest.makeSuite(测试类名)) #缺点:makeSuite()不会提示 suite.addTest(unittest.makeSuite(TestDemo1)) suite.addTest(unittest.makeSuite(TestDemo2)) # 4.实例化运行对象 runner = unittest.TextTestRunner() # 5.使用运行对象去执行套件对象 #运行对象.run(套件对象) runner.run(suite)

运行结果注意:

练习

 
  1. #test.py

  2. #1.导包

  3. import unittest

  4. from tools import add

  5. #2. 自定义测试类

  6. class TestAdd(unittest.TestCase):

  7. # 3. 书写测试方法,就是测试用例

  8. def test_method1(self):

  9. #1,2,3

  10. if add(1,2) == 3:

  11. print("测试通过")

  12. else:

  13. print("测试不通过")

  14. def test_method2(self):

  15. if add(10, 20) == 20:

  16. print("测试通过")

  17. else:

  18. print("测试不通过")

#案例练习 #1.导包 import unittest # 2.实例化(创建对象)套件对象 from test import TestAdd suite=unittest.TestSuite() # 3.使用套件对象添加用例方法 suite.addTest(unittest.makeSuite(TestAdd)) # 4.实例化运行对象 runner = unittest.TextTestRunner() # 5.使用运行对象去执行套件对象 runner.run(suite)

四、TestLoader(测试加载)

作用和TestSuite的作用一样,对TestSuite功能的补充,用来组装测试用例的。比如:如果TestCase的代码文件有很多。

步骤

  • 1.导包

  • 2.实例化测试加载对象并添加用例——>得到的是suite对象

    suite = unittest.TestLoader().discover('用例所在的路径',‘用例的代码文件名’)
    
  • 3.实例化 运行对象

  • 4.运行对象执行套件对象

#1.导包 import unittest #2.实例化加载对象并添加用例 #第一种: unittest.TestLoader().discover('用例所在的路径',‘用例的代码文件名’) # 用例所在的路径,建议使用相对路径,用例的代码文件名可以使用* (任意多个任意字符)通配符 # suite=unittest.TestLoader().discover('./case','test*.py') suite=unittest.TestLoader().discover('./case','*case*.py') #第二种:使用默认的加载对象并加载用例,防止忘记加TestLoader()的括号 suite=unittest.defaultTestLoader.discover('case','*case*') #3. 实例化运行对象 runner= unittest.TextTestRunner() #4.执行 runner.run(suite) #将3,4步合并 # unittest.TextTestRunner().run(suite)

五、Fixture(测试夹具)

是一种代码结构,在某些特定的情况下,会自动执行。 (方法级别和类级别前后的方法,不需要同时出现,根据用例代码的需要自行的选择使用)

1. 方法级别(掌握)

每个测试方法(用例代码)执行前后都会自动调用结构。

#方法执行之前 def setUp(self): 每个测试方法执行之前都会执行 pass #方法执行之后 def tearDown(self): 每个测试方法执行之前都会执行 pass

2.类级别(掌握)

每个测试类中所有方法执行前后都会自动调用结构,在整个类中执行之前执行之后使用一次。

#类级别的Fixture方法,是一个类方法 #类中所有方法之前 @classmethode def setUpClass(cls): pass #类中所有方法之后 @classmethod def tearDownClass(cls): pass

3.模块级别

每个模块(代码文件)执行前后执行的代码结构。

#模块级别的需要写在类的外边直接定义函数即可 #代码文件之前 def setUpModule(): pass #代码文件之后 def tearDownModule(): pass

案例:

  • 1.打开浏览器(整个测试过程中就打开一次浏览器)——>类级别
  • 2.输入网址(每个测试方法都要一次)——>方法级别
  • 3.输入用户名、密码和验证码点击登录(不同的测试数据)——>测试方法
  • 4.关闭当前页面(每个测试方法都需要一次) ——>方法级别
  • 5.关闭浏览器(整个测试过程中就关闭一次浏览器)——>类级别

import unittest def login(username,password): if username == 'admin' and password == '123456': return '登录成功' else: return '登录失败' class TestLogin(unittest.TestCase): def setUp(self) -> None: print('输入网址') def tearDown(self) -> None: print('关闭当前页面') @classmethod def setUpClass(cls) -> None: print('1.打开浏览器') @classmethod def tearDownClass(cls) -> None: print('5.关闭浏览器') def test_username_password_ok(self): self.assertEqual(login('admin','123456') ,'登录成功') if login('admin','123456') == '登录成功': print('pass') else: print('fail') def test_username_error(self): self.assertEqual(login('root', '123456'), '登录失败') self.assertIn('失败',login('root', '123456')) if login('root', '123456') == '登录失败': print('pass') else: print('fail')

六、断言

让程序代替人为判读测试程序执行结果是否符合预期结果的过程

优点

  • 1.提高测试效率
  • 2.实现自动化测试(让脚本在无人值守的状态下运行)

结果

  • true,用例通过
  • false,代码抛出异常,用例不通过

常用的UnitTest断言方法

 
  1. self.assertEqual(预期结果,实际结果)#判断预期结果是实际结果是否相等。

  2. 1.如果相等,用例通过

  3. 2.如果不等,用例不通过,抛出异常

  4. self.assertIn(预期结果,实际结果)#判断预期结果是否包含在实际结果中

  5. 1.包含,用例通过

  6. 2.不包含,用例不通过,抛出异常

注意:在unittest中使用断言,都需要通过self.断言方法 来调用!

def test_username_password_ok(self): self.assertEqual(login('admin','123456') ,'登录成功') if login('admin','123456') == '登录成功': print('pass') else: print('fail') def test_username_error(self): self.assertEqual(login('root', '123456'), '登录失败') self.assertIn('失败',login('root', '123456')) if login('root', '123456') == '登录失败': print('pass') else: print('fail')

七、参数化

在测试方法中,使用变量来替代具体的测试数据,然后使用传参的方法将测试数据传递给方法的变量。

好处:相似的代码不需要多次书写

工作中场景

  • 1、测试数据一般放在json文件中
  • 2、使用代码读取json文件,提取我们想要的数据——>[( ),( )]或[ [ ],[ ] ]

安装插件

  • unittest框架本身是不支持参数化,想要使用参数化,需要安装插件来完成。

  • 联网安装

    pip install parameterized
  • 验证

    pip list #查看到 parameterized from parameterized import pa...
    

步骤

  • 1.导包:unittest/pa...
  • 2.定义测试类
  • 3.书写测试方法(用到的测试数据使用变量代替)
  • 4.组织测试数据并传参(使用装饰器@parameterized.expand(data))

# 1.导包 # unittest/pa... import unittest from parameterized import parameterized from fixture import login import json #组织测试数据[(),(),()]or[[],[],[]] def build_data(): data = [] with open('data.json',encoding='utf-8') as f: result=json.load(f)#[{},{},{}] for i in result: data.append((i['username'],i['password'],i['expect'])) return data # data =[ # ('admin','123456','登录成功'), # ('admin','123','登录失败'), # ('root','123456','登录失败') # ] # 2.定义测试类 class TestLogin(unittest.TestCase): # 3. 书写测试方法(用到的测试数据使用变量代替) @parameterized.expand(build_data())# 4.组织测试数据并传参(装饰器 @) def test_login(self,username,password,expect): self.assertEqual(expect,login(username,password))

八、跳过

对于一些未完成的或者不满足测试条件测试函数和测试类,不想执行,可以使用跳过(使用装饰器完成)代码书写在TestCase里面

#直接将测试函数标记成跳过 @unittest.skip('跳过原因') #根据条件判断测试函数是否跳过,判断条件成立,跳过 @unittest.skipIf(判断条件,'跳过原因')

示例

import unittest version = 30 class TestDemo(unittest.TestCase): @unittest.skip('没什么原因,就是想跳过') def test_1(self): print("测试方法 1") @unittest.skipIf(version >=30,'如果版本号大于等于30就跳过') def test_2(self): print("测试方法 2") def test_3(self): print("测试方法 3")

九、测试报告

  • 自带的测试报告:只有单独运行TestCase的代码,才会生成测试报告

  • 生成第三方的测试报告HTMLTestRunner):
  1. 获取第三方的 测试运行类模块,将其放在代码的目录中

  2. 导包unittest

  3. 使用 套件对象,加载对象 去添加用例方法

  4. 实例化第三方的运行对象 并运行 套件对象

 
  1. HTMLTestRunner(参数)

  2. #stream=sys.stdout,必填,测试报告的文件对象(open),注意,是二进制文件需要用wb打开

  3. #verbosity=1,可选,报告的详细程度,默认1简略,2详细

  4. #title=none,可选,测试报告的标题

  5. #description=none,可选,描述信息,python的版本,pycharm版本

示例

# 1.获取第三方的 测试运行类模块,将其放在代码的目录中 from HTMLTestRunner import HTMLTestRunner # 2. 导包unittest import unittest # 3.使用 套件对象,加载对象 去添加用例方法 suite = unittest.defaultTestLoader.discover('.','para*.py')#加载对象 # 4.实例化第三方的运行对象 并运行 套件对象 file= "E:\test\Unittest\report1.html" with open(file,'wb') as f: runner = HTMLTestRunner(f,2,'测试报告','python 3.8') runner.run(suite)

查看测试报告

流程总结

1、组织用例文件(TestCase里边)书写参数化,书写断言,书写Fixture,书写 跳过如果是单个测试文件,直接运行,得到测试报告如果有多个测试文件,需要组织运行生成测试报告

2、使用 套件对象(TextSuite)组装,或者使用加载对象(TextLoader)组装

3、运行对象(TestRunner) 运行

1.运行对象 = 第三方的运行类(文件对象:使用wb方式打开) 2.运行对象.run(套件对象)


http://www.kler.cn/a/320662.html

相关文章:

  • python语言基础-5 进阶语法-5.2 装饰器-5.2.2 简单装饰器
  • 使用 Python 和 Py2Neo 构建 Neo4j 管理脚本
  • PySpark——Python与大数据
  • 基于Java Springboot编程语言在线学习平台
  • 【第五课】Rust所有权系统(一)
  • 蓝牙 HFP 协议详解及 Android 实现
  • 基于springboot的驾校预约管理系统的设计与实现 (含源码+sql+视频导入教程)
  • 【Django5】django的helloworld
  • Hqst 品牌 H81801D 千兆 DIP 网络变压器在光猫收发器机顶盒中的应用
  • 前端——flex布局
  • 全方位洗衣洗鞋小程序系统,重塑干洗店服务新体验;
  • LeetCode 22. 括号生成
  • Vue3使用vue-quill富文本编辑器实现图片大小调整
  • 简单了解Redis(初识阶段)
  • 【STM32】 TCP/IP通信协议(1)
  • 【JavaWeb】二、HTML 入门
  • js-17-对数组、对象进行浅拷贝和深拷贝
  • 四款负载均衡工具Nginx、HAProxy、MetalLB、gobetween 比较
  • 【ARM 嵌入式 编译系列 2.8 -- GCC 编译优化参数 位置无关码】
  • Chat2VIS: Generating Data Visualizations via Natural Language
  • 【Android】BottomSheet基本用法总结(BottomSheetDialog,BottomSheetDialogFragment)
  • Unity中的GUIStyle错误:SerializedObject of SerializedProperty has been Disposed.
  • 隧道面稳定性分析MATLAB
  • 立志最细,在FreeRtos中数据传输方式及应用!!!
  • PostgreSQL 创建表,常规表、外部表、分区表区别讲解
  • 华为HarmonyOS灵活高效的消息推送服务(Push Kit) - 1 简介