Web自动化之Pytest测试框架
pytest是一个python的单元测试框架,可以用于自动化测试中。
用例规则
pytest命令执行测试时,如果我们不指定具体的文件,PyTest默认从当前路径及其所有子目录中搜索py源文件,所有名字以test_开头或者以_test结尾的python源文件(.py文件)被认为是测试模块源文件,不符合这个命名规则的文件会被忽略。
●测试类(class)命名:默认以“Test”开头。
对于Pytest框架代码,你可以不把测试用例放置到class中,而是直接定义函数
测试固件
函数中的测试固件
●setup_module、teardown_module,在整个文件的开始和最后执行一次。
●setup_function和teardown_function,在每个函数开始前后执行。
import pytest'''
在函数中使用
1.setup_module、teardown_module,在整个文件的开始和最后执行一次
2.setup_function和teardown_function,在每个函数开始前后执行
'''
def setup_module():print('setup_module')def teardown_module():print('teardown_module')def setup_function():print('setup_function')def teardown_function():print('teardown_function')def test_a():print('aaaa')assert 'a' == 'a'def test_b():print('bbbb')assert 'b' == 'b'if __name__ == '__main__':pytest.main(["-s", "test_string_process.py"])
输出
test_string_process.py setup_module
setup_function
aaaa
.teardown_function
setup_function
bbbb
.teardown_function
teardown_module
(2)class中的测试固件
●setup_class、teardown_class,在整个class的开始和最后执行一次。
●setup_method和teardown_method,在每个方法开始前后执行。
import pytest'''
在class中使用
1.setup_class、teardown_class,在整个class的开始和最后执行一次
2.setup_method和teardown_method,在每个方法开始前后执行
'''
class Test01():def setup_class(self):print('setup_class')def teardown_class(self):print('teardown_class')def setup_method(self):print('setup_method')def teardown_method(self):print('teardown_method')def test_a(self):print('aaaa')assert 'a' == 'a'def test_b(self):print('bbbb')assert 'b' == 'b'if __name__ == '__main__':pytest.main(["-s", "./test_11_4.py"])
输出
test_string_process.py setup_class
setup_method
aaaa
.teardown_method
setup_method
bbbb
.teardown_method
teardown_class============================== 2 passed in 0.02s ==============================
(3)setup和teardown
setup和teardown既可以应用在函数中,也可以应用在class中,作用对象是函数或方法。
import pytest
def setup_module():print('setup_module')def teardown_module():print('teardown_module')def setup():print('setup')def teardown():print('teardown')def test_a():print('aaaa')assert 'a' == 'a'def test_b():print('bbbb')assert 'b' == 'b'if __name__ == '__main__':pytest.main(["-s", "./test_11_5.py"])
输出
test_string_process.py setup_module
setup
aaaa
.teardown
setup
bbbb
.teardown
teardown_module
断言
断言(assert)并不是PyTest框架的功能特性,而是Python的内置语言特性,用于检查指定的表达式的结果是否为True。
PyTest使用assert来表达正确的测试逻辑期望。一个测试用例可以写多个断言,当有一个断言失败时,PyTest就认为测试的结果为失败,该测试用例的执行会被终止。
import pytest'''
pytest的断言更灵活
'''
class Test01():def setup_class(self):print('setup_class')def teardown_class(self):print('teardown_class')def setup_method(self):print('setup_method')def teardown_method(self):print('teardown_method')def test_a(self):print('aaaa')assert 5 > 3 # Python比较运算符def test_b(self):print('bbbb')assert 'Storm' in 'Hello Storm' # 成员运算符if __name__ == '__main__':pytest.main(["-s", "./test_11_8.py"])
测试执行
main函数
(1)执行同级和下级目录所有符合条件的测试使用pytest.main(["-s"])执行当前文件所在目录下所有符合条件的测试用例
import pytestdef test_b():print('bbbb')assert 'Storm' in 'Hello Storm'if __name__ == '__main__':pytest.main(["-s"])
.-s参数,关闭捕捉,输出信息。使用-v参数则不会在控制台输出信息。
(2)pytest.main(["-s", "test_11_10.py"])
在调试脚本的时候,如果我们希望脚本只执行当前文件,那么可以直接传递文件参数名
(3)pytest.main(["-s", "./test_11_11.py::Test02"])
在class风格的脚本中,调试的时候还可以通过在文件名后加两个冒号和class名来指定执行某个class。
命令窗口执行
(1)执行当前目录所有测试用例首先进入目标目录,然后直接执行“pytest”即可自动寻找当前目录下的测试用例
(2)执行指定的用例文件“pytest+文件名”用来执行指定用例文件
(3)执行指定的用例类我们可以通过“文件名+::+类名”的方式来执行指定的用例类
失败重跑
Pytest本身不支持测试用例执行失败重试的功能。我们需要安装一个插件——pytest rerunfailures。然后就可以通过“--reruns重试次数”来设置测试用例执行失败后的重试次数。
在命令行使用
pytest test_11_12.py --reruns 2 ---reruns-delay 2
表示重试两次,时间间隔为2秒
标记机制
Pytest提供了标记机制,借助“mark”关键字,我们可以对测试函数(类、方法)进行标记。
对测试用例进行分级,例如某些主流程的用例可以标记为L1,次要流程的用例标记为L2等。这样有一个好处,我们可以在不同的情况执行不同的测试用例,例如,在做冒烟测试的时候,只需要执行L1级别的用例就行了。
●一个测试函数(类、方法)可以有多个标记。
●一个标记也可以应用于多个函数(类、方法)。
●执行参数使用:pytest -m mark名。
●执行多个标记:pytest -m "L1 or L2"。
import pytestclass Test01():@pytest.mark.L1@pytest.mark.L2def test_a(self):print('aaaa')assert 'a' == 'a'@pytest.mark.L2def test_b(self):print('bbbb')assert 'b' == 'b'class Test02():@pytest.mark.L1def test_c(self):print('cccc')assert 'c' == 'c'@pytest.mark.L3def test_d(self):print('dddd')assert 'd' == 'd'
只执行L1级别
pytest -s "test_string_process.py" -m "L1"
执行L1和L2
pytest -s "test_string_process.py" -m "L1 or L2"
执行非L1
pytest -s "test_string_process.py" -m "not L1"
跳过用例
(1)使用skip(reason=None)实现无条件跳过
import pytestclass Test01():@pytest.mark.skip(reason='这里是原因')def test_a(self):print('aaaa')assert 'a' == 'a'def test_b(self):print('bbbb')assert 'b' == 'b'if __name__ == '__main__':pytest.main(["-s", "./test_11_14.py"])
(2)使用skipif(condition, reason=None)实现满足条件跳过
import pytestclass Test01():@pytest.mark.skipif(2>1, reason='这里是原因')def test_a(self):print('aaaa')assert 'a' == 'a'def test_b(self):print('bbbb')assert 'b' == 'b'if __name__ == '__main__':pytest.main(["-s", "./test_11_14.py"])
全局设置
前面我们介绍的配置信息要么是在文件的main方法中,要么是在命令行。这里我们还可以在测试目录下面创建一个pytest.ini文件,文件中可以设定一些执行规则,借助该文件可以修改Pytest的默认行为,即可以修改Pytest的执行规则。
然后,我们就可以将一些配置信息写入pytest.ini文件。这里需要注意以下3点。
●文件名必须是pytest.ini。
●文件内容必须以“[pytest]”开头。
●文件内容不能包含中文。
通过关键字“addopts”来设置命令行参数,如“-s”或“-v”监控、失败重试的次数、重试的时间间隔、按标签来执行,多个参数之间用空格分隔
将自定义标签添加到pytest.ini文件中。
自定义测试用例查找规则
●在当前文件目录中的testcases目录下查找测试用例:testpaths = testcases。
●查找文件名以“test_”开头的文件,也可以修改为以其他文件名开头:python_file =test_*.py。
●查找以“Test*”开头的类,也可以修改为以其他类名开头:python_classes =Test*。
●查找以“test_”开头的函数,也可以修改为以其他函数名开头:python_functions = test_*。
[pytest]
addopts = -v --reruns 2 --reruns-delay 2 -m "L1"
markers = L1:level_1 testcasesL2:level_2 testcases
testpaths = testcases
python_file = test_*.py
python_classes = Test*
python_functions = test_*
注意需要进入testcases文件夹的终端命令行输入pytest,既可以按照配置文件执行用例。
合理使用pytest.ini文件能方便地控制测试用例执行的情况。
测试报告
Pytest框架支持多种形式的测试报告。将分别介绍pytest-html和Allure两种测试报告
pytest-html
安装,安装好以后,我们只需要在执行“pytest”命令的时候指定--html参数。
pip install pytest-html
pytest --html=report.html
生成的html文件打开即为报告。
import pytestclass TestStorm1(object):@pytest.mark.L1def test_01(self):print('aaa')assert 'a'=='a'if __name__ == '__main__':pytest.main(["-s", "test_storm_1.py", "--html=./report.html"])
也可以将测试报告的配置项放到pytest.ini文件
allure测试报告
Allure基于Java开发,因此我们需要提前安装Java 8或以上版本的环境。
◆安装allure-pytest插件在DOS窗口输入命令“pip3 install allure-pytest”,然后按“Enter”键。
下载安装Allure:你可以从GitHub下载安装文件“allure2-2.13.3.zip”,解压后,将bin目录配置到环境变量中,然后在DOS窗口中输入“allure”,并按“Enter”键,如果显示“Usage”的话,说明设置成功。
使用如下命令执行:pytest.main(["-m","login","-s","-q","--alluredir=./report"])。
●“-m”:标记用例。
●“login”:被标记需要执行用例。
●“-s”:允许终端在测试执行时输出某些结果,例如你想输入print的内容,可以加上“-s”。
●“-q”:简化输出结果。
●“--alluredir”:生成Allure指定语法。
●“./report”:生成报告的目录。
●“--clean-alluredir”:因为这个插件库allure-pytest生成了报告文件,你第二次执行时不会清理掉里面的东西,所以你需要删除这个report文件夹,然后执行重新新建report文件夹命令。说明:命令执行后,程序会在report文件夹里面生成文件。
定制报告
●feature:标注主要功能模块。
●story:标注features功能模块下的分支功能。
●severity:标注测试用例的重要级别。
blocker级别:致命缺陷。critical级别:严重缺陷。normal级别:一般缺陷,默认为这个级别。minor级别:次要缺陷。trivial级别:轻微缺陷。
●step:标注测试用例的重要步骤。
●attach:用于向测试报告中输入一些附加的信息,通常是一些测试数据信息。
●name就是附件名称,body就是数据,attachment_type就是传类型。附件支持的类型有TEXT、HTML、XML、PNG、JPG、JSON、OTHER。
●issue:这里传的是一个连接,记录的是你的问题。
●testcase:这里传的是一个连接,记录的是你的用例。
●description:描述用例信息。
import pytest,allure@allure.feature("测试场景1") #标记场景
class TestDemo():@allure.story("测试用例1-1") # 标记测试用例@allure.severity("trivial") # 标记用例级别def test_1_1(self): # 用例1a = 1 + 1assert a == 2@allure.story("测试用例1-2")@allure.severity("critical")@allure.step('用例2:重要步骤')def test_1_2(self):assert 2 == 2
通过main来执行测试用例,这时候程序会在report文件夹中生成一些JSON格式的文件
接下来回到DOS窗口,执行“allure generate --clean report”命令,可以看到新生成了一个allure-report文件夹,可以用浏览器打开index.html文件了
●区域一:显示报告生成的时间,执行的时间,一共执行了多少个测试用例,环状图显示用例通过的比例。
●区域二:显示的是测试集合(class)情况。
●区域三:显示的是测试场景(@allure.feature)。
●区域四:显示失败用例的信息。
Pytest参数化
Pytest自身支持参数化,使用方法为@pytest.mark.parametrize("argnames",argvalues)。●argnames:参数名称,单个参数用参数名,多个参数可以拼接到一个元组中。
●argvalues:参数对应值,类型必须为可迭代类型,一般为列表。
from selenium import webdriver
import pytestdata = [('admin', 'error', '0'), ('admin', 'rootroot', '1')]
@pytest.mark.parametrize(("username", "password", "status"), data)
class TestLogin():def setup(self):self.driver = webdriver.Chrome()self.driver.maximize_window()self.driver.implicitly_wait(20)# 访问"登录"页面self.driver.get('http://localhost:81/redmine/login')def teardown(self):self.driver.quit()def test_001_login(self, username, password, status):# 登录名login_name = self.driver.find_element_by_id('username')login_name.clear()login_name.send_keys(username)# 登录密码login_pwd = self.driver.find_element_by_id('password')login_pwd.clear()login_pwd.send_keys(password)# "登录"按钮login_btn = self.driver.find_element_by_id('login-submit')login_btn.click()if status == '0':# 登录失败后的提示信息ele = self.driver.find_element_by_id('flash_error')assert '无效的用户名或密码' in self.driver.page_sourceelif status == '1':# 登录后显示的用户名name = self.driver.find_element_by_link_text(username)assert name.text == usernameelse:print('参数化的状态只能传入0或1')if __name__ == '__main__':pytest.main(['-s', '-q', '--alluredir', './report/'])
Web自动化之Pytest测试框架相关推荐
- websocket接口自动化集成pytest测试框架详解
目录 websocket协议 1.介绍 2.原理 3.与http协议的比较 4.websocket应用场景 自动化测试资源分享 websocket协议 1.介绍 WebSocket是一种在单个TCP通 ...
- websocket接口自动化集成pytest测试框架
01.websocket协议 1.介绍 WebSocket是一种在单个TCP通信的协议.WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范.WebSo ...
- Pytest 测试框架——数据驱动
引言 前面已经和大家介绍过 Unittest 测试框架的数据驱动框架 DDT,以及其实现原理.今天和大家分享的是 Pytest 测试框架的数据驱动,Pytest 测试框架的数据驱动是由 pytest ...
- Pytest测试框架(五):pytest + allure生成测试报告
系列文章目录 Pytest测试框架(一):pytest安装及用例执行 Pytest测试框架(二):pytest 的setup/teardown方法 Pytest测试框架(三):pytest fixtu ...
- Pytest测试框架(二):pytest 的setup/teardown方法
系列文章目录 Pytest测试框架(一):pytest安装及用例执行 Pytest测试框架(二):pytest 的setup/teardown方法 Pytest测试框架(三):pytest fixtu ...
- Python编程必不可少的pytest测试框架
进行编程测试重要的是为了更高效的完成功能的实现. pytest是基于unittest实现的第三方测试框架,比 unittest 更加的简洁.高效,并且可以完美兼容 unittest 的测试代码,无需对 ...
- WEB自动化-(RFS)RobotFramework+Selenium框架介绍测试流程详解
各个驱动下载地址: http://www.seleniumhq.org/download/ 一.RFS介绍 1.概念 RFS框架:RobotFramework+Selenium框架 2.特点 2.1通 ...
- 自动化测试 —— Pytest测试框架
01 | 简介 Pytest是一个非常成熟的全功能的Python测试框架,主要有以下特点: 简单灵活,容易上手,文档丰富 支持参数化,可以细粒度地控制测试用例 支持简单的单元测试与复杂的功能测试,还可 ...
- pytest测试框架——allure报告
文章目录 一.allure的介绍 二.allure的运行方式 三.allure报告的生成 方式一.在线报告.会直接打开默认浏览器展示当前报告 方式二.静态资源文件报告(带index.html.css. ...
最新文章
- 刘炽平:腾讯要以生态方式进行开放,不做“颠覆者”
- 和平精英为什么找不到服务器,和平精英为什么登不上去 和平精英游戏登不上原因分析...
- django-celery
- 好的自我介绍,面试成功一大半
- 2 操作系统第一章 操作系统体系结构、中断和异常、系统调用
- awk工具的简单使用
- 如何选择一个Linux发行版本
- 数据抽取工具比对:Kettle、Datax、Sqoop、StreamSets
- 打造AS酷炫dimens适配插件
- connection对象的参数
- 关于websocket兼容IE版本
- Android Q共享音频输入
- Matlab 函数文件简介
- MIDI 文件格式解析举例
- 通过Unity预编译文件smcs.rsp文件添加预编译命令
- 堆排序(排升序为啥建大堆,排降序为啥建小堆)
- 怎样用计算机计算工程量,送给用EXCEL计算工程量的朋友们一个好方法
- jsp+servlet搭建在线投票问卷系统
- Women in Tech | 关于职业与成长,她们给人奋进的启发和动力
- Android 万能遥控 开源,快速实现WIFI红外遥控器(ESP8266 SoC模式)
热门文章
- Proximal Policy Optimization Algorithms翻译
- 触控设备手势唤醒的设计思路及其实现
- paramiko的安装
- 微机原理七种寻址方式
- C/C++ 由int (*p)[5]与int *p[5]引发的学习与思考
- 白光干涉仪在微透镜阵列微观三维形貌测量中的作用
- BT面板创建站点显示已存在问题解决
- 基于flask构建微服基本demo
- [SV] ignore_bins 用法
- 行人reid ,多个开源地址数据变成 market1501格式合并,附代码,数据地址