2024年搭配实战细讲Pytest--为后续UI测试封装打基础--值得收藏,一个月成功收割腾讯、百度、美团、网易offer

img
img

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

需要这份系统化的资料的朋友,可以戳这里获取

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

def test002():

print(‘这是一条最优级别的用例’)

def test005():

print(“skip_reason”)

def test003():

print(‘这是一条严重级别的用例’)

def test006():

print(“006冒烟”)

def test004():

print(‘这是一条较严重级别的用例’)

上述例子的情况下,与正常情况下无异,这里需要注意:

pytest与unittest不一样,我test序列号写的很乱,如果是在unittest中的话肯定就是按数字的顺序来执行了,pytest中不分先后,05在04用例的前面,那么就得按这顺序来,先运行05用例再04用例。

那么我们给这里加上mark标签看看:

def test002():

print(‘这是一条最优级别的用例’)

def test005():

print(“005冒烟”)

@pytest.mark.qingan

def test003():

print(‘这是一条严重级别的用例’)

def test006():

print(“006冒烟”)

@pytest.mark.qinganan

def test004():

print(‘这是一条较严重级别的用例’)

猜猜这里运行几条用例?3条,没错。

注意:这里mark标签是外置标签,我自己命名的。看看运行结果:

pytest -m qingan test_speack.py -sv这里指定外置标签的标签名。不指定就会运行全部的用例,不指定怎么对用例进行管理。

这里还是可以看到只执行了两条,也就是标签的那两条用例。这里对指定用例进行标记运行。

mark标签会受外界的装饰器影响吗?我们来看看。

def func(function):

def fn(*args,**kwargs):

print("this is "+function.name)

return function(*args,**kwargs)

return fn

----------上面是自己写的装饰器--------------

@func

def test002():

print(‘这是一条最优级别的用例’)

@pytest.mark.skip

def test005():

print(“skip_reason”)

@pytest.mark.qingan

@func

def test003():

print(‘这是一条严重级别的用例’)

def test006():

print(“006冒烟”)

@pytest.mark.qingan

@func

def test004():

print(‘这是一条较严重级别的用例’)

是不会的,也是遵循pytest强大的执行顺序来的。

那么看了自定义标签,看看内置标签吧:

def func(function):

def fn(*args,**kwargs):

print("this is "+function.name)

return function(*args,**kwargs)

return fn

----------上面是自己写的装饰器--------------

@func

def test002():

print(‘这是一条最优级别的用例’)

@pytest.mark.skip

def test005():

print(“skip_reason”)

@pytest.mark.qingan

@func

def test003():

print(‘这是一条严重级别的用例’)

def test006():

print(“006冒烟”)

@pytest.mark.qingan

@func

def test004():

print(‘这是一条较严重级别的用例’)

我在05用例处添加了一个内置标签,这里需要注意的是,执行命令不一样:

pytest test_speack.py -s -rs或者pytest -k qingan test_speack.py -sv

05被跳过了,我们可以更改内置标签的提示信息

@pytest.mark.skip(reason=‘不运行’)

def test005():

print(“skip_reason”)

控制台就会有这样的一条信息可以看到。

这里可以看到自定义标签与内置标签处用的运行命令有所不同,不同之处在于一个用了-m一个用了-k。

使用-m的时候我们需要指定自定义标签,才能跑用例,否则跑不起来,如果用-k即使不指定也是可以跑起来,这样的一个好处,相信不说你也知道了,控制用例执行,可以更好的执行你想执行的用例。更好的是用于冒烟测试。

另外还有一个也就是内置标签判断,skipif。这是一个怎么样的标签呢?

看skip后面带的if就知道了,可以做一个判断!条件为真则跳过运行,条件为假则运行用例。

@func

def test002():

print(‘这是一条最优级别的用例’)

@pytest.mark.skipif(1>2,reason=‘不运行’)

def test005():

print(“skip_reason”)

@pytest.mark.qingan

@func

def test003():

print(‘这是一条严重级别的用例’)

def test006():

print(“006冒烟”)

@pytest.mark.qingan

@func

def test004():

print(‘这是一条较严重级别的用例’)

pytest -k test_speack.py -sv我在用例005处写了一个skipif的判断,1>2是FALSE,所以此处不跳过。

所以此处为真的条件就不举例了,此处直接告诉各位答案了。


前置后置

====

在unittest你肯定看到过setup这一类的函数,看下面的例子

class Testcasse():

“”“前置后置”“”

def setup(self):

print(“1每个用例的前置”)

def teardown(self):

print(“2每个用例的后置”)

def setup_class(self):

print(“3所有用例的前置”)

def teardown_class(self):

print(“4所有用例的后置”)

def test_004(self):

print(“004”)

def test_005(self):

print(“005”)

其中的顺序是怎么样的呢。是否跟之前说的全部无优先级呢?运行一下就知道了。

这里就很明显了,优先级是3124,这里别误会,我在print里面加了数字,说一 这里就这样简写了。下面两个用例004,005是用于分辨的,不然运行不起来。各位可以自己跑一跑。这与pytest本身的规则有关系。


fixture

=======

这里很容易弄错写成fixtrue,所以需要注意一些。怎么用呢?fixture可以实现我们在pytest的用例中调佣其他函数,可以发现我们使用fixture是在被调用函数之上添加我们的fixture。看例子:

@pytest.fixture

def login():

print(“login”)

return “运行用例”

def test_seacher():

print(login) # 返回的是一个地址

print(f"搜索用户名{login}")

def test_seacher1(login):

print(login)

print(f"搜索用户名{login}")

pytest text_fixtrue.py -sv运行起来看看效果:

这样看就不难理解了。这是一种简单的距离,看起来像是调用。

fixture区别于unnitest的传统单元测试(setup/teardown)有显著改进。

fixture里面有个scope参数可以控制fixture的作用范围:session>module>class>function

-function:每一个函数或方法都会调用

-class:每一个类调用一次,一个类中可以有多个方法

-module:每一个.py文件调用一次,该文件内又有多个function和class

-session:是多个文件调用一次,可以跨.py文件调用,每个.py文件就是module

这里就需要用到了conftest.py配置了。可以实现数据共享,比如py跨文件共享前置,另外需要注意的是conftest.py脚本名称是固定的,不更改名称。pytest会自动寻找这个文件。

如果此文件放到项目的根目录下就可以全局调用了,如果放到某个package下,那就在改package内有效。

在根目录下这是conftest下的内容:

@pytest.fixture(scope=‘function’)

def openbrowser():

print(“打开浏览器”)

@pytest.fixture(scope=‘session’)

def qingan():

print(“我是清安”)

这是某个文件内的demo下的内容,主要看Testcase中的内容:

@pytest.fixture(scope=‘session’)

def login():

print(“登录方法”)

return “浏览器”

此处当scope等于function时,yield可以作用于全局

yield “类似于teardown,用法可以跟return一样”

def testSQL(login):

print(“链接数据库”)

print(login)

return “数据库连接结果”

@pytest.fixture()

def test01(login):

print(“用例1”)

class Testcase():

def test02(self,openbrowser):

print(“用例2”)

def test03(self,qingan):

print(“用例3”)

我调用了conftest下的function跟session参数方法。

这里可以看到,都被调用了。当然方法不唯一,用法不唯一,这里做这么一个简单的介绍,主要看各位怎么个用法。module也可以这样写。

接下来我们来看看实际的示例,我打开浏览器:demo.py文件

from selenium import webdriver

这里每次都需要打开一次浏览器,然后关闭再打开

@pytest.fixture

def fox():

fox1 = webdriver.Firefox()

print(“login”)

return fox1

def test_seacher(fox):

fox.get(“https://baidu.com”)

fox.quit()

def test_seacher1(fox):

fox.find_element_by_id(‘kw’).send_keys(“pytest”)

fox.find_element_by_id(‘su’).click()

fox.quit()

这里是单独的fixture直接同一文件下调用。打开两开浏览器,有点像unittest中的setup用法。这里的test_seacher1`又再次打开了一次浏览器导致不是百度界面无法定位到元素。

那么我们看看session怎么用------conftest.py文件

import pytest

from selenium import webdriver

@pytest.fixture(scope=‘session’)

def fox():

fox = webdriver.Firefox()

yield fox

demo.py文件

@pytest.mark.usefixtures(‘fox’)

class TestCase():

def test01(self,fox):

fox.get(“https://baidu.com”)

print(fox.title)

def test02(self,fox):

fox.find_element_by_id(‘kw’).send_keys(“pytest”)

fox.find_element_by_id(‘su’).click()

def test03(self,fox):

fox.quit()

这里用到了mark标签中的usefixtures方法,不用解释应该也知道了有use的地方是什么意思了吧,使用fixture方法,这里直接引入了conftest中的fox,只打开一次浏览器就能往下定位了。是不是很神奇。当然,module也是用在conftest里面。


参数化

===

有点像数据驱动,可以处理一些测试数据,简单的看看它的一个格式情况:

argnames:参数名

argvalues:参数对应值,类型必须为list

datas = [(‘qingan’, ‘123’),(‘qingqingan’, ‘123456’)]

class TestQingan:

@pytest.mark.parametrize(argnames=[‘username’, ‘password’], argvalues=datas)

def testqing01(self, username, password):

这里的运行两个用例

print(“处处把欢喜”)

print(username, password)

这里会把datas中的数据解析出来:列表中有几个元组就有几个对应的数据。

当然,还有一种情况就是会随机匹配对应的数值,说的比较抽象我们直接看看:

class TestQingan:

@pytest.mark.parametrize(“username”,[“qingan”,“123456”])

@pytest.mark.parametrize(“password”,[“qingqingan”,“123456”])

def testqing01(self, username, password):

这里的运行两个用例

print(“处处把欢喜”)

print(username, password)

如果你这样写了,那么pytest会把username跟password中的列表打乱,然后一一匹配:


命名

===

不知道你是否喜欢pytest的命名规则,如果不喜欢,此处有一好办法,帮你解决。

跟目录下创建一个pytest.ini文件,在里面这样写。pytest会自动去识别。往下看会解释规则

[pytest]

addopts= -s -vv --alluredir=./result/xml

testpaths=…/P_pytest/inidemo

python_files=test*.py

python_classes=Qing*

python_functions=qing*

以我上述的例子为例题运行出来的效果也与上述没有太大的差别,只是更改了名字而已:

class Qingan:

@pytest.mark.parametrize(“username”,[“qingan”,“123456”])

@pytest.mark.parametrize(“password”,[“qingqingan”,“123456”])

def qing01(self, username, password):

img
img

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

需要这份系统化的资料的朋友,可以戳这里获取

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

此处有一好办法,帮你解决。

跟目录下创建一个pytest.ini文件,在里面这样写。pytest会自动去识别。往下看会解释规则

[pytest]

addopts= -s -vv --alluredir=./result/xml

testpaths=…/P_pytest/inidemo

python_files=test*.py

python_classes=Qing*

python_functions=qing*

以我上述的例子为例题运行出来的效果也与上述没有太大的差别,只是更改了名字而已:

class Qingan:

@pytest.mark.parametrize(“username”,[“qingan”,“123456”])

@pytest.mark.parametrize(“password”,[“qingqingan”,“123456”])

def qing01(self, username, password):

[外链图片转存中…(img-UK1SKdVI-1715119923891)]
[外链图片转存中…(img-k0iuVJs6-1715119923892)]

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

需要这份系统化的资料的朋友,可以戳这里获取

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

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值