【接口自动化测试】---自动化框架pytest

发布于:2025-08-14 ⋅ 阅读:(15) ⋅ 点赞:(0)

目录

1、用例运行规则

2、pytest命令参数

3、pytest配置文件

4、前后置

5、断言

6、参数化---对函数的参数(重要)

7、fixture

7.1、基本用法

7.2、fixture嵌套:

7.3、请求多个fixture:

7.4、yield fixture

7.5、带参数的fixture


安装:

pip install pytest==8.3.2

1、用例运行规则

   文件名、类名、方法名命名时必须遵循规则,pytest才能自动识别到测试用例,不需要再手动编写main函数调用测试用例。 

写一个类:

class Test03():
    def test03_01(self):
        print("test03_01")

Test类中为什么不能有__init__方法?

1、pytest采用自动发现机制收集测试用例

2、它会自动实例化测试类并调用test测试方法作为测试用例。

如果写了__init__那么在pytest实例化类的时候,__init__方法就会被调用,这就会掩盖测试类的实际测试用例

那么,我们在初始化的时候应该怎么做呢?

class test02:
    #python默认构造方法---类的初始化
    def __init__(self):
        print("__init__")
    #类中的普通方法
    def init(self)
        print("init")

2、pytest命令参数

pytest -sv .\tests\test_aaa.py::Testaaa::testa_03:指定运行tests目录下的test_aaa.py文件中的Testaaa类中的teata_03方法

3、pytest配置文件

pytest.ini ⽂件通常位于项⽬的根⽬录下。通过在 pytest.ini 中定义配置项,可以覆盖
pytest 的默认⾏为,以满⾜项⽬的需求。
在当前项⽬下创建 pytest.ini ⽂件,该⽂件为 pytest 的配置⽂件,以下为常⻅的配置选项:

若不配置,则走默认规则。加了配置之后,就可以使用pytest执行不符合规则的文件名、类名、方法名了。

4、前后置

在测试类中,不能有init方法。那我们有初始化的需求该怎么办呢?

pytest框架提供了三种方法做前后置操作


1、setup_method 和 teardown_method:这两个方法用于类中的每个测试方法的前后置操作(setup_method 法一 teardown_method、setup_method 法二 teardown_method)

2、setup_class和teardown_class:两个方法用于整个测试类的前后置操作

(setup_clas 法一 teardown_class、 setup_clas 法二 teardown_class)

3、fixture:这是pytest推荐的方式来实现测试用例的前后置操作。这个方法更加灵活,后面专门进行讲解

5、断言

断言时调试的辅助工具,检查代码状态是否符合预期,如果断言失败,即条件为假,就会抛出AssertionError异常。  

对返回值内容进行测试。

assert 条件,错误信息

条件:必须是bool值

错误信息:当条件为假时显示,可选。

#断⾔接⼝返回值重要字段
def test2():
url = "http://jsonplaceholder.typicode.com/comments?postId=1"
r = requests.get(url=url)
print(r.json())
assert r.json()[1]['id'] == 1 #下标从0开始
#断⾔接⼝html返回值
def test3():
url = "http://jsonplaceholder.typicode.com/"
r = requests.get(url=url) #r是返回值  
assert "Use your own data" in r.text #前面的字符串是不是包含在r.text中
#html返回值是text格式的

6、参数化---对函数的参数(重要)

对测试函数的参数进行参数化,使用pytest内置的pytest.mark.parametrize装饰器

对单个参数的参数化:可以使用不同的数据类型

eg1:在用例上使用参数化:多个参数的参数化

import pytest

@pytest.mark.parametrize("test_input,expected",[("3+5",8),("2+4",6),("6*9",54)])

def test_eval(test_input,expected):
    assert eval(test_input) == expected
#通过eval进行计算

给了三组参数,函数就会执行三次

eg2:在类上使用参数化:在类上使用就可以使用参数集调用多个函数

用例可能用到同样的参数,就要对多组用例都使用参数化,那么把参数化定义在类上就是更好的方式。下面的每个用例都会跑两遍。

import pytest
@pytest.mark.parametrize("n,expected", [(1, 2), (3, 4)])

class TestClass:
def test_simple_case(self, n, expected):
assert n + 1 == expecte
def test_weird_simple_case(self, n, expected):
assert (n * 1) + 1 == expected

将参数化的结果保存在pytestmark中 表明是一个全局变量,不写pytestmark的时候就要在每个类前面写@pytest.mark.parametrize(.......)

#将参数化的结果保存在pytestmark中 表明是一个全局变量
pytestmark = pytest.mark.parametrize("data",(1,2))
class Test_A:
    def test_a01(self,data):
        print(data)
    def test_a02(self,data):
        print("data")
class Test_B:
    def test_b01(self,data):
        print(data)
    def test_b02(self,data):
        print("data")

注意我们在使用pytest的时候,import pytest会在语法层面出现报错,但是实际包是可以找到的,也意味着可以直接使用

自定义参数化数据源,而不是写死的。

#从函数的返回值来获取参数
def data_provider():
    #....
    return ["a","b","c"]
@pytest.mark.parametrize("data",data_provider())
def test_data(data):
    print(data)

7、fixture

7.1、基本用法

可以进行前后置操作,也可以进行参数化。⽤于提供测试函数所需的资源或上下⽂

import pytest

@pytest.fixture
def fixture_01():
    print("第⼀个fixture标记的⽅法")

def test_01(fixture_01):
    print("第⼀个测试⽤例")

测试脚本中存在很多重复的代码、公共的数据对象,使用fixture最为合适。

用例之前必须要先进行登录:

import pytest

@pytest.fixture
def login():
    print("---执⾏登陆操作-----")

def test_list(login):
    print("---访问列表⻚")
def test_detail(login):
    print("---访问详情⻚")

7.2、fixture嵌套:

import pytest

@pytest.fixture
def first_entry():
    return "a"

@pytest.fixture
def order(first_entry):
    return [first_entry]

def test_string(order):
    order.append("b")
    assert order == ["a", "b"] # 断⾔

7.3、请求多个fixture:

import pytest

class Fruit:
def __init__(self, name):
    self.name = name
def __eq__(self, other): #重写的比较方法 在比较两个Fruit对象是否相等时被调用
    return self.name == other.name

@pytest.fixture
def my_fruit():
    return Fruit("apple") #类对象 就会调用Fruit类里面的初始化函数

@pytest.fixture
def fruit_basket(my_fruit):
    return [Fruit("banana"), my_fruit] #类对象放在列表里面

def test_my_fruit_in_basket(my_fruit, fruit_basket):
    assert my_fruit in fruit_basket  #这里是在比较两个类对象 调用__eq__方法

上面的在测试方法中传入函数名作为参数时,会先执行传入的函数,这就实现了前置。那么后置怎么实现呢?

7.4、yield fixture

@pytest.fixture
def operator():
    print("前置操作:数据的初始化")
    yield
    print("后置操作:数据的清理")

def test_01(operator):
    print("第一个测试用例")

由结果可以看出,先执行operator中yield之前的部分,再执行调用operator的函数,执行完函数再执行yield的后半部分,就完成了前后置操作。和前面介绍的setup_method和teardown_method效果一样

yield可以返回数据。那么可以看出,是先执行前部分+yield,再执行测试用例,再执行后部分

@pytest.fixture
def operator():
    print("数据的初始化")
    yield 100
    print("数据的清理")
def test_01(operator):
    print(100 + operator)

文件:打开——读模式:读文件、写模式:写文件——关闭

@pytest.fixture
def file_read():
    print("打开文件句柄")
    fo = open("case/test.txt","r",encoding="utf-8")
    yield fo
    print("关闭文件句柄")
    fo.close()

@pytest.fixture
def file_write():
    print("打开文件句柄")
    fo = open("case/test.txt","w",encoding="utf-8")
    return fo
    # yield fo
    # print("关闭文件句柄")
    # fo.close()

def test_file(file_read,file_write):
    w = file_write
    w.write("我们")
    w.close()

    r = file_read
    str = r.read()
    print(str)

7.5、带参数的fixture

pytest.fixture(scope='', autouse='',params='',ids='',name='')

1、scope:控制fixture的作用范围,决定了fixture的生命周期

        1)funtion(默认)

        2)class:在同一个测试类中共享(类中的第一个测试函数调用fixture函数的前部分,最后一个函数调用后部分、如果有第二个类的话和第一个类相同)---(初始化--第一个用例、第二个用例---清理--初始化---第一个用例、第二个用例--清理)

        3)module:在同一个测试模块中共享这个fixture(一个文件里)(要加一个conftest.py文件)----(一个文件中有两个类,只会在第一个类之前执行初始化,在第二个类之后执行清理)---(初始化--第一个用例、第二个用例--第一个用例、第二个用例--清除)(同一个文件中的

        4)session:整个测试会话中共享这个fixture初始化--第一个用例、第二个用例--第一个用例、第二个用例--清除)---将cnftest.py文件涉及到的所有的文件整合到一起

2、autouse:默认值为false。设置为ture时,就不需要进行显示传递

3、params:用于参数化fixture,支持列表传入。每个参数都会使fixture执行一次。

4、ids:与params配合使用,给参数取名字

5、name:给fixture取名字

当测试用例在不同的文件里时,需要将fixture放到配置文件里,实现多个文件共享。

scope = "moudle"、scope = "session"时可用于实现全局的前后置应用,这里需要多一个文件配合,conftest.py和@pytest.fixture结合使用实现全局变量的前后置应用

conftest.py名称时固定的不能改变

每个conftest.py文件都会对其所在的目录及其子目录下的测试模块生效

在不同模块的测试中需要用到conftest.py的前后置功能时,不需要做任何的import导入操作。

可以在不同的.py文件中使用同一个fixture文件

scope = "moudle"、scope = "session"区别:module每个都进行初始化和清理,session第一个进行初始化,最后一个进行清理

params实现参数化和@pytest.mark.parametrize实现参数化的区别:

parametrize更适合简单场景,而fixture更适合需要动态数据和资源的复杂场景。

@pytest.mark.parametrize("参数名",(参数1,参数2)

测试函数

@pytest.fixture(params=[1,2,3])
def data_provider(request): #fixture标记的参数里面参数叫做request
    return request.param #通过request读取params

def test_data(data_provider):
    print(data_provider)

注意:要写为request.param而不是request.params


网站公告

今日签到

点亮在社区的每一天
去签到