• UnitTest框架
    • 1. 介绍
    • 2. TestCase(测试用例)
      • 1. 问题1:代码文件的命名不规范
      • 问题 2:代码运行没有结果
      • 问题 3 没有找到用例
    • 3. TestSuite & TestRunner
      • 练习
    • 4. TestLoader (测试加载)
    • 5. Fixture(测试夹具)
      • 1. 方法级别[掌握]
      • 2. 类级别[掌握]
      • 3. 模块级别[了解]
      • 4. 案例
    • 6. 断言
      • 1. assertEqual
      • 2. assertIn
    • 7. 参数化
      • 1. 安装插件
      • 2. 参数化代码
      • 3. 参数化 - json文件
    • 8. 跳过
    • 9. 测试报告
      • 1. 自带的测试报告
      • 2. 生成第三方的测试报告
      • 3. 测试流程
      • 4. 中文测试报告

UnitTest框架

1. 介绍

  • 框架

    说明:
    1. 框架英文单词framework 2. 为解决一类事情的功能集合> 需要按照框架的规定(套路) 去书写代码
    
  • 什么是UnitTest框架?

    概念:UnitTest是Python自带的一个单元测试框架,用它来做单元测试。
    ----
    自带的框架(官方): 不需要单外安装, 只要安装了 Python,就可以使用
    random, json, os, time
    第三方框架: 想要使用 需要先安装后使用(pytest)
    selenium , appium, requests ----
    单元测试框架: 主要用来做单元测试, 一般单元测试是开发做的.
    对于测试来说, unittest 框架的作用是 自动化脚本(用例代码) 执行框架(使用 unittest 框架 来 管理 运行 多个测试用例的)
    
  • 为什么使用UnitTest框架?

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

    1. TestCase(最核心的模块)

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

      TestSuite(测试套件), 用来 管理 组装(打包)多个 TestCase(测试用例) 的
      
    3. TestRunner

      TestRunner(测试执行,测试运行),  用来 执行 TestSuite(测试套件)的
      
    4. TestLoader

      TestLoader(测试加载), 功能是对 TestSuite(测试套件) 功能的补充,
      管理 组装(打包)多个 TestCase(测试用例) 的
      
    5. Fixture

      Fixture(测试夹具), 书写在 TestCase(测试用例) 代码中, 是一个代码结构, 可以在每个方法执行前后都会执行的内容举例:
      登录的测试用例, 每个用例中重复的代码就可以写在 Fixture 代码结构中, 只写一遍, 但每次用例方法的执行,都会执行 Fixture 中的代码
      1. 打开浏览器
      2. 输入网址

2. TestCase(测试用例)

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

    1. 导包 (unittest)
    2. 自定义测试类
    3. 在测试类中书写测试方法
    4. 执行用例
    
  • 代码

    """
    代码的目的: 学习 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. 问题1:代码文件的命名不规范

1. 代码文件的名字以数字开头
2. 代码文件名字中有空格
3. 代码文件名字有中文
4. 其他的特殊符号
(数字, 字母, 下划线组成, 不能以数字开头)

问题 2:代码运行没有结果

右
键运行没有 unittests for 的提示, 出现的问题
解决方案:
方案1. 重新新建一个代码文件, 将写好的代码复制进去
方案2. 删除已有的运行方式

问题 3 没有找到用例

测试方法中不是以 test_ 开头的, 或者单词写错了

3. TestSuite & TestRunner

TestSuite(测试套件): 管理 打包 组装 TestCase(测试用例) 文件的
TestRunner(测试执行): 执行 TestSuite(套件)
  • 步骤

    1. 导包(unittest)
    2. 实例化(创建对象)套件对象
    3. 使用套件对象添加用例方法
    4. 实例化运行对象
    5. 使用运行对象去执行套件对象
    
  • 代码

    TestSuite(测试套件): 是用来管理多个 TestCase(测试用例) 的,
    先创建多个 TestCase(测试用例) 文件
    
    """
    学习 TestSuite 和 TestRunner 的使用
    """
    # 1. 导包(unittest)
    import unittest
    from hm_07_testcase1 import TestDemo1
    from hm_07_testcase2 import TestDemo2# 2. 实例化(创建对象)套件对象,
    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'))# 4. 实例化运行对象
    runner = unittest.TextTestRunner()
    # 5. 使用运行对象去执行套件对象
    # 运行对象.run(套件对象)
    runner.run(suite)
    """
    学习 TestSuite 和 TestRunner 的使用
    """
    # 1. 导包(unittest)
    import unittest
    # 2. 实例化(创建对象)套件对象,
    from hm_07_testcase1 import TestDemo1
    from hm_07_testcase2 import TestDemo2suite = unittest.TestSuite()
    # 3. 使用套件对象添加用例方法
    # 方式二 将一个测试类中的所有方法进行添加
    # 套件对象.addTest(unittest.makeSuite(测试类名))
    # 缺点: makeSuite()  不会提示
    suite.addTest(unittest.makeSuite(TestDemo1))
    suite.addTest(unittest.makeSuite(TestDemo2))# 4. 实例化运行对象
    runner = unittest.TextTestRunner()
    # 5. 使用运行对象去执行套件对象
    # 运行对象.run(套件对象)
    runner.run(suite)

练习

1. 在 tools 模块中定义 add 函数, 对两个数字进行求和计算
2. 书写 TestCase 代码对 add() 进行测试
用例 1:  1, 2, 3
用例 2:  10, 20, 30
用例 3:  2, 3, 5
  • 用例代码
"""案例练习"""
# 1,导包
import unittest
from tools import add# 2, 自定义测试类class TestAdd(unittest.TestCase):# 3. 书写测试方法, 就是测试用例代码def test_method1(self):# 1, 2, 3 判断实际结果和预期结果是否相符if add(1, 2) == 3:print('测试通过')else:print('测试不通过')def test_method2(self):if add(10, 20) == 30:print('测试通过')else:print('测试不通过')def test_method3(self):# 1, 2, 3 判断实际结果和预期结果是否相符if add(2, 3) == 5:print('测试通过')else:print('测试不通过')
  • 套件和执行的代码
import unittest# 实例化套件对象
from hm_08_test import TestAddsuite = unittest.TestSuite()
# 添加测试方法
suite.addTest(unittest.makeSuite(TestAdd))
# 实例化执行对象
runner = unittest.TextTestRunner()
runner.run(suite)

4. TestLoader (测试加载)

TestLoader (测试加载), 作用和 TestSuite 的作用是一样的, 对 TestSuite 功能的补充,
用来组装测试用例的比如: 如果 TestCase 的代码文件有很多, (10 20, 30 )
- 使用步骤
1. 导包
2. 实例化测试加载对象并添加用例   ---> 得到的是 suite 对象
3. 实例化 运行对象
4. 运行对象执行套件对象
  • 代码实现
在一个项目中 TestCase(测试用例) 的代码,一般放在一个单独的目录 (case)
"""TestLoader 的使用"""
# 1, 导包
import unittest# 2, 实例化加载对象并添加用例
# unittest.TestLoader().discover('用例所在的路径', '用例的代码文件名')
# 用例所在的路径,建议使用相对路径, 用例的代码文件名可以使用 *(任意多个任意字符) 通配符
# suite = unittest.TestLoader().discover('./case', 'hm*.py')
# suite = unittest.TestLoader().discover('./case', '*test*.py')
# suite = unittest.TestLoader().discover('./case', '*test*')
suite = unittest.TestLoader().discover('./case', '*case1.py')# 3, 实例化运行对象
# runner = unittest.TextTestRunner()
# # 4, 执行
# runner.run(suite)# 可以将 3 4 步 变为一步
unittest.TextTestRunner().run(suite)
# 1. 导包
# 2. 使用默认的加载对象并加载用例
# 3. 实例化运行对象并运行"""TestLoader 的使用"""
# 1, 导包
import unittest# 2, 使用默认的加载对象并加载用例
suite = unittest.defaultTestLoader.discover('case', 'hm_*.py')# 可以将 3 4 步 变为一步
unittest.TextTestRunner().run(suite)

5. Fixture(测试夹具)

Fixture(测试夹具) 是一种代码结构在某些特定的情况下 会自动执行

1. 方法级别[掌握]

在每个测试方法(用例代码) 执行前后都会自动调用的结构
# 方法执行之前
def setUp(self):每个测试方法执行之前都会执行pass# 方法执行之后
def tearDown(self):每个测试方法执行之后都会执行pass

2. 类级别[掌握]

在每个测试类中所有方法执行前后 都会自动调用的结构(在整个类中 执行之前执行之后个一次)
# 类级别的Fixture 方法, 是一个 类方法
# 类中所有方法之前
@classmethod
def setUpClass(cls):pass# 类中所有方法之后
@classmethod
def tearDownClass(cls):pass

3. 模块级别[了解]

模块: 代码文件
在每个代码文件执行前后执行的代码结构
# 模块级别的需要写在类的外边直接定义函数即可
# 代码文件之前
def setUpModule():pass# 代码文件之后
def tearDownModule():pass
方法级别和类级别的 前后的方法,不需要同时出现,根据用例代码的需要自行的选择使用

4. 案例

1. 打开浏览器(整个测试过程中就打开一次浏览器)  类级别
2. 输入网址(每个测试方法都需要一次)  方法级别
3. 输入用户名密码验证码点击登录(不同的测试数据) 测试方法
4. 关闭当前页面(每个测试方法都需要一次)  方法级别
5. 关闭浏览器(整个测试过程中就关闭一次浏览器) 类级别
------
1. 打开浏览器(整个测试过程中就打开一次浏览器)  类级别
2. 输入网址(每个测试方法都需要一次)  方法级别
3. 输入用户名密码验证码点击登录(不同的测试数据) 测试方法
4. 关闭当前页面(每个测试方法都需要一次)  方法级别
2. 输入网址(每个测试方法都需要一次)  方法级别
3. 输入用户名密码验证码点击登录(不同的测试数据) 测试方法
4. 关闭当前页面(每个测试方法都需要一次)  方法级别
2. 输入网址(每个测试方法都需要一次)  方法级别
3. 输入用户名密码验证码点击登录(不同的测试数据) 测试方法
4. 关闭当前页面(每个测试方法都需要一次)  方法级别
5. 关闭浏览器(整个测试过程中就关闭一次浏览器) 类级别
import unittestclass TestLogin(unittest.TestCase):def setUp(self):"""每个测试方法执行之前都会先调用的方法"""print('输入网址......')def tearDown(self) -> None:"""每个测试方法执行之后都会调用的方法"""print('关闭当前页面......')@classmethoddef setUpClass(cls) -> None:print('------1. 打开浏览器')@classmethoddef tearDownClass(cls) -> None:print('------5. 关闭浏览器')def test_1(self):print('输入正确用户名密码验证码,点击登录 1')def test_2(self):print('输入错误用户名密码验证码,点击登录 2')

6. 断言

让程序代替人工自动的判断预期结果和实际结果是否相符.断言的结果有两种:
> True, 用例通过
> False, 代码抛出异常, 用例不通过在 unittest 中使用断言, 都需要通过 self.断言方法  来试验

1. assertEqual

self.assertEqual(预期结果, 实际结果)   # 判断预期结果和实际结果是否相等
1. 如果相等, 用例通过
2. 如果不相等,用例不通过, 抛出异常

2. assertIn

self.assertIn(预期结果, 实际结果)   # 判断预期结果是否包含在实际结果中
1. 包含 ,用例通过
2. 不包含, 用例不通过, 抛出异常assertIn('admin', 'admin')   # 包含
assertIn('admin', 'adminnnnnnnn')   # 包含
assertIn('admin', 'aaaaaadmin')   # 包含
assertIn('admin', 'aaaaaadminnnnnnn')   # 包含
assertIn('admin', 'addddddmin')   # 不是包含
import unittestfrom tools import loginclass TestLogin(unittest.TestCase):def test_username_password_ok(self):"""正确的用户名和密码: admin, 123456, 登录成功"""self.assertEqual('登录成功', login('admin', '123456'))def test_username_error(self):"""错误的用户名: root, 123456, 登录失败"""self.assertEqual('登录失败', login('root', '123456'))def test_password_error(self):"""错误的密码: admin, 123123, 登录失败"""self.assertEqual('登录失败', login('admin', '123123'))def test_username_password_error(self):"""错误的用户名和错误的密码: aaa, 123123, 登录失败"""# self.assertEqual('登录失败', login('aaa', '123123'))self.assertIn('失败', login('aaa', '123123'))

7. 参数化

参数化 在测试方法中, 使用 变量 来代替具体的测试数据, 然后使用传参的方法将测试数据传递给方法的变量
好处: 相似的代码不需要多次书写.工作中场景:
1. 测试数据一般放在 json 文件中
2. 使用代码读取 json 文件,提取我们想要的数据 ---> [(), ()] or [[], []]

1. 安装插件

unittest 框架本身是不支持 参数化, 想要使用参数化,需要安装插件来完成- 联网安装(在 cmd 窗口安装 或者 )pip install parameterized------
pip 是 Python 中包(插件) 的管理工具, 使用这个工具下载安装插件
  • 验证
pip list  # 查看到  parameterized新建一个 python 代码文件, 导包验证
from pa... import pa...

2. 参数化代码

1. 导包 unittest/ pa rameterized
2. 定义测试类
3. 书写测试方法(用到的测试数据使用变量代替)
4. 组织测试数据并传参

3. 参数化 - json文件

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

8. 跳过

对于一些未完成的或者不满足测试条件的测试函数和测试类, 不想执行,可以使用跳过
使用方法, 装饰器完成
代码书写在 TestCase 文件
# 直接将测试函数标记成跳过
@unittest.skip('跳过额原因')
# 根据条件判断测试函数是否跳过 , 判断条件成立, 跳过
@unittest.skipIf(判断条件, '跳过原因')
import unittest# version = 30
version = 29class 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')

9. 测试报告

1. 自带的测试报告

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

2. 生成第三方的测试报告

1. 获取第三方的 测试运行类模块 , 将其放在代码的目录中
2. 导包 unittest
3. 使用  套件对象, 加载对象 去添加用例方法
4. 实例化 第三方的运行对象 并运行 套件对象
# 1. 获取第三方的 测试运行类模块 , 将其放在代码的目录中
# 2. 导包 unittest
import unittest
from HTMLTestRunner import HTMLTestRunner# 3. 使用  套件对象, 加载对象 去添加用例方法
suite = unittest.defaultTestLoader.discover('.', 'hm_05_pa1.py')
# 4. 实例化 第三方的运行对象 并运行 套件对象
# HTMLTestRunner()
# stream=sys.stdout, 必填,测试报告的文件对象(open ), 注意点,要使用 wb 打开
# verbosity=1, 可选, 报告的详细程度,默认 1 简略, 2 详细
# title=None, 可选, 测试报告的标题
# description=None 可选, 描述信息, Python 的版本, pycharm 版本# file = 'report.html'   # 报告的后缀是.html
file = 'report1.html'   # 报告的后缀是.html
with open(file, 'wb') as f:# runner = HTMLTestRunner(f)  # 运行对象runner = HTMLTestRunner(f, 2, '测试报告', 'python 3.6.8 ')  # 运行对象# 运行对象执行套件, 要写在 with 的缩进中runner.run(suite)

3. 测试流程

1. 组织用例文件(TestCase 里边), 书写参数化, 书写断言, 书写 Fixture, 书写 跳过, 如果单个测试测试文件, 直接运行, 得到测试报告, 如果有多个测试文件, 需要组装运行生成测试报告2. 使用 套件对象组装, 或者使用 加载对象组装3. 运行对象 运行
3.1 运行对象 = 第三方的运行类(文件对象(打开文件需要使用 wb 方式))
3.2 运行对象.run(套件对象)

4. 中文测试报告

import unittest
from HTMLTestRunnerCN import HTMLTestReportCN# 组装用例方法
suite = unittest.defaultTestLoader.discover('.', '*pa1.py')# 实例化运行对象
with open('report_cn.html', 'wb') as f:runner = HTMLTestReportCN(f)runner.run(suite)

【博学谷学习记录】超强总结,用心分享 | 软件测试 UnitTest框架相关推荐

  1. [博学谷学习记录]超强总结,用心分享|第07节 常用的API-----笔记篇

    目录 1.API 1.1 API概述-帮助文档的使用 1.2 键盘录入字符串 2. String类 2.1 String概述 2.2 String类的构造方法 2.4 创建字符串对象的区别对比 2.5 ...

  2. {博学谷学习记录} 超强总结,用心分享|狂野架构师-前置互联网架构演变过程

    本章以系统架构,数据架构,两种维度来进行讲解 目录 1 系统架构 1,1 单体架构 1.2 中台战略 2 数据库架构 2,1 单体架构 2.2 主从读写 2.3 分库分表 3 总结 1 系统架构 1, ...

  3. [博学谷学习记录]超强总结,用心分享|架构 Nacos入门

    提示:学习笔记 欢迎指点 文章目录 前言 一.Nacos安装 二.Nacos服务注册与发现 1.服务提供者Provider 2.服务消费者Consumer 三.Nacos作为配置中心 前言 Nacos ...

  4. [博学谷学习记录]超强总结,用心分享|架构 敏捷 - 开发管理之道

    提示:学习笔记 欢迎指点 文章目录 1.敏捷开发思想之道 2.面向对象开发之道 3.敏捷学习之道 1.敏捷开发思想之道 一名敏捷开发者,敏捷思想的掌握自然首当其冲.在敏捷开发实施的过程中,我们虽然不是 ...

  5. [博学谷学习记录]超强总结,用心分享|第16节 集合续-----笔记篇

    目录 1.HashSet集合 1.1HashSet集合概述和特点[应用] 1.2HashSet集合的基本应用[应用] 1.3哈希值[理解] 1.4哈希表结构[理解] 1.5HashSet集合存储学生对 ...

  6. [博学谷学习记录] 超强总结,用心分享|陌陌综合案例

    注:大家觉得博客好的话,别忘了点赞收藏呀,本人每周都会更新关于人工智能和大数据相关的内容,内容多为原创,Python Java Scala SQL 代码,CV NLP 推荐系统等,Spark Flin ...

  7. [博学谷学习记录]超强总结,用心分享|Hive的压缩格式

    压缩格式 工具 算法 文件扩展名 是否可切分 DEFAULT 无 DEFAULT .deflate 否 Gzip gzip DEFAULT .gz 否 bzip2 bzip2 bzip2 .bz2 是 ...

  8. [博学谷学习记录]超强总结,用心分享|软件测试之计算机基础(一)

    本周开始学习软件测试,而我也即将开始在平台记录我的学习之路.我会把我的个人心得及掌握的知识发布在此平台,俗话说最好的输入就是输出,希望在输出的同时能有更多的收获,也希望与大家多多交流. 为了更好的学习 ...

  9. [博学谷学习记录]超强总结,用心分享|人工智能机械学习基础知识线性回归总结分享

    1.线性回归的核心是参数学习,线性回归和回归方程(函数)有关 2.线性回归是目标值预期是输入变量的线性组合 3.欠拟合的产生原因是学习到数据的特征过少 4.多元线性回归中的"线性" ...

最新文章

  1. 阿里云 redis 公网连接
  2. BZOJ 2806 Luogu P4022 [CTSC2012]Cheat (广义后缀自动机、DP、二分、单调队列)
  3. java查找最小字符集_如何查找Java中的默认字符集/编码?
  4. win11任务栏怎么隐藏 Windows11隐藏任务栏的设置方法
  5. jar包可以到maven下载
  6. 最短路 Codeforces Round #103 (Div. 2) D. Missile Silos
  7. 如何在水晶报表9中实现选择打印机打印?
  8. php开发问题-class_exists
  9. Ozone SCM HA设计浅谈
  10. IEEE期刊论文模板的查找,下载方法--
  11. mescroll API 汇总
  12. WebView文件下载
  13. 软件开发工程师证书有用吗_关于软件工程师职业证书你知道多少?
  14. 主要几个浏览器的内核是什么
  15. 第16章Stata面板数据分析
  16. Anaconda3 下载安装与Labelme下载安装
  17. 微软云强劲增长的背后,是全新的人工智能黑科技
  18. 操作系统 图形窗口 子系统
  19. mtk6592 android 5,八核vs四核:MTK MT6592运行《现代战争5》画面对比
  20. 咱一起来刷一刷leetCode的题吧

热门文章

  1. Mac OS X的火狐上安装Burp's CA Certificate
  2. 用pageOffice控件实现 office 文档在线编辑Word 打开文档后在页面里触发事件
  3. 在PyCharm 配置使用flake8进行语法检测
  4. java长整型_java – 将整数转换为长整型
  5. 大数据Hive数据定义语言DDL
  6. 山东省家庭休闲农场发展对策研究
  7. C# 面试题整理与分享
  8. 戴尔服务器启动和raid设置(以dell r420为例)
  9. 新东方于厦门大学演讲的笔记——人生感悟
  10. windows系统“删库跑路“脚本bat