一篇文章带你了解Python常用自动化测试框架 —— Pytest_python自动化框架怎么看

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新软件测试全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注软件测试)
img

正文

-k: 运行测试用例名称中包含某个字符串的测试用例,我们可以采用or表示或者,采用and表示都

采用or就表示:我们的运行用例名称中包含or两侧的其中一个数据即可

采用and就表示:我们的运行用例名称中包含and两侧的所有数据才满足条件

pytest -vs -k “qiuluo”
pytest -vs -k “qiuluo or weiliang”
pytest -vs -k “qiuluo and weiliang”

-m:冒烟用例执行,后面需要跟一个冒烟名称

我们在这里简单介绍一下冒烟用例的执行方法,我们这里其实就是一个分组执行的方法

例如我们的用例划分为user_manage用户管理测试和product_manage商品管理测试,我们只希望执行其中一组测试

首先我们需要在他们的不同方法上进行@mark划分,具体操作如下:

class TestDemo:

我们在Case上采用@pytest.mark. + 分组名称,就相当于该方法被划分为该分组中

注意:一个分组可以有多个方法,一个方法也可以被划分到多个分组中

@pytest.mark.user_manage
def test_demo1(self):
print(“user_manage_test1”)

@pytest.mark.product_manage
def test_demo2(self):
print(“product_manage_test1”)

@pytest.mark.user_manage
@pytest.mark.product_manage
def test_demo3(self):
print(“manage_test1”)

我们在执行中只需要采用前面我们所说的-m + 分组名称即可

pytest -vs -m user_manage

这里插一句,我们在运行过程中可以采用抛出异常的方式来模拟测试失败:raise Exception() 抛出异常

最后我们也可以采用main方法来执行pytest,同样我们也可以使用参数来进行调节

if name == ‘main’:
pytest.main()

if name == ‘main’:
pytest.main([“‐vs”])

最后我们插入一个简单的案例跳过方法:

pytest的跳过案例方法其实和unittest是完全相同的

我们只需要采用skip或skipif方法来指定参数并贴在方法上即可跳过

@pytest.mark.skip(跳过原因)

@pytest.mark.skipif(跳过条件,跳过原因)

我们给出一个示例

class TestDemo:

workage2 = 5
workage3 = 20

@pytest.mark.skip(reason=“无理由跳过”)
def test_demo1(self):
print(“我被跳过了”)

@pytest.mark.skipif(workage2<10,reason=“工作经验少于10年跳过”)
def test_demo2(self):
print(“由于经验不足,我被跳过了”)

@pytest.mark.skipif(workage3<10,reason=“工作经验少于10年跳过”)
def test_demo3(self):
print(“由于经验过关,我被执行了”)

def test_demo3(self):
print(“我没有跳过条件,所以我被执行了”)

Pytest前后置方法

首先我们需要先了解前后置是什么:

  • 前后置就是针对不同层级方法执行前和执行后所需要执行的步骤进行封装并执行
  • 这个层级通常被划分为:文件层,类层,方法层

首先我们先来介绍Pytest通过固件来实现前后置的方法:

我们通常采用前后置来做一些方法前后的操作

如果我们采用方法层的前后置,那么它会在每个方法执行前后去执行该内容

如果我们采用类层的前后置,那么它会在调用这个类内所有方法的前后去执行该内容,但是无论该类的方法执行多少次,它只会调用一次

例如我们做login测试时,我们只需要在开始测试时打开一次浏览器,然后在测试结束时关闭一次浏览器,那么我们就采用类的前后置

我们做login测试时,为了保证前置操作不对后续Case有影响,所以我们在执行方法前打开该网页,执行方法后关闭该网页,采用方法的前后置

Pytest的固件前后置其实和unittest是基本相同的

首先是方法级别的固件前后置

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

方法执行之前

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

方法执行之后

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

然后是针对类级别的固件前后置

它是在每个测试类中所有方法执行前后 都会自动调用的结构(在整个类中执行之前或之后执行一次)

需要注意:类级别的固件前后置, 是一个类方法

类中所有方法之前

@classmethod
def setUpClass(cls):
pass

类中所有方法之后

@classmethod
def tearDownClass(cls):
pass

最后是针对模块级别的固件前后置

在每个代码文件执行前后执行的代码结构

需要注意:模块级别的需要写在类的外边直接定义函数即可

代码文件之前

def setUpModule():
pass

代码文件之后

def tearDownModule():
pass

下面我们采用一个用户账户登录的用例来简单展示一下固件前后置

import unittest

class TestLogin(unittest.TestCase):

在执行该类前所需要调用的方法

@classmethod
def setUpClass(cls) -> None:
print(‘------打开浏览器’)

在执行该类后所需要调用的方法

@classmethod
def tearDownClass(cls) -> None:
print(‘------关闭浏览器’)

每个测试方法执行之前都会先调用的方法

def setUp(self):
print(‘输入网址…’)

每个测试方法执行之后都会调用的方法

def tearDown(self) -> None:
print(‘关闭当前页面…’)

测试Case1

def test_1(self):
print(‘输入正确用户名密码验证码,点击登录 1’)

测试Case2

def test_2(self):
print(‘输入错误用户名密码验证码,点击登录 2’)

然后我们还需要讲解一下Fixtrue实现前后置的方法:

首先我们需要知道Fixtrue所实现的功能基本和固件所实现的功能是一样的,但是会更加方便

首先我们给出Fixture的完整格式,然后我们再分开介绍各个参数

@pytest.fixture(scope=None,autouse=False,params=None,ids=None ,name=None)

scope:作用范围

参数主要有三种:function函数,class类,package/session包

function:在函数层面上执行前后置

我们通常采用yield进行前后置划分,yield前是前置,yield后是后置

@pytest.fixture(scope=“function”)
def exe_database_sql():
print(“执行SQL查询”)
yield
print(“关闭数据库连接”)

我们还可以通过yield或return去返回一些参数在方法中使用

但是需要注意,yield返回参数后后置仍旧可以执行,但是return返回参数后后置操作无法执行

@pytest.fixture(scope=“function”)
def exe_database_sql():
print(“执行SQL查询”)
yield “success”

return “success” 执行后无法执行后置操作

print(“关闭数据库连接”)

我们的方法在调用时,可以直接使用exe_database_sql表示返回信息进行输出

def test_2(self,exe_database_sql):
print(exe_database_sql)

class:在类之前和之后执行

@pytest.fixture(scope=“class”)
def exe_database_sql():
print(“执行SQL查询”)
yield
print(“关闭数据库连接”)

package/session:在整个项目会话之前和之后执行

@pytest.fixture(scope=“session”)
def exe_database_sql():
print(“执行SQL查询”)
yield
print(“关闭数据库连接”)

autouse:是否自动启动

该参数默认为False,我们可以将其修改为True

该参数的功能主要在判断该固件是否在自定义范围内可以自动启动

若自动启动,则所有方法在执行时都会自动执行该前后置;但若为False,则我们需要手动启动

首先如果是自动启动,则我们无需关心任何参数,我们的所有方法都会自动调用

@pytest.fixture(scope=“function”,autoues=True)
def exe_database_sql():
print(“执行SQL查询”)
yield
print(“关闭数据库连接”)

但若是关闭自动启动,我们在不同的scope下有不同的调用方法

@pytest.fixture(scope=“function”,autoues=Flase)
def exe_database_sql():
print(“执行SQL查询”)
yield
print(“关闭数据库连接”)

scope = function:我们需要在方法后加上该Fixture方法名

def test_2(self,exe_database_sql):
print(exe_database_sql)

scope = class:我们需要在对应的类上添加@pytest.mark.usefixtures(“exe_database_sql”)装饰器调用

@pytest.mark.usefixtures(“exe_database_sql”)
class TestDemo:
pass

scope = session:.一般会结合conftest.py文件来实现,我们后面再介绍

还需要注意autouse仅限于在自己的类中使用上述方法,如果要跨类使用,那么我们也需要在conftest.py中配置

params:实现参数化配置

通常我们的脚本都是根据导出的yaml文件进行属性填充,针对参数化我们后面再讲,我们先将Fixture的参数化

params通常后面跟上具体的数据(列表,元组等),然后我们在调用时有固定的写法

首先我们需要在Fixture方法参数中定义一个request,然后使用request.param来使用我们传递的params数据

class TestDemo:
def read_yaml():
return [“胡桃”,“胡桃宝宝”,“胡桃厨”]

首先我们的参数需要获取数据:params=read_yaml()

@pytest.fixture(scope=“function”,autouse=False,params=read_yaml())

然后我们的Fixture方法需要一个request参数

def exe_database_sql(request):
print(“执行SQL查询”)

我们通过request.param获取数据,可以采用yield返回该数据

yield request.param
print(“关闭数据库连接”)

ids:参数别名id

不能单独使用,必须和params一起使用,作用是对参数起别名

我们在采用pytest进行测试数据输出时会有对应的方法调用n次,该n次采用不同的params参数,这个ids就是修改了console控制台展示数据

class TestDemo:
def read_yaml():
return [“胡桃”,“胡桃宝宝”,“胡桃厨”]

当我们书写了ids,我们的控制输出就不会再是上面的[“胡桃”,“胡桃宝宝”,“胡桃厨”],而是我们所书写的[“1”,“2”,“3”]

@pytest.fixture(scope=“function”,autouse=False,params=read_yaml(),ids=[“1”,“2”,“3”])
def exe_database_sql(request):
print(“执行SQL查询”)

我们通过request.param获取数据,可以采用yield返回该数据

yield request.param
print(“关闭数据库连接”)

name:Fixture别名

作用是给fixtrue起别名,一旦使用了别名,那么fixtrue的名称就不能再用了,只能用别名

class TestDemo:

如果我们在这里使用到了别名

@pytest.fixture(scope=“function”,name=“exe_datebase_sql_name”)
def exe_database_sql(request):
print(“执行SQL查询”)
yield
print(“关闭数据库连接”)

我们这里就需要使用别名进行操作,之前的名称无法使用

def test_2(self,exe_datebase_sql_name):
print(exe_database_sql)

接下来我们就将会讲解到我们刚刚提到的conftest.py文件:

首先我们需要知道conftest.py文件的名字是固定形式,不可改变

conftest.py文件主要就是用来存储我们的Fixture,然后我们会根据该文件的不同位置来判断可以使用的方法

conftest可以在不同的目录级别下创建,如果我们在根目录下创建,那么所有case都会使用到该Fixture

但是如果我们在testcases文件夹下的某个模块文件下创建conftest.py,那么它的作用范围就只包含在该目录下

根目录创建的conftest.py

我们在该目录下的conftest文件里写的所有fixture可以在任意测试类下执行

import pytest
@pytest.fixture(scope=“function”,name=“exe_datebase_sql_name”)
def exe_database_sql():
print(“全部方法运行前均可以执行”)
yield
print(“全部方法运行后均可以执行”)

testcases文件下的所有测试类

这里需要注意:我们使用conftest下的Fixture时,不需要import导包就可以使用

import pytest
class TestDemo1:

测试Case1

def test_1(self,exe_datebase_sql_name):
print(‘输入正确用户名密码验证码,点击登录 1’ + exe_datebase_sql_name)

testcases文件夹下的usercases文件夹下创建的conftest.py

我们在该目录下创建的conftest文件里写的所有fixture仅可以在该目录下的测试类中使用,在其他测试类中使用会出现报错

import pytest
@pytest.fixture(scope=“function”,name=“usercases_fixture”)
def exe_database_sql():
print(“usercases方法运行前均可以执行”)
yield
print(“usercases方法运行后均可以执行”)

testcases文件下的usercases文件夹下的测试类

import pytest
class TestUserCases1:

测试Case1

def test_1(self,usercases_fixture):
print(‘输入正确用户名密码验证码,点击登录 1’ + usercases_fixture)

最后我们简单给出一个前后置执行顺序优先级:

fixture_session > fixture_class > setup_class > fixture_function > setup

然后最后我们给出前后置执行的一个总体逻辑顺序:

  • 查询当前目录下的conftest.py文件
  • 查询当前目录下的pytest.ini文件并找到测试用例的位置
  • 查询用例目录下的conftest.py文件
  • 查询测试用例的py文件中是否有setup,teardown,setup_class,teardown_class
  • 再根据pytest.ini文件的测试用例的规则去查找用例并执行

Pytest进阶内容

最后我们再来讲解一些pytest比较关键性的一些进阶内容

Allure效果美化

我们在使用Pytest所生成的页面往往不够美观且展示信息杂乱不好分析,所以我们通常搭载allure来实现界面美化:

  • Allure框架是一个灵活轻量级多语言测试报告工具
  • 它不仅可以以WEB的方式展示简介的测试结果,而且允许参与开发过程的每个人从日常执行的测试中最大限度的提取有用信息

下面我们就来学习如何安装使用allure:

首先我们需要去下载在电脑上下载allure并配置好环境变量

我们这里给出官网下载地址:https://github.com/allure-framework/allure2/releases

温馨提醒:下载链接在github上,如果无法打开可以刷新重试或者使用加速器梯子等辅助工具

环境变量的配置只需要将bin文件所在目录放在电脑的Path路径下即可,这里不再展示

第二步我们需要在pycharm上下载allure-pytest插件(如果之前pip了那个整体文件,这里应该是已经下载过了)

pip install allure-pytest

第三步我们就可以直接来生成allure的测试结果展示界面了

1.我们通常首先需要生成一个allure临时Json文件

我们通常会加上这么一串"‐‐alluredir=./temps ‐‐clean‐alluredir"

‐‐alluredir = 文件生成地址 : 表示我们将allure临时文件生成在我们所指定的相对临时目录下

‐‐clean‐alluredir : 由于每次都会生成大量文件,所以我们会在生成前清除当前目录下的allure文件,保证我们数据都是最新数据

2.我们需要依靠临时文件来生成allure.html网页

我们通常在main方法中执行

if name == ‘main’:

正常运行

pytest.main()

休眠:主要为了JSON临时文件的生成

time.sleep(3)

allure generate 固定语句 + allure临时JSON文件目录 + -o 输出指令 + allure.html生成文件目录 + --clean 清除旧数据

os.system(“allure generate ./temps ‐o ./reports ‐‐clean”)

Parametrize数据驱动

我们通常会采用Parametrize注解来进行数据驱动,下面我们来详细讲解一下:

格式:@pytest.mark.parametrize(参数名称,参数值)

意义:我们会将参数名称作为id,然后根据参数值的个数去依次调用,存在n个参数值,我们将会调用n次case

1.参数值为列表或元组时,参数名称可以为一个

首先我们这里因为使用单个元素的列表(元组),我们的参数名可以为一个

@pytest.mark.parametrize(‘caseinfo’,[‘胡桃’,‘胡桃宝宝’,‘芙芙’,‘芙芙宝宝’])

在方法参数里,我们需要调用parametrize的参数名称caseinfo,需要保证一模一样

def test_01_get_token(self,caseinfo):

在这里我们可以借助参数名称caseinfo来代替列表中的元素

列表中存在几个,我们该方法将执行几次,例如现在列表是四个元素,那么我们方法将会重复执行四次并每次按顺序赋值不同的元素

print(“获取统一接口鉴权码:”+caseinfo)

2.参数值为列表的多个时,参数名称可以为多个

这里我们列表中嵌套了一个列表,如果我们是单参数名称,那么输出时就会将第一个列表[‘胡桃厨’,‘胡桃宝宝’]输出出去

但是如果我们是多参数名称,系统会自动将第一个列表的元素分开赋值给arg1,arg2便于我们分开使用,个人还是比较推荐的

@pytest.mark.parametrize(‘arg1,arg2’,[[‘胡桃厨’,‘胡桃宝宝’],[‘芙芙厨’,‘芙芙宝宝’]])

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

这里我们列表中嵌套了一个列表,如果我们是单参数名称,那么输出时就会将第一个列表[‘胡桃厨’,‘胡桃宝宝’]输出出去

但是如果我们是多参数名称,系统会自动将第一个列表的元素分开赋值给arg1,arg2便于我们分开使用,个人还是比较推荐的

@pytest.mark.parametrize(‘arg1,arg2’,[[‘胡桃厨’,‘胡桃宝宝’],[‘芙芙厨’,‘芙芙宝宝’]])

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注软件测试)
[外链图片转存中…(img-bU0ItvYd-1713449597226)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 29
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值