目录
[1)单元测试(Unit Testing)](#1)单元测试(Unit Testing))
[2)集成测试(Integration Testing):](#2)集成测试(Integration Testing):)
[3)系统测试(System Testing):](#3)系统测试(System Testing):)
[4)验收测试(Acceptance Testing):](#4)验收测试(Acceptance Testing):)
[1)黑盒测试(Black Box Testing):](#1)黑盒测试(Black Box Testing):)
[2)灰盒测试(Gray Box Testing):](#2)灰盒测试(Gray Box Testing):)
[3)白盒测试(White Box Testing):](#3)白盒测试(White Box Testing):)
[1. 功能性](#1. 功能性)
[2. 性能](#2. 性能)
[3. 兼容性](#3. 兼容性)
[4. 易用性](#4. 易用性)
[5. 安全性](#5. 安全性)
[6. 可靠性](#6. 可靠性)
[7. 可移植性](#7. 可移植性)
[2--- 划分等价类](#2--- 划分等价类)
[5. 案例:登录等价类划分](#5. 案例:登录等价类划分)
[1. 确定输入域和输出域](#1. 确定输入域和输出域)
[2. 识别边界条件](#2. 识别边界条件)
[3. 选择测试数据](#3. 选择测试数据)
[14.HTTP 请求组成](#14.HTTP 请求组成)
[16.HTTP 响应组成](#16.HTTP 响应组成)
[2XX 成功](#2XX 成功)
[4XX 客户端错误](#4XX 客户端错误)
[5XX 服务器错误](#5XX 服务器错误)
1)pytest的安装pytest的安装)
2)创建pyTest工程目录创建pyTest工程目录)
3)requests初体验requests初体验)
4)封装登录接口api封装登录接口api)
5)编写测试文件编写测试文件)
6)使用断言测试使用断言测试)
7)封装检测宿舍名称是否存在Api封装检测宿舍名称是否存在Api)
8)封装密码验证Api封装密码验证Api)
9)封装接口充值api封装接口充值api)
10)编写充值业务测试类编写充值业务测试类)
11)效果效果)
12)json文件数据驱动测试json文件数据驱动测试)
1) 安装allure 安装allure)
1.测试基础
1)单元测试(Unit Testing)
- 单元测试是针对软件中的最小可测试单元(通常是函数或方法)进行的测试。目的是验证每个部分是否按预期工作。
- 这种测试通常由开发者编写,并且经常作为自动化测试的一部分执行。
- 单元测试有助于及早发现代码级别的错误,使得问题定位更加容易。
2)集成测试(Integration Testing):
- 当多个单元组合在一起形成模块时,就需要进行集成测试了。这一阶段的目标是检查这些单元之间接口的数据交换是否正确无误。
- 集成测试旨在发现与接口相关的缺陷,确保各个组件能够协同工作。
- 可以采用不同的策略来进行集成测试,比如自顶向下、自底向上等方法。
- 功能交互测试
3)系统测试(System Testing):
- 系统测试是在所有组件都已集成后对整个系统进行全面的功能性及非功能性测试。这一步骤关注的是整个系统的运行情况,而不仅仅是单个功能点。
- 测试内容广泛,包括但不限于性能测试、安全性测试、兼容性测试等。
- 目标是确认软件产品满足了所有的需求规格说明书的要求。
- 功能整体测试
4)验收测试(Acceptance Testing):
- 验收测试发生在系统测试之后,有时也被称为"用户验收测试"(UAT, User Acceptance Testing)。它允许客户或者最终用户在真实环境中使用该软件,并对其进行评估。
- 主要目的是验证软件是否符合业务需求以及用户的期望值。只有当软件通过了验收测试,才能被认为是可以交付给客户的。
- 此阶段也可能涉及到Alpha测试和Beta测试等形式,在更广泛的范围内收集反馈信息。
- 用户对产品的满意程度
2.测试的可见程度
1)黑盒测试(Black Box Testing):
- 黑盒测试是指测试人员仅关注软件的功能需求而不考虑其内部结构或工作原理的一种测试方法。
- 测试用例基于规格说明文档来设计,而不是代码本身。目的是验证应用程序是否满足功能要求,并从用户的角度检查输出结果是否正确。
- 这种方法适用于所有层级的测试,但最常见于系统测试和验收测试阶段。
- 优点是能够模拟真实用户的使用场景;缺点则是难以覆盖到所有的代码路径。
- 简单来说:就是页面可见(UI功能可见),源代码不可见
- 就是对页面测试,如下图
2)灰盒测试(Gray Box Testing):
- 灰盒测试结合了黑盒与白盒两种方法的特点,测试者对于系统的内部有一定了解,但并不需要详细了解每一个细节。
- 在这种模式下,测试既可以依据功能规范也可以基于技术架构来进行。它允许测试者利用部分内部信息来指导测试过程,从而更有效地定位问题。
- 适合用于集成测试阶段,有助于发现接口之间的问题。
- 通过这种方式,测试者能够在一定程度上优化测试策略,同时保持较高的测试效率。
- 简单来说就是,部分源码可见,UI不可见,输入输出数据访问通道
- 常见的有接口测试
- 接口测试的工具PostMan
3)白盒测试(White Box Testing):
- 白盒测试又称为透明盒测试或结构性测试,指的是测试人员充分理解并直接访问软件的源代码以进行测试的方法。
- 测试用例的设计基于代码的逻辑流程,包括但不限于条件语句、循环等控制结构。
- 目标在于提高代码覆盖率,确保每个分支都被执行至少一次,帮助找出编码错误如未处理的异常、冗余代码等问题。
- 常见于单元测试阶段,对于保证软件质量具有重要意义。
- 缺点可能包括实现成本较高及对测试人员的技术要求较高等方面。
- 简单来说就是,全部源码都可见,UI不可见,测试的是本身语法逻辑
- 对源码逻辑,大概就是对下面这张图内容进行测试
4)冒烟测试 (Smoke Testing)
- 定义 :冒烟测试是一种快速、表面级别的确认测试,通常在新构建或新版本的软件发布后立即执行。它的目的是验证软件的核心功能是否正常工作。
- 目的:确保主要的功能没有严重的问题,使得进一步的测试(如详细的系统测试)有意义。如果冒烟测试失败,那么开发团队需要立即修复关键问题,然后再进行其他测试。
- 适用场景:当一个新的软件构建完成或者有较大的改动之后,首先进行冒烟测试来检查基本的功能性。
5)回归测试 (Regression Testing)
- 定义 :回归测试是在软件修改后重新运行之前的测试用例,以确保对现有功能的影响被最小化,并且之前已经解决的问题没有重新出现。
- 目的 :保证软件的新变更(例如bug修复、性能优化或新增功能)不会破坏现有的功能。它帮助确认新代码与现有代码之间的兼容性。
- 适用场景:每当软件经历了更改,无论是bug修复还是添加了新的特性之后,都应该执行回归测试来验证整个系统的稳定性。
3.如何验证某系统的质量?
1. 功能性
- 需求一致性 :确保实现的功能与需求规格说明书中的描述完全一致。
- 功能测试 :通过设计测试案例覆盖所有功能点,逐一验证功能是否按预期工作。
- 简单来说需求数量一致,功能一致
2. 性能
- 负载测试 :模拟不同的用户负载来检查系统在高压力下的表现。
- 压力测试 :逐步增加系统负载直到达到性能瓶颈,以确定系统的最大处理能力。
- 响应时间分析 :测量并优化关键操作的响应时间。
- 资源利用率监控:监测CPU、内存等资源使用情况,确保高效利用。
- 简单来说响应快,占用资源少
3. 兼容性
- 跨平台测试 :在不同的操作系统和浏览器上运行应用程序,确保其能够正常工作。
- 多设备测试 :对于移动应用来说,在多种型号手机和平板电脑上进行测试是非常重要的。
- 浏览器兼容性:如果适用的话,确保网站或web应用能在主要浏览器版本中正确显示和运作。
- 简单来说不同设备平台正常使用
4. 易用性
- 用户体验评估:邀请真实用户参与测试,收集反馈意见,并据此改进界面设计。
- 可用性测试:包括但不限于导航清晰度、交互流畅度等方面。
- 遵循UI/UX最佳实践:如使用标准图标、保持一致的设计风格等。
- 用户体验好
5. 安全性
- 渗透测试:模拟黑客攻击尝试发现安全漏洞。
- 代码审计:审查源码寻找潜在的安全隐患。
- 数据加密:确保敏感信息传输及存储时得到适当保护。
- 身份验证机制:实施强密码策略、双因素认证等措施加强账户安全。
- 敏感信息无泄露存储
6. 可靠性
- 长时间稳定性测试 :让系统连续运行较长时间,观察是否有异常发生。
- 故障恢复能力:人为制造故障条件,检验系统能否快速恢复正常服务。
- 日志记录与监控:建立有效的错误跟踪机制,便于问题定位。
- 简单来说长时间运行无异常
7. 可移植性
- 迁移测试 :将现有环境迁移到新的硬件或软件平台上后进行全面测试。
- 数据一致性检查 :迁移前后对比数据库内容,确保数据完整无损。
- 配置管理:维护好不同环境下的配置文件,简化部署流程。
- 升级迁移数据不丢失
4.等价类划分(重要)
1)等价类划分的基本原则
有效等价类
- 指符合规格说明要求的合理和有意义的输入数据构成的集合。
无效等价类
- 指不符合规格说明要求的不合理或无意义的输入数据构成的集合。
2)如何进行等价类划分
1---确定输入域
首先明确要测试的功能或模块的输入范围。这包括所有可能的输入数据类型、格式以及取值范围。
2--- 划分等价类
根据业务规则
- 依据功能需求文档中定义的业务规则来划分等价类。
边界条件
- 特别注意边界的划分,因为很多错误发生在边界上。
数据类型
- 对于不同的数据类型(如整数、浮点数、字符串等),分别考虑它们的有效和无效等价类。
3---设计测试用例
- 选择代表性的测试数据
- 从每个等价类中选取具有代表性的测试数据作为测试用例。
- 覆盖所有等价类
- 确保至少有一个测试用例能够覆盖每一个等价类。
- 关注边界条件
- 对于边界上的等价类,通常需要额外设计一些测试用例来专门验证这些边界情况。
3)示例
假设我们有一个简单的登录系统,用户名和密码的要求如下:
- 用户名长度为5到10个字符。
- 密码长度为6到12个字符。
我们可以这样划分等价类:
-
用户名
- 有效等价类:长度在5到10之间的任意字符串。
- 无效等价类:长度小于5或大于10的字符串;空字符串;包含非法字符的字符串。
-
密码
- 有效等价类:长度在6到12之间的任意字符串。
- 无效等价类:长度小于6或大于12的字符串;空字符串;包含非法字符的字符串。
然后,我们可以为每种等价类设计具体的测试用例,比如:
- 对于用户名的有效等价类,可以选择长度为5、8、10的用户名。
- 对于用户名的无效等价类,可以选择长度为4、11的用户名,以及包含特殊字符的用户名。
5. 案例:登录等价类划分
我们只对下面的登录窗口的用户名框和用户密码框进行划分
需求如下图片
1.需求:
2.功能分析
3.提取测试用例
6.边界值分析法的步骤
1. 确定输入域和输出域
- 输入域:明确所有可能的输入数据及其取值范围。
- 输出域:确定程序预期的输出结果。
2. 识别边界条件
- 对于每个输入变量,确定其最小值、最大值以及这些值附近的值。
- 如果有多个输入变量,还需要考虑它们之间的组合边界。
3. 选择测试数据
- 标准边界值 :
- 最小值(下限)
- 最大值(上限)
- 比最小值小一点的值
- 比最大值大一点的值
- 扩展边界值 (可选):
- 在有效范围内选取一些内部值
- 考虑特殊值如0、空字符串等
7.案例:注册表范围划分
1.需求
2.分析
3.测试用例提取
8.测试用例要素
1)测试用例编号:
- 目的 :提供一个唯一的标识符来区分不同的测试用例。
- 形式:可以是纯数字序列(如 TC001, TC002...)或者包含模块名加数字序号的形式(如 USER-TC001, LOGIN-TC002...),便于管理和追踪。
- 好处:有助于快速定位特定的测试用例,特别是在大型项目中。
- 格式:项目名+模块名+数字
2)用例标题:
- 要求 :简短而明确地描述测试的主要目标或功能点。
- 示例:"验证用户登录功能"、"检查错误消息显示正确性"等。
- 好处:让读者能够迅速把握测试的核心内容。
3)所属模块:
- 定义 :指明测试用例属于应用程序中的哪个具体部分或组件。
- 例子:如果是web应用,可能是"用户注册","购物车管理"等。
- 好处:有助于组织测试用例,并且方便团队成员了解各个模块的测试覆盖率。
4)优先级:
- 设定 :基于测试的重要性和紧急程度来确定。常见的分级有高、中、低三级。
- 影响因素:业务关键性、风险等级、时间限制等。
- 好处:指导测试执行顺序,确保最重要的测试首先被执行。
- P0-P3
5)前置条件:
- 内容 :列出所有必须满足的前提条件才能开始执行该测试用例。
- 例子:"数据库已初始化"、"用户已登录系统"等。
- 好处:保证测试环境的一致性和可重复性。
6)测试步骤:
- 编写 :详细记录每一步操作,确保任何人都能按照这些步骤重现测试过程。
- 注意点:保持步骤的清晰易懂,避免歧义。
- 好处:提高测试的准确性和可靠性。
7)测试数据:
- 选择 :根据测试的需求准备合适的输入数据。
- 类型:静态数据(预设的数据集)、动态生成的数据(通过脚本或其他方式自动生成)。
- 好处 :确保测试的有效性,覆盖不同场景下的行为。
8)预期结果:
- 定义 :在执行完测试步骤后应该观察到的结果。
- 作用:作为判断测试是否成功的基准。
- 好处:为评估测试结果提供依据。
9)实际结果:
- 记录 :在测试执行完毕后记录下实际发生的情况。
- 对比:将实际结果与预期结果进行比较,以此来判断测试是否通过。
- 好处:发现潜在的问题并记录下来供后续分析。
10)备注:
- 用途 :用于添加任何额外的信息,比如特殊说明、注意事项、问题描述等。
- 好处:提供了上下文信息,有助于理解和解释测试用例及其执行情况。
9.案例:测试用例转换为文档
转化为下面的形式
|--------------|-----------------------|-----------|---------|----------------------------|----------------------|---------------------------------|----------|
| 用例编号 | 用例标题 | 项目/模块 | 优先级 | 前置条件 | 测试步骤 | 测试数据 | 预期结果 |
| my_login_001 | 登录成功(已注册手机号+注册时使用密码) | 登录 | p1 | 1,已经打开登录界面 2,准备一个已经注册的手机号 | 1,输入账号 2,输入密码 3,点击登录 | 账号:12345678911 密码:123456 | 登录成功 |
| my_login_002 | 登录成功(已注册邮箱+注册时使用密码) | 登录 | p1 | 1,已经打开登录界面 2,准备一个已经注册的手机号 | 1,输入账号 2,输入密码 3,点击登录 | 账号:mjl1330338@163.com 密码:123457 | 登录成功 |
| my_login_003 | 登录成功(已注册用户账号+注册时使用密码) | 登录 | p1 | 1,已经打开登录界面 2,准备一个已经注册的手机号 | 1,输入账号 2,输入密码 3,点击登录 | 账号:mjl133033 密码:123458 | 登录成功 |
| my_login_004 | 登录失败(为空+有效密码) | 登录失败 | p2 | 1,已经打开登录界面 | 1,输入账号 2,输入密码 3,点击登录 | 账号: 密码:123456 | 登录失败 |
| my_login_005 | 登录失败(未注册手机号+有效密码) | 登录失败 | p2 | 1,已经打开登录界面 2,未注册手机号 3,有效密码 | 1,输入账号 2,输入密码 3,点击登录 | 账号:12345678922 密码:123456 | 登录失败 |
| my_login_006 | 登录失败(未注册邮箱+有效密码) | 登录失败 | p2 | 1,已经打开登录界面 2,未注册邮箱 3,有效密码 | 1,输入账号 2,输入密码 3,点击登录 | 账号:test@163.com 密码:123456 | 登录失败 |
| my_login_007 | 登录失败(未注册用户账号+有效密码) | 登录失败 | p2 | 1,已经打开登录界面 2,未注册用户名 3,有效密码 | 1,输入账号 2,输入密码 3,点击登录 | 账号:testAccount 密码:123456 | 登录失败 |
| my_login_008 | 登录失败(已注册手机号+无效密码) | 登录失败 | p2 | 1,已注册手机号 2,无效密码 | 1,输入账号 2,输入密码 3,点击登录 | 账号:12345678911 密码:789456 | 登录失败 |
| my_login_009 | 登录失败(已注册邮箱+无效密码) | 登录失败 | p2 | 1,已注册邮箱 2,无效密码 | 1,输入账号 2,输入密码 3,点击登录 | 账号:mjl1330338@163.com 密码:789456 | 登录失败 |
| my_login_010 | 登录失败(已注册用户账号+无效密码) | 登录失败 | p2 | 1,已注册用户账号 2,无效密码 | 1,输入账号 2,输入密码 3,点击登录 | 账号:mjl133033 密码:789456 | 登录失败 |
使用xlsx文件进行用例转化
10.判定表
判定表(Decision Table)是一种结构化的工具,用于表示复杂的逻辑条件和相应的动作。它通过表格的形式清晰地展示不同条件组合下的决策结果,特别适用于处理多条件判断的情况。判定表可以帮助测试人员设计全面的测试用例,确保所有可能的条件组合都被考虑到。
1)判定表的基本组成部分
- 条件桩(Condition Stubs) :列出所有的输入条件。
- 动作桩(Action Stubs) :列出所有可能的动作或输出。
- 条件项(Condition Entries):每个条件桩下对应的具体条件值(通常是T/真 或 F/假)。
- 动作项(Action Entries):每个动作桩下对应的具体动作(执行或不执行)。
- 规则(Rules):每行代表一组特定的条件组合及其对应的动作。
2)创建判定表的步骤
- 确定条件和动作 :首先明确需要考虑的所有输入条件和对应的输出动作。
- 列出所有条件组合:对于每个条件,可以有多个可能的取值(通常是二元的T/F),列出所有可能的组合。
- 填写动作:根据业务规则或需求文档,为每个条件组合填写对应的动作。
- 简化判定表:如果某些规则是重复的或者不可能发生的,可以将它们合并或删除。
3)示例
假设有一个银行系统,用户申请贷款时需要满足以下条件:
- 年龄大于等于18岁。
- 信用评分高于700分。
- 月收入大于5000元。
根据这些条件,系统决定是否批准贷款。我们可以创建一个判定表来表示这个逻辑:
条件桩 年龄 >= 18 信用评分 > 700 月收入 > 5000 动作桩 批准贷款 规则1 T T T T 批准 规则2 T T F F 拒绝 规则3 T F T F 拒绝 规则4 T F F F 拒绝 规则5 F T T F 拒绝 规则6 F T F F 拒绝 规则7 F F T F 拒绝 规则8 F F F F 拒绝
在这个例子中:
- 条件桩包括"年龄 >= 18"、"信用评分 > 700"和"月收入 > 5000"。
- 动作桩是"批准贷款"。
- 每个规则代表了一组具体的条件组合及其对应的动作。
4)简化判定表
在实际应用中,有些规则可能是不必要的或冗余的。例如,如果用户年龄小于18岁,无论其他条件如何,都不会批准贷款。因此,规则5到规则8可以简化为一个规则:
条件桩 年龄 >= 18 信用评分 > 700 月收入 > 5000 动作桩 批准贷款 规则1 T T T T 批准 规则2 T T F F 拒绝 规则3 T F T F 拒绝 规则4 T F F F 拒绝 规则5 F X X F 拒绝
这里的"X"表示该条件的取值不影响最终的结果。
5)使用判定表的好处
- 清晰性:以表格形式呈现,易于理解和维护。
- 完整性:确保所有可能的条件组合都被覆盖。
- 减少冗余:通过合并相似规则,减少不必要的测试用例。
- 提高效率:帮助快速识别和设计测试用例,提高测试覆盖率。
通过使用判定表,你可以更系统地设计测试用例,确保软件在各种复杂条件下都能正确工作。
11.禅道缺陷追踪
1.登录禅道
禅道网址:用户登录 - 禅道
点击登录即可
2.提交bug
进入主界面之后====>点击测试====>点击bug ====》 点击 提交bug
提交bug
可以看到我们提交的bug
因为我们是把bug提交给我们自己了,所以能提交bug的解决方案
12.案例:业务测试
1.充值业务图
2.用例设计
|-----------------|---------------|-----------|---------|----------|--------------------------------|-----------------------------------------------------|-------------|
| 用例编号 | 用例标题 | 项目/模块 | 优先级 | 前置条件 | 测试步骤 | 测试数据 | 预期结果 |
| my_recharge_001 | 充值成功 | 充值业务 | p0 | 1,打开网站 | 1,登录成功 2,不退出登录 3,寝室名字正确 4,密码正确 | 1,账号:mjl13303 2,密码:123456 3,寝室名字:2222 4,输入密码:456789 | 充值成功 |
| my_recharge_002 | 充值失败(登录失败) | 充值业务 | p1 | 1,打开网站 | 1,登录失败 | 1,账号:mjl13303 2,密码:456789 | 登录失败 |
| my_recharge_003 | 充值失败(退出登录) | 充值业务 | p1 | 1,打开网站 | 1,登录成功 2,退出登录 | 1,账号:mjl13303 2,密码:123456 | 退出登录,返回登录界面 |
| my_recharge_004 | 充值失败(寝室名字不正确) | 充值业务 | p1 | 1,打开网站 | 1,登录成功 2,不退出登录 3,寝室名字错误 | 1,账号:mjl13303 2,密码:123456 3,寝室名字:2223 | 提示寝室名字不正确 |
| my_recharge_005 | 充值失败(密码不正确) | 充值业务 | p1 | 1,打开网站 | 1,登录成功 2,不退出登录 3,寝室名字正确 4,密码错误 | 1,账号:mjl13303 2,密码:123456 3,寝室名字:2222 4,输入密码:456789 | 提示充值密码不正确 |
3.用例测试
1,充值成功测试
进入登录界面输入账号mjl133033,密码123456
跳转到信息页面
进入用户充值界面,输入寝室名字:2222
寝室名字存在
输入密码123456,密码存在
点击充值,弹出充值成功
我们再查询页面可以看到充值记录
2,充值失败(登录失败)
进入登录界面,输入账号mjl133033,密码456789
登录失败
3,充值失败(退出登录)
进入登录界面,输入账号mjl133033,密码123456
进入首页,点击退出按钮
返回到登录界面
4,充值失败(寝室名字不存在)
进入登录界面,输入账号mjl133033,密码:123456
输入寝室名字2221
寝室不存在,充值失败
5.充值失败(输入密码错误)
进入登录界面,账号mjl133033,密码123456
输入寝室号2222
输入充值金额和用户密码456789
密码错误充值失败。
13.案例:兼容性测试
1.谷歌浏览器
2.360浏览器
3.EDGE浏览器
4.自适应
5.移动端
14.HTTP 请求组成
请求行
-
这是HTTP请求的第一行,包含了三个主要元素:
- 请求方法 :定义了要对指定资源执行的操作类型(例如GET, POST, PUT, DELETE等)。
- 资源路径 :指定了请求的URL中的路径部分,告诉服务器客户端想要访问哪个资源。(打个比方,你去快递站取快递,那你肯定要告诉快递工作站工作人员(后端服务器)****自己快递的信息()。然后工作人员给你快递(响应))。
- 协议版本:表明使用的HTTP协议版本,如HTTP/1.1或HTTP/2.0。
请求头
-
紧随请求行之后的是一个或多个请求头字段,每个字段都包含有关客户端的信息或者关于如何处理请求的信息。常见的请求头包括
User-Agent
,Content-Type
,Accept
,Authorization
等。
请求体
- 对于某些请求方法(比如POST或PUT),请求体是必需的,它包含了实际要发送给服务器的数据。这个数据可以是表单数据、JSON对象、文件上传等形式。GET请求通常没有请求体。
15.常见的请求方法
GET
- 用来获取资源。由于GET请求可能会被缓存且会被记录在浏览器历史中,所以不应该用于敏感操作。
POST
- 常用于提交表单数据或上传文件到服务器。与GET不同,POST请求的数据不会出现在URL中,因此适合传递密码等敏感信息。
PUT
- 用于替换目标资源上的所有当前内容。它是幂等的,这意味着多次相同的PUT请求应该产生相同的结果。
DELETE
- 用于删除指定的资源。同样,DELETE也是幂等的。
16.HTTP 响应组成
状态行:
- 状态行是响应的第一行,它包含HTTP版本号、状态码以及对应的状态消息。
- 例如:
HTTP/1.1 200 OK
HTTP/1.1
是协议版本。200
是状态码,表示请求成功。OK
是与状态码相关联的简短文本描述。
响应头:
- 响应头提供了关于响应的信息,如内容类型、编码方式、缓存控制等。
- 一些常见的响应头包括:
Content-Type
: 指示了响应数据的MIME类型(如text/html
,application/json
)。Content-Length
: 响应体的长度,以字节为单位。Date
: 发送响应的时间。Server
: 生成响应的软件名称和版本。Cache-Control
: 控制缓存的行为。Expires
: 资源失效日期,用于缓存机制。Location
: 在重定向时使用,指示新的资源位置。Set-Cookie
: 设置cookie信息,供浏览器保存并在未来的请求中发送回服务器。
响应体:
- 响应体包含了从服务器返回的实际内容,比如HTML文档、图片或JSON对象。
- 对于某些响应,比如状态码为204 No Content的情况,响应体可以为空。
17.常见的响应状态码
2XX 成功
-
表示请求已经被成功接收、理解和接受。
- 200 OK:最常用的成功响应。
- 201 Created:当POST请求创建了一个新资源时返回。
- 204 No Content:请求已成功处理,但不返回任何实体主体。
4XX 客户端错误
-
这类错误意味着客户端可能发生了问题,例如格式不正确的请求。
- 400 Bad Request :服务器无法理解请求的内容。
- 401 Unauthorized :需要用户提供身份验证才能获取资源。
- 403 Forbidden :用户有权限访问该资源,但是服务器拒绝了请求。
- 404 Not Found :请求的资源不存在。
5XX 服务器错误
-
表示服务器遇到了内部错误,无法完成请求。
- 500 Internal Server Error:服务器遇到意外情况,无法完成请求。
- 503 Service Unavailable:服务器暂时无法处理请求,通常是由于过载或维护。
18.HTTP中的一些解释
下图是请求头,响应头和url
请求路径参数
响应体
19.postman测试充值业务
1)充值流程
2)测试用例提取
3)测试用例设计
|-----------------|--------|---------|----------|----------|----------|---------------------|----------|------------|------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ID | 模块 | 优先级 | 用例名称 | 接口名称 | 前置条件 | 请求url | 请求方法 | 请求参数类型 | 请求参数 | 预期结果 |
| my_recharge_001 | 充值模块 | p0 | 充值成功 | 登录接口 | | /login | get | params | username: mjl133033 userpassword: 123456 | { "statusCode": 200, "data": { "userId": 4, "userName": "mjl133033", "userPassword": "", "userSex": "男", "userXh": "2202220488", "userPhone": "12345678911", "userStatus": "0" }, "message": "登录成功", "token": "xxxxx" } |
| my_recharge_001 | 充值模块 | p0 | 充值成功 | 寝室判断接口 | 登录成功 | /checkDormitoryName | get | params | dormitorynname: 2222 | { "statusCode": 205, "data": { "dormitoryId": 1, "dormitoryName": "2222", "dormitoryMonkey": 5148 }, "message": "寝室存在" } |
| my_recharge_001 | 充值模块 | p0 | 充值成功 | 密码判断接口 | 登录成功 | /checkOldPwd | get | params | username: mjl133033 userpassword: 123456 | { "statusCode":203, "data":null ,"message":"密码正确" } |
| my_recharge_001 | 充值模块 | p0 | 充值成功 | 充值接口 | 登录成功 | /despoitMonkey | get | params | userid: 4 usermonkey: 60 dormitoryid: 1 | {"statusCode":205, "data":null, "message":"充值成功" } |
4)PostMan测试
1--新建一个集合类
2--新建一个请求
3--添加接口信息
4--登录接口测试
5--创建一个环境
6--为集合设置环境
7--设置myEn环境中的token
8--请求头中设置myEn环境变量的token
9--密码检查接口测试
10--充值接口测试
20.PostMan批量执行
21.PostMan断言
//判断状态码是不是200
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
//判断响应数据中是否包含成功
pm.test("判断响应数据中是否包含成功",function(){
pm.expect(pm.response.text()).to.include("成功")
})
//判断JSON数据中msg的值
pm.test("断言json数据中的ms值为登录成功:",function(){
//获取响应体数据
var myJson = pm.response.json();
pm.expect(myJson.message).to.eql("登录成功")
})
22.Postman参数化(引入外部文件)
1-编写外部json文件
javascript[ { "username":"mjl133033", "userpassword":"123456", "statusCode":200, "messageContain":"成功", "message":"登录成功" }, { "username":"mjl13303322", "userpassword":"123456", "statusCode":200, "messageContain":null, "message":"用户名不存在" },{ "username":"mjl133033", "userpassword":"456789", "statusCode":200, "messageContain":null, "message":"密码错误" } ]
2-如何引入外部json文件
3-如何引入外部json文件中的数据
Test代码中使用data.键名
//获取响应体信息
var myData = pm.response.json()
//把token放置在myEn环境变量中
pm.environment.set("token",myData.token)
//判断状态码是不是200
pm.test("Status code is 200", function () {
pm.response.to.have.status(data.statusCode);
});
//判断JSON数据中msg的值
pm.test("用户密码错误:",function(){
//获取响应体数据
var myJson = pm.response.json();
pm.expect(myJson.message).to.eql(data.message)
})
非Tests代码使用{{键名}}引用数据对象
4-点击测试
23.PyTest接口自动化
1)pytest的安装
win+R===》cmd ===> 安装 pip3 install requests ===>验证安装 pip3 show requests
注(自己电脑上一定要有pyton环境)
2)创建pyTest工程目录
1-创建项目
2--手动创建pytets目录
如下图
3)requests初体验
pythonimport requests # request.get() response = requests.get(url="http://localhost:8888/login", params={ "username":"mjl133033", "userpassword":"123456" }); print response.text
4)封装登录接口api
pythonimport requests # 定义两个变量接受参数 username = "mjl133033" userPassword = "123456" class MyLoginApi: #初始化api def __init__(self): # 这个是登录的url self.myLoginUrl = "http://localhost:8888/login" self.response = None # 登录 def login(self,username,userPassword): return requests.get(url=self.myLoginUrl, params={"username":username, "userpassword":userPassword}) # 获取token def getToken(self): response = self.login(username,userPassword) return response.json()["token"]
5)编写测试文件
pythonimport api.LoginApi # 登录测试类 myLoginAPi = api.LoginApi.MyLoginApi() # myData myDataArray = [ { "username":"mjl133033", "userpassword":"123456", "statusCode":200, "messageContain":"成功", "message":"登录成功" }, { "username":"mjl13303322", "userpassword":"123456", "statusCode":200, "messageContain":"", "message":"用户名不存在" },{ "username":"mjl133033", "userpassword":"456789", "statusCode":200, "messageContain":"", "message":"密码错误" } ] for i in range(len(myDataArray)): response = myLoginAPi.login(myDataArray[i]["username"],myDataArray[i]["userpassword"]) statusCode = response.json()["statusCode"] message = response.json()["message"] myData = response.json()["data"] token = response.json()["token"] print ("statusCode :" , statusCode) print ("message :" , message) print ("data :", myData) print ("token :", token) print ("--------------------------------------------------") # print ("statusCode:状态码是否是200"); # assert 200 == statusCode # print ("message:返回信息是否包含:登录成功" ) # assert "登录成功" in message # print ("token:token是否不为空") # assert token != ""
测试结果
6)使用断言测试
pythonimport api.LoginApi # 登录测试类 myLoginAPi = api.LoginApi.MyLoginApi() # myData myDataArray = [ { "username":"mjl133033", "userpassword":"123456", "statusCode":200, "messageContain":"成功", "message":"登录成功" }, { "username":"mjl13303322", "userpassword":"123456", "statusCode":200, "messageContain":"", "message":"用户名不存在" },{ "username":"mjl133033", "userpassword":"456789", "statusCode":200, "messageContain":"", "message":"密码错误" } ] for i in range(len(myDataArray)): print("--------------------------------------------------") response = myLoginAPi.login(myDataArray[i]["username"],myDataArray[i]["userpassword"]) statusCode = response.json()["statusCode"] message = response.json()["message"] myData = response.json()["data"] token = response.json()["token"] print ("statusCode :" , statusCode) print ("message :" , message) print ("data :", myData) print ("token :", token) if (statusCode==200): print("statusCode:状态码为是200"); assert 200 == statusCode else: print("statusCode:状态码不为200,是",statusCode) assert 200 != statusCode if ("登录成功" in message): print ("message:返回信息是否包含:登录成功" ) assert "登录成功" in message else: print ("message:返回信息不包含:登录成功",message) assert "登录成功" not in message if(token!=None): print("token:token不为空",token) assert token != None else: print("token:token为空",token) assert token == None print ("============================================")
7)封装检测宿舍名称是否存在Api
python# 检测宿舍名称是否存在 import requests class CheckDormitoryName: def __init__(self): self.checkDormitoryNameUrl = "http://localhost:8888/checkDormitoryName" def checkDormitoryName(self,dormitoryName,token): # Headers headers = { "token":token } #传递参数 return requests.get(self.checkDormitoryNameUrl,params={"dormitorynname":dormitoryName},headers=headers)
8)封装密码验证Api
python# 密码是否正确 import requests class MyCheckOldPwd: def __init__(self): self.checkOldPwdUrl = "http://localhost:8888/checkOldPwd" def checkOldPwd(self,username,oldPwd,token): # Headers headers = { "token": token } response = requests.get(self.checkOldPwdUrl,params = {"username":username,"userpassword":oldPwd},headers=headers) return response
9)封装接口充值api
pythonimport requests class MyDepoitMonkey: def __init__(self): self.depoitMonkeyUrl = "http://localhost:8888/despoitMonkey" def depoitMonkey(self,userid,usermonkey,dormitoryid,token): headers = { "token": token } data = { "userid":userid, "usermonkey":usermonkey, "dormitoryid":dormitoryid, } response = requests.get(self.depoitMonkeyUrl,params=data,headers = headers) return response
10)编写充值业务测试类
python# 充值业务 # 登录api from api.LoginApi import MyLoginApi # 检查寝室api from api.CheckDormitoryName import CheckDormitoryName # 充值api from api.DepoitMonkey import MyDepoitMonkey # 密码api from api.CheckOldPwd import MyCheckOldPwd import pytest class TestMyRecharge001: # 定义token 用于中间缓存,供其他api使用 token = None; # 前置处理 def setup_method(self): self.myLoginApi = MyLoginApi() self.checkDormitoryName = CheckDormitoryName() self.depoitMonkey = MyDepoitMonkey() self.checkOldPwd = MyCheckOldPwd() self.myToken = None ; # 后置处理 def teardown_method(self): pass # 登录 接口测试 def test01_my_login(self): print("开始执行登录接口") username = "mjl133033" userpassword = "123456" response = self.myLoginApi.login(username,userpassword) print(response.text) # 获取token self.myToken = response.json()["token"] print(self.myToken) print("结束") # 寝室名字判断测试 def test02_check_dormitory_name(self): # 寝室名字 print("开始执行寝室名字校验接口") dormitoryName = "2222" response = self.checkDormitoryName.checkDormitoryName(dormitoryName,self.myToken) print(response.json()["message"]) print("结束") # 密码测试接口 def test03_check_old_pwd(self): print("开始执行密码校验接口") username = "mjl133033" oldPwd = "123456" response = self.checkOldPwd.checkOldPwd(username,oldPwd,self.myToken) print(response.json()["message"]) print("结束") # 充值测试接口 def test04_depoit_monkey(self): print("开始执行充值接口") userid = "1" usermonkey = "100" dormitoryid = "1" response = self.depoitMonkey.depoitMonkey(userid,usermonkey,dormitoryid,self.myToken) print(response.json()["message"]) print("结束")
11)效果
12)json文件数据驱动测试
在data文件夹下编写json数据
python[ { "username":"mjl133033", "userpassword":"4567894" }, { "username":"mjl13303322", "userpassword":"4854678" },{ "username":"mjl1330332", "userpassword":"123456" } ]
python# 密码接口测试类 import json import api.CheckOldPwd import pytest import api.LoginApi # 读取json数据,并且封装为元组返回 def dataBuild(fileJson): # 定义空列表接受数据 dataList = [] with open(fileJson,"r") as f: # 加载json文件 jsonData = json.load(f) # 循环遍历封装json数据 for data in jsonData: # 添加元组 dataList.append((data["username"],data["userpassword"])) # 处理数据返回 return dataList # 实例化 class TestMyRecharge002: def setup_method(self): self.checkOldPwd = api.CheckOldPwd.MyCheckOldPwd() self.myLoginApi = api.LoginApi.MyLoginApi(); self.token = None def teardown_method(self): pass def test01_my_login(self): # 模拟已经登录 response = self.myLoginApi.login("mjl133033","123456"); # 设置token self.token = response.json()["token"] # def checkOldPwd(self,username,oldPwd,token): @pytest.mark.parametrize("username,userpassword",dataBuild(fileJson="../data/MyPwdJson.json")) def test01_check_old_pwd(self,username,userpassword): # 测试数据 # 测试结果 result = self.checkOldPwd.checkOldPwd(username,userpassword,self.token) print("下面是里面的json数据") print(result.json())
13.定义config文件
# 修改配置文件
import os
BASE_URL = "http://localhost:8888"
# 获取项目的根路径
PROJECT_PATH = os.path.dirname(file)
修改对应的信息
24.Allure测试报告
1) 安装allure
win+r==>命令窗口===>pip install allure-pytest
2)allure下载地址
3)配置环境变量
查看版本号 ===> allure --version
4)编写pytest.ini配置文件
[pytest]
addopts=-s --alluredir report
testpaths=./script
python_file=*.py
python_classes=*
python_functions=*
5)运行pytest
Teminal ===>命令行===》pytest -s ==> 等待运行结果
6)启动网页报告
如果你的配置都已经完成,但是下面出现这种情况,接着往下看
cmd窗口输入 allure serve report
会弹出来这个页面:如果没有弹出来那么就输入 上面的网址