zl程序教程

您现在的位置是:首页 >  Java

当前栏目

测试之路 pytest接口自动化框架-插件补充及pytest装饰器扩展

2023-02-18 16:23:13 时间

哈喽大家好,我是歪小王,本期继续分享pytest学习笔记。本期主要是pytest的常用插件补充以及pytest常用装饰器

01 上期回顾

上期内容主要围绕pytest配置文件进行阐述,其中包括命令行参数、失败重试、生成html版本的测试报告、分组以及文件路径设置、运行顺序等。本期就上期内容进行一点补充。

上期我们说到pytest的运行方式是由上至下的线性运行方式,那在日常工作中。有些用例是要优先执行的,在我们写完用例后,才发现这些前置用例写在了用例队列中的后几行,这个时候就可以使用pytest中控制排序方法进行排序。使用方法如下

安装pip install pytest-ordering 进行安装 使用装饰器在需要控制顺序的函数上增加这个装饰器即可

@pytest.mark.run(order = x)
def test_login(self):....
# 优先级:0 > 较小的正数 > 较大的正数 > 空 > 较小的负数 > 较大的负数

分布式执行:

当我们将所有的⾃动化测试⽤例都编写完成后,进⾏执⾏时,由于case较多,导致执⾏速度⽐较慢,那么如何提高用例执行效率呢?

安装 pip install pytest-xdist;

分布式命令:-n x/auto (x表示分布执行数,auto则是根据当前硬件CPU核芯数进行自动分配)

使用方式有三种:

1.在配置文件中的命令行参数增加-n x

2.在main文件中增加-n x

3.在terminal使用pytest命令运行时,在命令后面增加-n x

from time import sleep
class TestDemo:
    def test_demo(self):
        sleep(2)
        print("测试用例1")

    def test_demo2(self):
        sleep(2)
        print("测试用例2")

    def test_demo3(self):
        sleep(2)
        print("测试用例3")

    def test_demo4(self):
        sleep(2)
        print("测试用例4")

如上代码,使用普通执行,运行时间大概是8秒多一点

使用分布式后效果如下

02 pytest装饰器扩展

日常用例执行中,会遇到某些用例需要跳过、做预期值,以及最重要也是最常用的数据参数化。那么在pytest中,也自带了这些装饰器。

跳过测试函数

使用修饰器

@pytest.mark.skipif(布尔类型, reason='不想执行了')

如果第一个参数为True就跳过。如果为False就不跳过

reason是跳过原因,入参类型必须是一个字符串

class TestLogin:
    S = 5

    def test_login(self):
        print('test_login')
        assert 1
    # reason不能传None
    @pytest.mark.skipif(S < 6, reason='不想执行了')
    def test_login_b(self):
        print('test_login_b')
        assert 1

预期失败

应用场景:一般会使用在反向测试的时候

使用装饰器标记用例,并写入预期值:

@pytest.mark.xfail(布尔类型, reason='')

如果为True是预期失败,如果是False是预期成功

报告结论:

红色的表示bug(预期和结果不一致)

带X的,表示预期失败

import pytest


class TestLogin:
    S = 5
    # 预期成功。结果成功
    @pytest.mark.xfail(False, reason='')
    def test_login1(self):
        print('test_login')
        assert 1

    # 预期成功。结果失败
    @pytest.mark.xfail(False, reason='')
    def test_login2(self):
        print('test_login_b')
        assert 0

    # 预期失败。结果失败
    @pytest.mark.xfail(True, reason='')
    def test_login3(self):
        print('test_login')
        assert 0

    # 预期失败 结果成功
    @pytest.mark.xfail(True, reason='')
    def test_login4(self):
        print('test_login')
        assert 1

数据参数化

应用场景:同一个接口,不同用例,一般是一个正向用例,多个反向用例

使用装饰器:

单个参数:@pytest.mark.parametrize('参数名', [参数值1,参数值2......])

多个参数:@pytest.mark.parametrize((“参数名1”,“参数名2”....), [(“参数名1的值1”,“参数名2的值1”),(“参数名1的值2”,“参数名2的值2”)])

# 单个参数化装饰器。参数传入,name(参数名),[参数值1,参数值2......] 多个值之间用逗号分割
@pytest.mark.parametrize('name', ['lisi', 'zhangssan'])
def test_contact(self, name):
    print(name)

# 多个参数在单个参数的基础上,将参数名变成元祖。参数值以列表嵌套元祖的方式
# 实现[('zhangsan','18888888888'),('lisi','13333333333')]
    #参数名可以以元祖方式,也可以以字符串方式传--->>'name,phone'
@pytest.mark.parametrize(('name','phone'), [('zhangsan','188888888888'),('lisi','13333333333')])
def test_contact(self, name , phone):
    print("姓名是:",name)
    print("手机号是:",phone)

可以看到。上方用例代码只写了两条,但是结果中则是四条case。这就是参数化的好处。简化代码的同时,可以覆盖更多的场景

03 结语

好了。本期内容就到这里了。大家下期见。拜拜~