【Web UI自动化测试】Web UI自动化测试之框架篇(全网最全)
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
本文大纲截图
-
UnitTest框架
-
PyTest框架
框架 框架英文单词 framework为解决一类事情的功能的集合。需要按照框架的规定套路去书写代码。
一、UnitTest框架介绍【文末分享自动化测试学习资源】
1、什么是UnitTest框架
-
概念UnitTest是python自带的一个单元测试框架用它来做单元测试
-
自带的框架不需要单独按照只要安装了 python就可以用
-
第三方框架想要使用 需要先安装后使用如pytest
-
单元测试框架主要用来做单元测试一般单元测试是开发做的。对于测试来说UnitTest 框架的作用是自动化脚本用例代码执行框架使用UnitTest框架来管理 运行多个测试用例的
2、为什么使用UnitTest框架
-
1能够组织多个用例去执行
-
2提供丰富的断言方法让程序代码代替人工自动的判断预期结果和实际结果是否相符
-
3能够生成测试报告
-
4UnitTest框架对于测试来说的作用是自动化脚本执行框架使用 UnitTest框架来管理运行多个测试用例的脚本
3、UnitTest框架核心组成要素
1TestCase【最核心的模块】
-
TestCase测试用例这个测试用例是UnitTest框架的组成部分不是手工和自动化中所说的用例Test Case
-
主要作用每个TestCase测试用例都是一个代码文件在这个代码文件中 来书写 真正的用例代码
2TestSuite
-
TestSuite测试套件用来 管理、组装打包多个 TestCase测试用例的
3TestRunner
-
TestRunner测试执行测试运行用来 执行 TestSuite测试套件的
4TestLoader
-
TestLoader测试加载功能是对 TestSuite测试套件功能的补充管理、组装打包多个 TestCase测试用例的
5Fixture
-
Fixture测试夹具书写在TestCase测试用例代码中是一个代码结构可以在每个方法执行前后都会执行的内容
-
每个用例中重复的代码就可以写在 Fixture 代码结构中只写一遍但每次用例方法的执行都会执行Fixture中的代码
-
举例登录的测试用例
-
1、打开浏览器
-
2、输入网址
-
4、UnitTest框架实践
4.1 TestCase测试用例
介绍
-
1每个 TestCase测试用例都是一个代码文件在这个代码文件中 来书写真正的用例代码
-
2代码文件的名称必须按照标识符的规则来书写可以将代码的作用在文件的开头又多行注释说明
注意
-
1代码文件的命名规范
-
1>代码文件名字不能以数字开头
-
2>代码文件名字中不能有空格
-
3>代码文件名字不能有中文
-
4>代码文件名字由字母、数字、下划线组成且不能以数字开头
-
-
2代码运行没结果
-
原因右键运行没有
unittest for xxx
的提示 而出现的问题 -
解决方案1重新建一个代码文件将写好的代码复制进去
-
解决方案2删除已有的运行方式
-
-
3没有找到用例测试方法中不是以 test_ 开头的或者单词写错了
步骤
-
1导包 import unittest
-
2自定义测试类
-
3在测试类中书写测试方法
-
4执行用例
代码
# 1、导包
import unittest
# 2、新建测试类需要继承 unittest 模块中的 TestCase类 即可
class TestDemo1(unittest.TestCase):
# 3、书写测试方法即 用例代码目前没有真正的用例代码使用 print 代替
# 注意书写要求测试方法 必须以 test_ 开头本质以 test 开头
def test_method1(self):
print("测试方法1")
def test_method2(self):
print("测试方法2")
class TestDemo2(unittest.TestCase):
def test_method3(self):
print("测试方法3")
def test_method4(self):
print("测试方法4")
# 4、执行用例方法
# 4.1 将光标放在 类名后边 运行会执行类中的 所有测试方法
# 4.2 将光标放在 方法名后边 运行只执行当前的方法
4.2 TestSuite & TestRunner测试套件&运行
介绍
-
1TestSuite(测试套件)管理、打包、组装 多个 TestCase(测试用例) 文件
-
2TestRunner(测试执行)执行 TestSuite(测试套件)
步骤
-
1导包 import unittest
-
2实例化套件对象创建套件对象
-
3使用套件对象 添加 用例方法
-
4实例化运行对象创建运行对象
-
5使用运行对象 去执行 套件对象
实例化套件对象并添加测试用例:
# 导包
import unittest
from UnitTest_study.hm01_unittest import TestDemo
# 实例化套件对象
suite = unittest.TestSuite()
# 方法1单个添加测试用例需要导包TestDemo
suite.addTest(TestDemo('test_001'))
suite.addTest(TestDemo('test_002'))
# 方法2批量添加测试用例需要导包TestDemo
suite.addTest(unittest.makeSuite(TestDemo))
实例化运行对象:
# 导包
import unittest
# 实例化运行对象
runner = unittest.TextTestRunner()
# 运行测试套件
runner.run(suite)
查看测试执行结果的方法:
-
说明
.
运行通过F
用例不通过E
用例代码有问题
代码
方法一使用套件对象单个单个方法添加用例并运行
-
添加用例基本格式
unittest.TestSuite().addTest(类名('方法名'))
-
特点逐条添加测试用例
-
运行用例基本格式
unittest.TextTestRunner().run(测试用例集)
# 1、导包
import unittest
from unittest_testcase import TestDemo1, TestDemo2
# 2、实例化套件对象创建套件对象
suite = unittest.TestSuite()
# 3、使用套件对象 添加 用例方法
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)
方法二使用套件对象批量单个类添加用例并运行
-
添加用例基本格式
unittest.TestSuite().addTest(unittest.makeSuite(类名))
-
特点批量添加测试用例
-
运行用例基本格式
unittest.TextTestRunner().run(测试用例集)
# 1、导包
import unittest
from unittest_testcase import TestDemo1, TestDemo2
# 2、实例化套件对象创建套件对象
suite = unittest.TestSuite()
# 3、使用套件对象 添加 用例方法
suite.addTest(unittest.makeSuite(TestDemo1))
suite.addTest(unittest.makeSuite(TestDemo2))
# 4、实例化运行对象创建运行对象
runner = unittest.TextTestRunner()
# 5、使用运行对象 去执行 套件对象
# 格式运行对象.run(套件对象)
runner.run(suite)
4.3 TestLoader测试加载
介绍 TestLoader(测试加载)和 TestSuite 的作用一样是对 TestSuite 功能的补充用来管理组装打包多个 TestCase。在一个项目中 TestCase(测试用例)的代码一般放在一个单独的目录case中
步骤
-
1导包 import unittest
-
2实例化测试加载对象并添加用例得到的是 suite 对象
-
3实例化 运行对象
-
4运行对象执行套件对象
代码:
-
基本格式一
suite = unittest.TestLoader().discover('case', 'test_*.py')
-
基本格式二
suite = unittest.defaultTestLoader.discover('case', 'test_*.py')
# 导包
import unittest
# 方法1实例化对象并添加测试用例
suite = unittest.TestLoader().discover('case', 'test_*.py')
# 方法2实例化对象并添加测试用例(说明插件代码中有一句defaultTestLoader = TestLoader()所以有了方法2)
suite = unittest.defaultTestLoader.discover('case', 'test_*.py')
# 运行测试套件
unittest.TextTestRunner().run(suite)
4.4 Fixture测试夹具
介绍 Fixture(测试夹具)是一个代码结构书写在 TestCase代码中可以在每个方法执行前后都会执行的内容在某些特定情况下会自动执行。Fixture是一个概述对一个测试用例环境的初始化和销毁就是一个Fixture。
Fixture控制级别 方法级别、类级别、模块级别
方法级别【掌握】
-
作用在每个测试方法用例代码执行前后都会自动调用的结构
-
关键字
setUp
、tearDown
-
格式
class TestDemo(object):
"""测试示例类"""
def setUp(self):
"""每个方法执行之前都会执行"""
print("方法 -> 开始")
def tearDown(self):
"""每个方法执行之后都会执行"""
print("方法 -> 结束")
类级别【掌握】
-
作用在每个测试类中所有方法执行前后 都会自动调用的结构在整个类中 执行之前执行之后各一次
-
说明类级别的fixture 是一个 类方法要用
@classmethod
来装饰 -
关键字
setUpClass
、tearDownClass
-
格式
class TestDemo(object):
"""测试示例类"""
@classmethod
def setUpClass(cls):
"""每个方法执行之前都会执行"""
print("类 -> 开始")
@classmethod
def tearDownClass(cls):
"""每个方法执行之后都会执行"""
print("类 -> 结束")
模块级别【了解】
-
作用在每个模块代码文件执行前后执行的代码结构
-
关键字
setUpModule
、tearDownModule
-
格式
# 模块级别的需要写在类的外边直接定义函数即可
def setUpModule(self):
"""每个方法执行之前都会执行"""
print("模块 -> 开始")
def tearDownModule(self):
"""每个方法执行之后都会执行"""
print("模块 -> 结束")
class TestDemo(object):
"""测试示例类"""
代码
import unittest
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_01(self):
print('输入正确用户名密码验证码点击登录')
def test_02(self):
print('输入错误用户名密码验证码点击登录')
4.5 跳过
介绍
-
使用场景对于一些未完成的或者不满足测试条件的测试函数和测试类不想执行可以使用跳过
-
使用方法利用装饰器来完成代码书写在 TestCase 文件中
-
格式一直接将测试函数标记成跳过
-
@unittest.skip('跳过原因')
-
-
格式二根据条件判断测试函数是否跳过判断条件成立则跳过
-
@unittest.skipIf(判断条件, '跳过原因')
-
代码
import unittest
# version = 30
version = 29
class TestDemo(unittest.TestCase):
@unittest.skip('没有什么原因就是不想执行')
def test_01(self):
print('测试方法01')
@unittest.skipIf(version >= 30, '版本大于 30不用测试')
def test_02(self):
print('测试方法02')
def test_03(self):
print('测试方法03')
4.6 断言
介绍
-
概念让程序代替人为判断测试程序执行结果是否符合预期结果的过程
-
作用
-
1提高写实效率
-
2实现自动化测试让脚本在无人值守状态下运行
-
-
断言结果
-
True用例通过
-
False代码抛出异常用例不通过
-
-
说明
-
1UnitTest中提供了非常丰富的断言方法
-
2复杂的断言方法在自动化测试中几乎使用不到所以掌握几个常用的即可
-
3在unittest中使用断言都需要通过 self.断言方法 来使用
-
UnitTest断言方法
self.assertEqual(预期结果, 实际结果)
-
含义判断预期结果和实际结果 是否相等
-
返回结果如果相等用例通过如果不相等用例不通过抛出异常。
self.assertIn(预期结果, 实际结果)
-
含义判断预期结果 是否包含 在实际结果中
-
结果包含用例通过不包含用例不通过抛出异常。
代码
import unittest
from UnitTest_study.hm07_login import login
class TestLogin(unittest.TestCase):
def test_uername_password_ok(self):
"""正确用户名和密码admin123456登录成功"""
self.assertEqual('登录成功', login('admin', '123456'))
4.7 参数化
介绍
-
好处相似代码不需要多次书写
-
说明
-
1在测试方法中使用 变量 来代替具体的测试数据然后使用传参的方法将测试数据传递给方法的变量
-
2unittest框架本身不支持 参数化要使用参数化需要安装插件来完成
-
-
场景
-
1测试数据一般放在 json 文件中
-
2使用代码读取 json 文件提取出符合要求格式的数据—>>
[(), ()]
或[[], []]
-
-
安装
pip install parameterized
-
步骤
-
1导包 unittestparameterized
-
2定义测试类
-
3书写测试方法用到的测试数据使用变量代替
-
4组织测试数据并传参
-
-
测试数据
-
1测试数据放在 json 文件中
-
2新建函数读取 json文件中的 测试数据读取的数据格式
[(), (), ()]
或[[], [], []]
-
# 组织测试数据 [(), (), ()]
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
-
3利用装饰器给函数变量传递数据
-
@parameterized.expand(build_data())
代码示例1
import unittest
from parameterized import parameterized
from UnitTest_study.hm07_login import login
# 组织测试数据 [(), (), ()]
data = [
('admin', '123456', '登录成功'),
('root', '123456', '登录失败'),
('admin', '123123', '登录失败')
]
# 定义测试类
class TestLogin(unittest.TestCase):
# 书写测试方法用到的测试数据使用变量代替
# 组织测试数据并传参装饰器 @
@parameterized.expand(data)
def test_login(self, username, password, expect):
"""正确用户名和密码admin123456登录成功"""
self.assertEqual(expect, login(username, password))
代码示例2
测试数据文件 data.json
代码
import json
import unittest
from parameterized import parameterized
from UnitTest_study.hm07_login import login
# 组织测试数据 [(), (), ()]
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
# 定义测试类
class TestLogin(unittest.TestCase):
# 书写测试方法用到的测试数据使用变量代替
# 组织测试数据并传参装饰器 @
@parameterized.expand(build_data())
def test_login(self, username, password, expect):
"""正确用户名和密码admin123456登录成功"""
self.assertEqual(expect, login(username, password))
4.8 测试报告插件
自带的测试报告
只有单独运行 TestCase 的代码时才会生成测试报告位置在控制台左侧区域的右上角
第三方测试报告
-
1获取第三方的 测试运行类模块并将其放在代码目录中
-
2导包 unittest、HTMLTestRunner、HTMLTestReportCN
-
3实例化 套件对象并使用 加载套件加载用例
-
4实例化 第三方的运行对象运行 套件对象并生成测试报告
HTMLTestRunner 插件
-
HTMLTestRunner
# 导包
import unittest
from UnitTest_study.HTMLTestRunner import HTMLTestRunner
suite = unittest.defaultTestLoader.discover('.', 'hm08_parameterized1.py')
file = 'report.html'
with open(file, 'wb') as f:
runner = HTMLTestRunner(f, 2, '测试报告', 'python 3.7')
runner.run(suite)
-
HTMLTestRunnerCN
# 导包
import unittest
from UnitTest_study.HTMLTestRunnerCN import HTMLTestReportCN
suite = unittest.defaultTestLoader.discover('.', 'hm08_parameterized1.py')
with open('report_CN.html', 'wb') as f:
HTMLTestReportCN(f).run(suite)
4.9 总结
1TestCase测试用例组织用例文件TestCase里面书写 跳过、断言、参数化使用Fixture夹具单个测试文件直接运行可以得到测试报告有多个测试文件运行则需要组装运行生成测试报告。
2、添加测试用例 到 测试套件中
-
TestSuite测试套件套件对象组装测试用例
# 导包
import unittest
from UnitTest_study.hm01_unittest import TestDemo
# 实例化套件对象
suite = unittest.TestSuite()
# 方法1单个添加测试用例需要导包TestDemo
suite.addTest(TestDemo('test_001'))
suite.addTest(TestDemo('test_002'))
# 方法2批量添加测试用例需要导包TestDemo
suite.addTest(unittest.makeSuite(TestDemo))
-
TestLoader测试加载默认加载对象加载测试用例
# 导包
import unittest
# 方法1实例化对象并添加测试用例
suite = unittest.TestLoader().discover('case', 'hm*.py')
# 方法2实例化对象并添加测试用例
suite = unittest.defaultTestLoader.discover('case', 'hm*.py')
# 运行测试套件
unittest.TextTestRunner().run(suite)
3、实例化运行对象 运行 测试条件
-
TestRunner运行对象
# 导包
import unittest
# 实例化运行对象
runner = unittest.TextTestRunner()
# 运行测试套件
runner.run(suite)
-
运行并生成测试报告
-
基本格式
-
with open('./report.html', 'wb') as f:
-
# 实例化第三方运行对象
-
第三方运行对象 = 第三方运行类(f)
-
第三方运行对象.run(套件对象)
-
-
第三方运行类文件对象(打开文件需要使用 wb 方式)
-
HTMLTestRunner
-
import unittest
from UnitTest_study.HTMLTestRunner import HTMLTestRunner
suite = unittest.defaultTestLoader.discover('.', 'hm08_parameterized1.py')
file = 'report.html'
with open(file, 'wb') as f:
runner = HTMLTestRunner(f, 2, '测试报告', 'python 3.7')
runner.run(suite)
-
HTMLTestRunnerCN
import unittest
from UnitTest_study.HTMLTestRunnerCN import HTMLTestReportCN
suite = unittest.defaultTestLoader.discover('.', 'hm08_parameterized1.py')
with open('report_CN.html', 'wb') as f:
runner = HTMLTestReportCN(f)
runner.run(suite)
二、PyTest框架介绍
1、什么是PyTest框架
PyTest是python中一种单元测试框架同自带的UnitTest测试框架类似相比于UnitTest框架使用起来更简洁效率更高。在自动化测试中充当测试执行的功能并可以与UnitTest互换。
2、为什么使用PyTest框架
-
1非常容易上手入门简单文档丰富文档中有很多实例可以参考官方文档
https://docs.pytest.org/en/6.2.x/
-
2支持简单的单元测试和复杂的功能测试
-
3支持参数化UnitTest需要通过插件扩展参数化功能
-
4执行测试过程中可以将某些测试跳过或者对某些预期失败的Case标记成失败
-
5支持重复执行失败的Case通过安装插件实现
-
6支持运行由NoseUnitTest编写的测试Case。注pytest框架的脚本在UnitTest下无法执行
-
7具有很多第三方插件并且可以自定义扩展。插件获取
https://docs.pytest.org/en/latest/reference/plugin_list.html
-
8方便的和持续集成工具集成
3、PyTest框架安装与基本使用
与UnitTest不同的是pytest需要先安装才能使用。注意如果pytest命令无法使用则需要以管理员身份重新安装pytest。
安装步骤
-
打开cmd窗口输入命令
-
安装
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pytest
-
确认版本
pytest --version
-
查看
pip show pytest
测试形式
-
测试函数形式
-
1新建hm01.py文件文件中编写函数名以test开头的测试函数
-
2打开
Terminal
切换到.py文件路径下输入pytest -s hm01.py
-
3控制台查看执行结果
-
-
测试类形式
-
1新建hm02.py文件文件中编写类名以Test开头的测试类测试方法名必须以 test 开头
-
2打开
Terminal
切换到.py文件路径下输入pytest -s hm02.py
-
3控制台查看执行结果
-
运行方式
-
命令行模式【建议】
-
命令行中执行
pytest -s 测试脚本文件
-
如
pytest -s test_login.py
-
-
主函数模式
-
在 测试脚本文件中增加主函数
-
# 主函数模式基本格式
if __name__ = '__main__':
pytest.main(["-s", "文件名.py"])
#举例在 test_login.py 文件中增加主函数
if __name__ = '__main__':
pytest.main(["-s", "test_login.py"])
-
说明
-
1-s 表示支持控制台打印如果不加print不会出现任何内容
-
2主函数模式需要导包 import pytest
-
4、PyTest框架实践
4.1 配置文件
介绍
-
场景使用配置文件后可以快速的使用配置的项来选择执行哪些测试模块
步骤
-
1项目下新建scripts模块
-
2将测试脚本文件放到scripts中
-
3pytest的配置文件放在自动化项目目录下
-
4名称为pytest.ini
-
5命令行运行时会使用该配置文件中的配置
-
6第一行内容为
[pytest]
示例
-
[pytest]
# 告知系统该文件的例行 -
testpaths = ./case
# testpaths指定测试用例存放位置 -
addopts = -s
# 添加pytest命令选项 -
python_files = test*.py
# 指定测试脚本文件名前缀 -
python_classes = Test*
# 指定测试类名前缀 -
python_functions = test*
# 指定测试函数/测试方法名前缀
注意
-
1、在Windows系统下pytest配置文件中不允许写注释信息
-
2、一个工程内只需要一个
pytest.ini
配置文件并且需要保证文件名正确 -
3、一般情况只需要将 pytest.ini 配置文件 置于工程根目录下
-
4、配置有 pytest.ini 配置文件的工程只需要打开命令行输入 pytest 命令即可执行测试注意必须要cd切换到和配置文件同一级的目录下输入pytest
默认配置
-
说明测试用例文件名/测试类名/测试方法名均为
Test/test开头
没有配置文件的默认规则 -
代码
-
[pytest]
-
testpaths = ./case
-
addopts = -s
-
python_files = test*.py
-
python_classes = Test*
-
python_functions = test*
自定义规则
-
说明测试用例文件名/测试类名/测试方法名需要根据具体项目进行设置以下以Hm/hm为例
-
扩展指定单个文件/类/方法执行只需要在配置文件中写死即可
-
代码
-
[pytest]
-
testpaths = ./case
-
addopts = -s
-
python_files = hm*.py
-
python_classes = Hm*
-
python_functions = hm*
-
4.2 特殊方法
函数级别方法 setup
和teardown
介绍
-
场景:
-
pytest在运行自动化脚本的前后会执行两个特殊的方法分别setup和teardown。
-
在执行脚本之前会执行setup方法在执行脚本之后会执行teardown方法。
-
有了这两个方法我们可以在setup中进行获取驱动对象的操作在teardown中进行关闭驱动对象的操作。
-
-
说明特殊方法名写法固定没有代码提示需要手写。
代码格式
import pytest
class TestDemo(object):
"""测试示例类"""
def setup(self):
"""开始方法"""
print("方法 -> 开始")
def teardown(self):
"""结束方法"""
print("方法 -> 结束")
"""
举例函数级别 setup
、teardown
"""
import pytest
class TestDemo(object):
"""测试示例类"""
# 说明特殊方法名写法固定没有代码提示需要手写。
def setup(self):
"""开始方法"""
print("函数 -> 开始")
def teardown(self):
"""结束方法"""
print("函数 -> 结束")
def test_method1(self):
"""示例测试方法"""
print("测试方法1")
def test_method2(self):
"""示例测试方法"""
print("测试方法2")
if __name__ == '__main__':
pytest.main(['-s', 'hm05_pytest.py'])
类级别方法 setup_class
和teardown_class
介绍 运行于测试类的始末在一个测试内只运行一次setup_class和teardown_class不关心测试类内有多少个测试函数
代码格式
import pytest
class TestDemo(object):
"""测试示例类"""
def setup_class(self):
"""开始方法"""
print("类 -> 开始")
def teardown_class(self):
"""结束方法"""
print("类 -> 结束")
"""
举例类级别 setup_class
、teardown_class
"""
import pytest
class TestDemo(object):
"""测试示例类"""
# 说明特殊方法名写法固定没有代码提示需要手写。
def setup_class(self):
"""开始方法"""
print("类 -> 开始")
def teardown_class(self):
"""结束方法"""
print("类 -> 结束")
def test_method1(self):
"""示例测试方法"""
print("测试方法1")
def test_method2(self):
"""示例测试方法"""
print("测试方法2")
if __name__ == '__main__':
pytest.main(['-s', 'hm06_pytest.py'])
举例函数级别和类级别同时使用
"""
特殊方法函数级别和类级别同时使用
"""
import pytest
class TestDemo(object):
"""测试示例类"""
# 执行顺序1 ->3 ->5 ->4 ->3 ->6 ->4 ->2
def setup_class(self): # 1
print("类级别 ->> 开始")
def teardown_class(self): # 2
print("类级别 ->> 结束")
def setup(self): # 3
print("函数级别 -> 开始")
def teardown(self): # 4
print("函数级别 -> 结束")
def test_method1(self): # 5
"""示例测试方法"""
print("测试方法1")
def test_method2(self): # 6
"""示例测试方法"""
print("测试方法2")
if __name__ == '__main__':
pytest.main(['-s', 'hm07_pytest.py'])
4.3 执行顺序插件
介绍
-
场景现实生活中如果想下订单必须先登录我们可以通过插件的形式来控制函数执行的顺序。
-
安装
pip3 install pytest-ordering
-
使用
-
1标记于被测试函数
@pytest.mark.run(order=x)
-
2根据order传入的参数来解决运行顺序
-
3order值全为正数或全为负数时运行顺序值越小优先级越高
-
4正数和负数同时存在正数优先级高
-
5控制方法执行顺序对测试类同样有效使用方法一样
-
-
格式
@pytest.mark.run(order=x)
代码
"""
pytest 控制方法执行顺序插件
"""
import pytest
@pytest.mark.run(order=2)
class TestDemo1(object):
"""测试示例类"""
# 语法@pytest.mark.run(order=序号)
# 注意run(order=序号)没有代码提示需要手写
@pytest.mark.run(order=3)
def test_method1(self):
"""示例测试方法"""
print("测试方法1")
@pytest.mark.run(order=1)
def test_method2(self):
"""示例测试方法"""
print("测试方法2")
@pytest.mark.run(order=2)
def test_method3(self):
"""示例测试方法"""
print("测试方法3")
# 扩展序号支持正数和负数以及正负混合
# 1、纯正数数越小优先级越高【掌握】
# 2、纯负数数越小优先级越高【了解】
# 3、正负混合正数先按照顺序执行负数最后执行【了解】
# 注意控制方法执行顺序对测试类同样有效
@pytest.mark.run(order=1)
class TestDemo2(object):
"""测试示例类"""
def test_method(self):
"""示例测试方法"""
print("测试类2 -> 测试方法")
if __name__ == '__main__':
pytest.main(['-s', 'hm08_pytest.py'])
4.4 失败重试插件
介绍
-
场景自动化测试脚本可能会使用到网络如果网络不好可能最终会使脚本不通过。像这种情况可能并不是脚本本身的问题仅仅是因为网络忽快忽慢那么我们可以使用失败重试的插件当失败后尝试再次运行。一般情况最终成功可以视为成功但最好进行排查看是否是脚本问题。
-
安装
pip3 install pytest-rerunfailures
-
使用在配置文件中的命令行参数中增加
--reruns n
-
n
为失败重试几次 -
如
addopts = -s --html=./report/test_report.html --self-contained-html --reruns 3
-
-
说明
-
1正式脚本一般设置不超过3次测试脚本设置1次即可
-
2当脚本执行报错时会自动重新执行设置次数
-
-
格式
addopts = -s --reruns 3
代码 配置文件
-
[pytest]
-
testpaths = ./case
-
addopts = -s --reruns 3
-
python_files = test*.py
-
python_classes = Test*
-
python_functions = test*
4.5 跳过
介绍:
-
场景同一个软件在不同的设备上可能会有不同的效果比如iOS的3d touch操作是需要6s以上设备支持的6和6s都可以安装同一款应用如果设备不支持那根本没有必要去测试这个功能此时可以让这种函数进行跳过。
-
说明同样支持跳过测试类使用方式一样
-
格式
@pytest.mark.skipif(condition, reason=None)
-
在需要跳过的测试脚本之上加上装饰器
-
condition
跳过的条件必传参数 -
reason
标注原因必传参数 -
注意
reason=
不能省略否则会报错
-
代码
@pytest.mark.skipif(condition, reason='xxx')
"""
pytest 跳过测试
"""
import pytest
version = 25 # 模拟软件版本号
class TestDemo(object):
"""测试示例类"""
def test_method1(self):
"""示例测试方法"""
print("测试方法1")
# 注意reason= 不能省略否则会报错
@pytest.mark.skipif(version >= 25, reason='当前版本不执行')
def test_method2(self):
"""示例测试方法"""
print("测试方法2")
def test_method3(self):
"""示例测试方法"""
print("测试方法3")
# 说明同样可以跳过测试类
@pytest.mark.skipif(version >= 25, reason='当前版本不执行')
class TestDemo2(object):
"""测试示例类"""
def test_method(self):
"""示例测试方法"""
print("测试类2->测试方法")
if __name__ == '__main__':
pytest.main(['-s', 'hm09_pytest.py'])
4.6 断言
Python自带断言
-
预期相等
assert 1 == 1
-
预期包含
assert 'admin' in '欢迎 admin 归来'
代码
import pytest
def add_func(num1, num2):
"""加法函数"""
return num1 + num2
class TestDemo(object):
"""示例测试类"""
# 调用被测函数
result = add_func(1, 2)
# 断言判断结果
assert 3 == result
4.7 参数化
介绍
-
应用场景登录功能都是输入用户名输入密码点击登录。但登录的用户名和密码如果想测试多个值是没有办法用普通的操作实现的。数据参数化可以帮我实现这样的效果。
-
格式
@pytest.mark.parametrize(argnames, argvalues, indirect, ids=None, scope=None)
-
在需要参数化的测试脚本之上加上装饰器
-
argnames
参数名 -
argvalues
参数对应值类型必须为可迭代类型一般使用list
-
单个参数
-
介绍
-
1argnames为字符串类型根据需求决定合适的参数名
-
2argvalues为列表类型根据需求决定列表元素中的内容
-
3在测试脚本中参数名字与argnames保持一致
-
4在测试脚本中正常使用
-
-
格式
@pytest.mark.parametrize('参数变量', ['数值1', '数值2', ...])
-
代码
"""
pytest 参数化功能单个参数
"""
import pytest
class TestDemo(object):
"""示例测试类"""
# @pytest.mark.parametrize('参数变量', ['数值1', '数值2', ...])
@pytest.mark.parametrize('name', ['小米', '小新'])
def test_method1(self, name):
"""示例测试方法"""
print("获取的名字是", name)
if __name__ == '__main__':
pytest.main(['-s', 'hm10_pytest.py'])
多个参数
-
介绍
-
1多个参数必须置于同一个字符串内
-
2数据格式必须是
[(),()]
或者[[], []]
-
-
格式一
@pytest.mark.parametrize('参数1, 参数n', [('数值1-1', '数值2-2'), ('数值2-1', '数值2-2'), ...])
-
格式二
@pytest.mark.parametrize(('参数1', '参数n'), [('数值1-1', '数值2-2'), ('数值2-1', '数值2-2'), ...])
代码示例1
"""
pytest 参数化功能多个参数
"""
import pytest
class TestDemo(object):
"""示例测试类"""
@pytest.mark.parametrize('name, pwd', [('admin', 123456), ('test', 654321)])
def test_method1(self, name, pwd):
"""示例测试方法"""
print("账号{} 的秘密是{}".format(name, pwd))
if __name__ == '__main__':
pytest.main(['-s', 'hm11_pytest.py'])
代码示例2
import pytest
def build_test_data():
"""构造测试数据函数"""
# 中间代码略
return [('admin', 123456), ('test', 654321), ('xxx', 'yyy')]
class TestDemo(object):
"""示例测试类"""
# 通过方法引入数据pytest中必须带小括号
@pytest.mark.parametrize('name, pwd', build_test_data())
def test_method1(self, name, pwd):
"""示例测试方法"""
print("账号{} 的秘密是{}".format(name, pwd))
4.8 测试报告插件
介绍:
-
应用场景自动化测试脚本最终执行是通过还是不通过需要通过测试报告进行体现。
-
安装:
pip3 install pytest-html
-
使用:在配置文件中的命令行参数中增加
--html=用户路径/report.html
-
扩展在
--html
后面加上--self-contained-html
可以把CSS样式内嵌到html报告文件中防止分享报告时丢失样式 -
示例:
-
addopts = -s --html=./report/test_report.html
-
addopts = -s --html=./report/test_report.html --self-contained-html
-
-
格式
addopts = -s --html=./report/test_report.html --self-contained-html
代码 配置文件
-
[pytest]
-
testpaths = ./case
-
addopts = -s --html=./report/test_report.html --self-contained-html
-
python_files = test*.py
-
python_classes = Test*
-
python_functions = test*
4.9 PyTest框架运行UnitTest的TestCase
在配置文件中把python_files的名字修改为TestCase测试用例的文件名(xxx.py)即可。
4.10 总结
配置文件
-
位置
项目/pytest.ini
-
内容
-
[pytest]
-
testpaths = ./case
-
addopts = -s --html=./report/test_report.html --self-contained-html --reruns 3
-
python_files = test*.py
-
python_classes = Test*
-
python_functions = test*
-
【最后可能给予你助力的自动化教程】
最后感谢每一个认真阅读我文章的人看着粉丝一路的上涨和关注礼尚往来总是要有的虽然不是什么很值钱的东西如果你用得到的话可以直接拿走
面试资料
我们学习软件测试必然是为了找到高薪的工作下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料并且有阿里大佬给出了权威的解答刷完这一套面试资料相信大家都能找到满意的工作。
上面是我整理的配套资源这些资源对于软件测试的的朋友来说应该是最全面最完整的备战仓库为了更好地整理每个模块我也参考了很多网上的优质博文和项目力求不漏掉每一个知识点很多朋友靠着这些内容进行复习拿到了BATJ等大厂的offer这个仓库也已经帮助了很多的软件测试的学习者希望也能帮助到你。