自动化测试 —— Pytest fixture及conftest详解

这篇具有很好参考价值的文章主要介绍了自动化测试 —— Pytest fixture及conftest详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

fixture是在测试函数运行前后,由pytest执行的外壳函数。fixture中的代码可以定制,满足多变的测试需求,包括定义传入测试中的数据集、配置测试前系统的初始状态、为批量测试提供数据源等等。fixture是pytest的精髓所在,类似unittest中setup/teardown,但是比它们要强大、灵活很多,它的优势是可以跨文件共享。

一、Pytest fixture

1.pytest fixture几个关键特性

  • 有独立的命名,并通过声明它们从测试函数、模块、类或整个项目中的使用来激活
  • 按模块化的方式实现,每个fixture都可以互相调用
  • fixture可以实现unittest不能实现的功能,比如unittest中的测试用例和测试用例之间是无法传递参数和数据的,但是fixture却可以解决这个问题
  • fixture的范围从简单的单元扩展到复杂的功能测试,允许根据配置和组件选项对fixture和测试用例进行参数化

2.Pytest fixture定义

  • 定义fixture跟定义普通函数差不多,唯一区别就是在函数上加个装饰器@pytest.fixture(),fixture命名不要用test_开头,跟用例区分开。用例才是test_开头的命名;
  • fixture装饰器里的scope有四个级别的参数:function(不写默认这个)、class、module、session;
  • fixture可以有返回值,如果没有return,默认会是None;用例调用fixture的返回值,就是直接把fixture的函数名称作为参数传入;
  • fixture可以返回一个元组、列表或字典;
  • 测试用例可传单个、多个fixture参数;
  • fixture与fixture间可相互调用;

3.Pytest fixture用法

1)用法一:作为参数使用

fixture的名字直接作为测试用例的参数,用例调用fixture的返回值,直接将fixture的函数名称当做变量名称;如果用例需要用到多个fixture的返回数据,fixture也可以返回一个元祖,list或字典,然后从里面取出对应数据。

① 将fixture函数作为参数传递给测试用例

@pytest.fixture()
def login():
    print("this is login fixture")
    user = "chen"
    pwd = 123456
    return user, pwd

def test_login(login):
    """将fixture修饰的login函数作为参数传递给本用例"""
    print(login)
    assert login[0] == "chen"
    assert login[1] == 123456
    assert "chen" in str(login)

② 同一个用例中传入多个fixture函数

@pytest.fixture()
def user():
    user = "cris"
    return user

@pytest.fixture()
def pwd():
    pwd = "123456"
    return pwd

def test_trans_fixture(user, pwd):
    """同一条用例中传入多个fixture函数"""
    print(user, pwd)
    assert "cris" in str(user)
    assert pwd == "123456"

③ fixture函数之间的相互传递

@pytest.fixture()
def user2():
    user = "cris"
    return user

@pytest.fixture()
def login_info(user2):
    """fixture与fixture函数之间的相互传递"""
    pwd = "e10adc3949ba59abbe56e057f20f883e"
    return user2, pwd

def test_assert_login_info(login_info):
    print(login_info)
    print(type(login_info))
    assert login_info[0] == "cris"
    assert login_info[1] == "e10adc3949ba59abbe56e057f20f883e"

2)用法二:提供灵活的类似setup和teardown功能

Pytest的fixture另一个强大的功能就是在函数执行前后增加操作,类似setup和teardown操作,但是比setup和teardown的操作更加灵活;具体使用方式是同样定义一个函数,然后用装饰器标记为fixture,然后在此函数中使用一个yield语句,yield语句之前的就会在测试用例之前使用,yield之后的语句就会在测试用例执行完成之后再执行。

@pytest.fixture()
def run_function():
    print("run before function...")
    yield
    print("run after function...")

def test_run_1(run_function):
    print("case 1")

def test_run_2():
    print("case 2")

def test_run_3(run_function):
    print("case 3")

运行结果如下:

 

常见的应用场景:@pytest.fixture可以用在selenium中测试用例执行前后打开、关闭浏览器的操作:

@pytest.fixture()
def fixture_driver():
    driver = webdriver.Chrome()
    yield driver
    driver.quit()

def test_baidu(fixture_driver):
    driver = fixture_driver
    driver.get("http://www.baidu.com")
    driver.find_element_by_id('kw').send_keys("python fixture")
    driver.find_element_by_id('su').click()

3)用法三:利用pytest.mark.usefixtures叠加调用多个fixture

如果一个方法或者一个class用例想要同时调用多个fixture,可以使用@pytest.mark.usefixtures()进行叠加。注意叠加顺序,① 与直接传入fixture不同的是,@pytest.mark.usefixtures无法获取到被fixture装饰的函数的返回值;

② @pytest.mark.usefixtures的使用场景是:被测试函数需要多个fixture做前后置工作时使用;

@pytest.fixture
def func_1():
    print("用例前置操作---1")
    yield
    print("用例后置操作---1")

@pytest.fixture
def func_2():
    print("用例前置操作---2")
    yield
    print("用例后置操作---2")

@pytest.fixture
def func_3():
    print("用例前置操作---3")
    yield
    print("用例后置操作---3")

@pytest.mark.usefixtures("func_3")  # 最后执行func_3
@pytest.mark.usefixtures("func_2")  # 再执行func_1
@pytest.mark.usefixtures("func_1")  # 先执行func_1
def test_func():
    print("这是测试用例")

执行结果:

 

4)用法四:fixture自动使用autouse=True

当用例很多的时候,每次都传这个参数,会很麻烦。fixture里面有个参数autouse,默认是False没开启的,可以设置为True开启自动使用fixture功能,这样用例就不用每次都去传参了,autouse设置为True,自动调用fixture功能。所有用例都会生效,包括类中的测试用例和类以外的测试用例

@pytest.fixture(autouse=True, scope="function")
def func_auto():
    """autouse为True时,会作用于每一条用例"""
    print("\n---用例前置操作---")
    yield
    print("---用例后置操作---")

# func_auto函数的autouse=True时,无论是否使用usefixtures引用func_auto,都会执行func_auto
@pytest.mark.usefixtures("func_auto")
def test_01():
    print("case 1")

def test_02():
    print("case 2")

class Test:
    def test_03(self):
        print("case 3")

执行结果:

4.Pytest fixture四种作用域

fixture(scope='function',params=None,autouse=False,ids=None,name=None)

fixture里面有个

  • function:每一个函数或方法都会调用
  • class:每一个类调用一次,一个类中可以有多个方法
  • module:每一个.py文件调用一次,该文件内又有多个function和class
  • session:多个文件调用一次,可以跨.py文件调用(通常这个级别会结合conftest.py文件使用)

1)function级别

function默认模式为@pytest.fixture() 函数级别,即scope="function",scope可以不写。每一个函数或方法都会调用,每个测试用例执行前都会执行一次function级别的fixture。

# @pytest.fixture(scope="function")等价于@pytest.fixture()
@pytest.fixture(scope="function")
def func_auto():
    """用例级别fixture,作用域单个用例"""
    print("\n---function级别的用例前置操作---")
    yield
    print("---function级别的用例后置操作---")

# test_01会引用func_auto函数,test_02没有用修饰器修饰,故不会引用
def test_func_auto_fixture_1(func_auto):
    print("func 1 print")

def test_func_auto_fixture_2():
    print("func 2 print")

2)class级别

fixture的scope值还可以是class,此时则fixture定义的动作就会在测试类class的所有用例之前和之后运行,需注意:测试类中只要有一个测试用例的参数中使用了class级别的fixture,则在整个测试类的所有测试用例都会调用fixture函数

① 用例类中的测试用例调用fixture

执行fixture定义的动作,以及此测试类的所有用例结束后同样要运行fixture指定的动作

@pytest.fixture(scope="class")
def class_auto():
    """类级别fixture,作用域整个类"""
    print("\n---class级别的用例前置操作---")
    yield
    print("---class级别的用例后置操作---")

class TestClassAutoFixture:
    # class级别的fixture任意一个用例引用即可
    def test_class_auto_fixture_1(self, class_auto):
        print("class 1 print")

    def test_class_auto_fixture_2(self):
        print("class 1 print")

测试类中的第1条测试用例引用了fixture修饰的函数,则整个测试类的所有测试用例都会执行fixture函数的前置操作,在所有用例执行完成后,都会执行fixture函数的后置操作。

② 用例类外的测试用例调用fixture

如果在类外的函数中去使用class级别的fixture,则此时在测试类外每个测试用例中,fixture跟function级别的fixture作用是一致的,即def test_class_auto_fixture(class_auto): print("class 1 print")

如下图所示,测试类外的函数引用了class级别的fixture,则它的作用会等同于function级别的fixture,运行结果如下:

3)module级别

在Python中module即.py文件,当fixture定义为module时,则此fixture将在当前文件中起作用。这里需要特别说明的是,当fixture的scope定义为module时,只要当前文件中有一个测试用例使用了fixture,不管这个用例是在类外,还是在类中,都会在当前文件(模块)的所有测试用例执行之前去执行fixture定义的行为以及当前文件的所有用例结束之后同样去执行fixture定义的对应操作。

@pytest.fixture(scope="module")
def module_auto():
    """作用于整个py文件"""
    print("\n---module级别的用例前置操作---")
    yield
    print("---module级别的用例后置操作---")
    
# 测试类外和测试类内的函数方法都调用了module级别的fixture,但整个py文件只会生效一次fixture。
def test_module_scope_out_class(module_auto):
    print("case scope 01")
    
class TestScope1:
    def test_scope_01(self):
        print("case scope 01")

    def test_scope_02(self, module_auto):
        print("case scope 02")

    def test_scope_03(self):
        print("case scope 03")

若类中的方法分别调用了class级别的fixture和module级别的fixture,则会两个fixture都生效:

# 顺序在前面fixture会先执行
def test_scope_01(self, module_auto, class_auto): 
    print("case scope 01")

若类中的方法同时调用了function级别、class级别、module级别的fixture,则3种fixture会同时生效:

# 顺序在前面fixture会先执行
def test_scope_02(self, module_auto, class_auto, func_auto):  
    print("case scope 02")

4)session级别(使用conftest.py共享fixture)

当fixture的scope定义为session时,是指在当前目录下的所有用例之前和之后执行fixture对应的操作

fixture为session级别是可以跨.py模块调用的,也就是当我们有多个.py文件的用例的时候,如果多个用例只需调用一次fixture,那就可以设置为scope="session",并且写到conftest.py文件里

使用方式:

① 定义测试用例文件

② 在指定目录下创建conftest.py(固定命名,不可修改)文件,然后在conftest.py文件中定义fixture方法,将scope指定为session,此时在当前目录下只要有一个用例使用了此fixture,则就会在当前目录下所有用例之前和之后会执行fixture定义的对应的操作。

@pytest.fixture(scope="session", )
def session_auto():
    """session级别的fixture,针对该目录下的所有用例都生效"""
    print("\n---session级别的用例前置操作---")
    yield
    print("---session级别的用例后置操作---")

定义了session级别的fixture,存放于该用例文件的同一个目录下的conftest.py文件中,该目录下的任一用例文件中的任一测试用例,引用了这个session级别的fixture,则这个session级别的fixture会针对这整个用例文件会生效。若存放在根目录下,则针对整个工程的所有用例都会生效。

class TestSessionAutoFixture:
    # session级别的fixture任意一个用例引用即可
    def test_session_auto_fixture_1(self, session_auto):
        print("session 1 print")

    def test_session_auto_fixture_2(self):
        print("session 1 print")


def test_session_auto_fixture():
    print("session 1 print")

运行结果如下:

 

5.Pytest fixture其他参数用法

1)ids参数-修改用例结果名称

@pytest.mark.parametrize() 还提供了第三个 ids 参数来自定义显示结果。

stars = ["刘德华", "张学友", "黎明", "郭富城"]
# 利用列表生成式生成一个用例名称的列表
ids = [f"test-case-{d}" for d in range(len(stars))]

@pytest.mark.parametrize("name", stars, ids=ids)
def test_multi_param(name):
    print(f"my name is {name}")

注:ids生成的用例名称数量一定要和用例数量一致,否则会报错,执行结果如下:

 

 

2)name参数-重命名fixture函数名称

@pytest.fixture(name="rename_get_user_info")
def get_user_info():
    user_name = "周润发"
    print(user_name)

# 此处需传入重命名后的fixture函数名
@pytest.mark.usefixtures("rename_get_user_info")
def test_parametrize_by_use_fixtures():
    """通过usefixtures装饰器传入fixture"""
    print(f"test parametrize use fixtures")
    
def test_parametrize_by_fixture_name(rename_get_user_info):
    """将fixture函数名作为形参传入"""
    print(f"test parametrize use fixtures")

3)params参数-提供返回值供测试函数调用

示例一

@pytest.fixture(params=[{"name": "周润发"}, {"age": 61}, {"height": 183}])
def fix_func(request):  # request为内建fixture
    # 使用request.param作为返回值供测试函数调用,params的参数列表中包含了做少元素,该fixture就会被调用几次,分别作用在每个测试函数上
    return request.param  # request.param为固定写法

def test_fix_func(fix_func):
    print(f"fixture函数fix_func的返回值为:{fix_func}")
    
    """打印结果如下:
    fixture函数fix_func的返回值为:{'name': '周润发'}
    fixture函数fix_func的返回值为:{'age': 61}
    fixture函数fix_func的返回值为:{'height': 183}
    """

示例二

params = [
    {"case_id": 1, "case_title": "验证正常添加车辆", "car_name": "苏C99688", "car_type": 1, "origin": 1, "expected": "200"},
    {"case_id": 2, "case_title": "验证添加重复车辆", "car_name": "苏C99688", "car_type": 1, "origin": 1, "expected": "500"},
    {"case_id": 3, "case_title": "验证车牌号为空", "car_name": "", "car_type": 2, "origin": 1, "expected": "500"}]

@pytest.fixture(params=params)
def add_car_params(request):
    return request.param

def test_add_car(add_car_params):
    print(f"{add_car_params['case_id']}-{add_car_params['case_title']}-{add_car_params['car_name']}")
    
    """
    运行结果如下:
    1-验证正常添加车辆-苏C99688
    2-验证添加重复车辆-苏C99688
    3-验证车牌号为空-
    """

6.内置fixture

1)tmpdir和tmpdir_factory

内置的tmpdir和tmpdir_factory负责在测试开始运行前创建临时文件目录,并在测试结束后删除。如果测试代码要对文件进行读/写操作,那么可以使用tmpdir或tmpdir_factory来创建文件或目录。单个测试使用tmpdir,多个测试使用tmpdir_factory。tmpdir的作用范围是函数级别,tmpdir_factory的作用范围是会话级别。

def test_tmpdir(tmpdir):
    # tmpdir already has a path name associated with it
    # join() extends the path to include a filename
    # the file is created when it's written to
    a_file = tmpdir.join('something.txt')

    # you can create directories
    a_sub_dir = tmpdir.mkdir('anything')

    # you can create files in directories (created when written)
    another_file = a_sub_dir.join('something_else.txt')

    # this write creates 'something.txt'
    a_file.write('contents may settle during shipping')

    # this write creates 'anything/something_else.txt'
    another_file.write('something different')

    # you can read the files as well
    assert a_file.read() == 'contents may settle during shipping'
    assert another_file.read() == 'something different'


def test_tmpdir_factory(tmpdir_factory):
    # you should start with making a directory
    # a_dir acts like the object returned from the tmpdir fixture
    a_dir = tmpdir_factory.mktemp('mydir')

    # base_temp will be the parent dir of 'mydir'
    # you don't have to use getbasetemp()
    # using it here just to show that it's available
    base_temp = tmpdir_factory.getbasetemp()
    print('base:', base_temp)

    # the rest of this test looks the same as the 'test_tmpdir()'
    # example except I'm using a_dir instead of tmpdir

    a_file = a_dir.join('something.txt')
    a_sub_dir = a_dir.mkdir('anything')
    another_file = a_sub_dir.join('something_else.txt')

    a_file.write('contents may settle during shipping')
    another_file.write('something different')

    assert a_file.read() == 'contents may settle during shipping'
    assert another_file.read() == 'something different'

2)pytestconfig

内置的pytestconfig可以通过命令行参数、选项、配置文件、插件、运行目录等方式来控制pytest。pytestconfig是request.config的快捷方式,它在pytest文档里有时候被称为“pytest配置对象”。

要理解pytestconfig如何工作,可以添加一个自定义的命令行选项,然后在测试中读取该选项。

def pytest_addoption(parser):
    """"添加一个命令行选项"""
    parser.addoption(
        "--env", default="test", choices=["dev", "test", "pre"], help="enviroment parameter")

以pytest_addoption添加的命令行选项必须通过插件来实现,或者在项目顶层目录的conftest.py文件中完成。它所在的conftest.py不能处于测试子目录下。

上述是一个传入测试环境的命令行选项,接下来可以在测试用例中使用这些选项。

def test_option(pytestconfig):
    print('the current environment is:', pytestconfig.getoption('env'))
# 运行测试
pytest -s -q test_config.py::test_option

由于前面的pytest_addoption中定义的env的默认参数是test,所以通过pytestconfig.getoption获取到的env的值就是test:

3)其他内置fixture

  • cache:作用是存储一段测试会话的信息,在下一段测试会话中使用;
  • capsys:capsys 有两个功能:允许使用代码读取 stdout 和 stderr;可以临时禁制抓取日志输出;
  • monkeypatch:可以在运行期间对类或模块进行动态修改。在测试中,monkey patch 常用于替换被测试代码的部分运行环境,或者将输入依赖或输出依赖替换成更容易测试的对象或函数;
  • doctest_namespace:doctest 模块是 Python 标准库的一部分,借助它,可以在函数的文档字符串中放入示例代码,并通过测试确保有效。你可以使用 --doctest-modules 标识搜寻并运行 doctest 测试用例;
  • recwarn:可以用来检查待测代码产生的警告信息;recwarn 的值就像是一个警告信息列表,列表里的每个警告信息都有4个属性 category、message、filename、lineno。警告信息在测试开始后收集,如果你在意的警告信息出现在测试尾部,则可以在信息收集前使用 recwarn.clear() 清除不需要的内容。除了 recwarn,pytest 还可以使用 pytest.warns() 来检查警告信息。

二、Pytest conftest全局作用文件详解

Pytest支持在测试的目录中,创建conftest.py文件,进行全局配置。

conftest.py文件须知:

  1. 可以跨.py文件调用,有多个.py文件调用时,可让conftest.py只调用了一次fixture,或调用多次fixture;
  2. conftest.py与运行的用例要在同一个pakage下,并且有__init__.py文件;
  3. 不需要import导入conftest.py,pytest用例会自动识别该文件,放到项目的根目录下就可以全局目录调用了,如果放到某个package下,那就在package内有效,可有多个conftest.py;
  4. conftest.py配置脚本名称是固定的,不能改名称;
  5. conftest.py文件不能被其他文件导入;
  6. 所有同目录测试文件运行前都会执行conftest.py文件;

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

自动化测试 —— Pytest fixture及conftest详解文章来源地址https://www.toymoban.com/news/detail-844342.html

如果你想学习软件测试和需要软件测试资料,欢迎加入扣扣交流群:731789136,里面可以免费领取软件测试+自动化测试资料+软件测试面试宝典+简历模版+实战项目+面试刷题工具和大佬答疑解惑,我们一起交流一起学习!

到了这里,关于自动化测试 —— Pytest fixture及conftest详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【自动化测试教程】 —— pytest 框架详解 ~

    特点: 容易上手, 入门简单, 文档丰富, 文档中有很多参考案例 支持简单的单元测试和复杂的功能测试 支持参数化 执行测试用例过程中, 支持跳过操作 支持重复失败的case 支持运行Nose, unittest编写测试用例 pytest支持很多第三方插件 方便和持续集成工具集成 断言方法: assert res

    2024年02月12日
    浏览(35)
  • Selenium+Pytest自动化测试框架详解

    selenium自动化+ pytest测试框架 本章你需要 一定的python基础——至少明白类与对象,封装继承; 一定的selenium基础——本篇不讲selenium,不会的可以自己去看selenium中文翻译网 测试框架有什么优点 代码复用率高,如果不使用框架的话,代码会很冗余 可以组装日志、报告、邮件等

    2024年02月08日
    浏览(76)
  • 自动化测试中如何判断测试是否通过?详解 Pytest 测试框架的断言用法

    目录 前言: 01 — Python 原生的 assert 02 — Pytest 的 assert 优点 03 — Pytest 断言的用法 4.1 断言字符串 4.2 断言函数或者接口返回值 4.3 断言集合类型 04 — Pytest 断言 Excepiton 05 — 为断言添加自定义功能 06 — 禁止 Pytest 的 assert 特性 07 — 总结 在自动化测试中,判断测试是否通过是

    2024年02月16日
    浏览(47)
  • 【UI自动化测试技术】自动化测试研究:Python+Selenium+Pytest+Allure,详解UI自动化测试,学习模拟鼠标+模拟键盘进行相关操作(精)(四)

    1、了解元素交互的常用方法 2、学习如何对多选元素进行操作 3、 学习模拟鼠标进行相关操作 ( 本节目标 ) 4、 学习模拟键盘进行相关操作 ( 本节目标 ) 用于向 Web 浏览器提供虚拟化设备输入操作的低级接口.除了刚刚讲过的Web元素交互之外, Actions 接口 还提供了对指定输

    2024年03月24日
    浏览(44)
  • 自动化测试(三):接口自动化pytest测试框架

    API:Application Programming Interface 接口自动化按照自动化的工具可分为 基于 接口测试工具 的接口自动化 eg1:Postman+Newman+git/Svn+Jenkins(基于Javascript语言)接口自动化 Postman :创建和发送 API 请求,并对响应进行断言和验证。 Newman : Postman 的命令行工具,它允许测试人员在没有界

    2024年02月10日
    浏览(42)
  • 从0到1精通自动化测试,pytest自动化测试框架,配置文件pytest.ini(十三)

    pytest配置文件可以改变pytest的运行方式,它是一个固定的文件pytest.ini文件,读取配置信息,按指定的方式去运行 pytest里面有些文件是非test文件 pytest.ini pytest的主配置文件,可以改变pytest的默认行为 conftest.py 测试用例的一些fixture配置 _init_.py 识别该文件夹为python的package包

    2024年02月11日
    浏览(38)
  • Pytest自动化测试

    目录 一、Pytest如何安装 二、Pytest如何编写用例 三、Pytest如何运行用例 四、Pytest如何实现参数化 五、Pytest如何跳过和标记用例 六、Pytest如何失败重执行 七、Pytest如何使用夹具 八、Pytest如何进行夹具共享 九、Pytest如何设置夹具作用域 Pytest是Python中最流行的自动化测试框架之

    2024年02月02日
    浏览(26)
  • pytest 框架自动化测试

    随笔记录 目录 1. 安装  2. 安装pytest 相关插件 2.1 准备阶段 2.2 安装  2.3 验证安装成功  3. pytest测试用例的运行方式 3.1 主函数模式 3.1.1 主函数执行指定文件  3.1.2 主函数执行指定模块 3.1.3 主函数执行某个文件中的某个类、方法、函数 3.1.4 主函数执行生成allure报告 3.2 命令

    2024年02月19日
    浏览(37)
  • Pytest自动化测试框架---(单元测试框架)

    unittest是python自带的单元测试框架,它封装好了一些校验返回的结果方法和一些用例执行前的初始化操作,使得单元测试易于开展,因为它的易用性,很多同学也拿它来做功能测试和接口测试,只需简单开发一些功能(报告,初始化webdriver,或者http请求方法)便可实现。 但自

    2024年02月14日
    浏览(47)
  • 从0到1精通自动化测试,pytest自动化测试框架,doctest测试框架(十四)

    doctest从字面意思上看,那就是文档测试。doctest是python里面自带的一个模块,它实际上是单元测试的一种。 官方解释:doctest 模块会搜索那些看起来像交互式会话的 Python 代码片段,然后尝试执行并验证结果 doctest测试用例可以放在两个地方 函数或者方法下的注释里面 模块的

    2024年02月11日
    浏览(67)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包