什么是Pytest及Pytest常用方法

什么是Pytest?

  • 一、什么是pytest
  • 二、Pytest的特点
  • 三、Pytest以及常用插件安装
  • 四、编写规则
  • 五、Pytest之收集用例及命令行参数
    • 1、用例收集规则
    • 2、命令行参数
  • 六、跳过用例
  • 七、Pytest的前置和后置方法
    • 1、Pytest可以集成unittest实现前置和后置
    • 2、Pytest前置和后置
  • 八、pytest的ini配置文件
    • 1、pytest.ini的放置位置
    • 2、pytest.ini的作用
  • 九、python编程之ini文件处理-configparser模块应用
    • 1、configparser模块是什么
    • 2、configparser模块基本使用
  • 十、pytest执行测试的方法
  • 十一、fixtrue修饰器标记的方法
    • 1、作用域为函数scope='function'
      • (1)用法一:@pytest.fixture(scope='function',autouse=True)
      • (2)用法二:在使用的时候再加修饰器@pytest.mark.usefixtures("方法名")
      • (3)用法三:@pytest.fixture() 不传参数,在需要调用login函数的地方以参数的形式传入了执行的方法login
    • 2、作用域为类scope='class'
      • (1)用法一:@pytest.fixture(scope='class',autouse=True)
      • (2)用法二:在使用的时候再加修饰器@pytest.mark.usefixtures("方法名")
    • 3、作用域为module时表示整个模块中都只会执行一次
    • 4、作用域为package时表示整个包都只会执行一次
    • 5、在N个用例中指定某一个用例执行
  • 十二、pytest之内置fixture函数之request
  • 十三、@pytest.mark.parametrize()方法实现参数化
  • 十四、request.config 是获取测试的配置文件参数

一、什么是pytest

Pytest是一个非常成熟的全功能的Python测试框架。

二、Pytest的特点

什么是Pytest及Pytest常用方法_第1张图片

三、Pytest以及常用插件安装

在这里插入图片描述
新建一个文件require-install.txt,把以下内容放进去

pytest
pytest-html
pytest-xdist
pytest-rerunfailures

然后在Dos窗口中使用此命令安装所有的模块

pip install -r require-install.txt

四、编写规则

什么是Pytest及Pytest常用方法_第2张图片

五、Pytest之收集用例及命令行参数

1、用例收集规则

什么是Pytest及Pytest常用方法_第3张图片

2、命令行参数

什么是Pytest及Pytest常用方法_第4张图片

什么是Pytest及Pytest常用方法_第5张图片

六、跳过用例

什么是Pytest及Pytest常用方法_第6张图片

@pytest.mark.skipif(2 > 1, reason="当条件为True时跳过")

七、Pytest的前置和后置方法

1、Pytest可以集成unittest实现前置和后置

注意:setUpClass和tearDownClass需要用@classmethod装饰器装饰。

import unittest
import pytest


class TestCase(unittest.TestCase):
    def setUp(self) -> None:
        print("unittest 每个用例前置")

    def tearDown(self) -> None:
        print("unittest 每个用例后置")

    @classmethod
    def setUpClass(cls) -> None:
        print("unittest 所有用例的前置,所有用例之前只执行一次")

    @classmethod
    def tearDownClass(cls) -> None:
        print("unittest 所有用例的后置,所有用例之后只执行一次")

    def test_case1(self):
        print("测试用例case1")

    def test_case2(self):
        print("测试用例case2")


if __name__ == '__main__':
    pytest.main(["-vs", "pytest_unittest_demo.py"])

运行结果
什么是Pytest及Pytest常用方法_第7张图片

2、Pytest前置和后置

(1)setup:在测试函数或类之前执行,完成准备工作,例如数据库链接、测试数据、打开文件等。
(2)teardown:在测试函数或类之后执行,完成收尾工作,例如断开数据库链接、回收内存资源等。

注意:setup、teardown、setup_class、teardown_class都是小写!

class TestCase:
    
    def setup_class(self):
        print("pytest 所有测试用例的前置,所有用例执行之前只执行一次!")

    def teardown_class(self):
        print("pytest 所有测试用例的后置,所有用例执行之后只执行一次!")

    def setup(self):
        print("pytest 在每一个测试用例执行之前执行一次!")

    def teardown(self):
        print("pytest 在每一个测试用例执行之后执行一次!")

    def test_case3(self):
        print("测试用例三case3")

    def test_case4(self):
        print("测试用例case4")


if __name__ == '__main__':
    pytest.main(["-vs", "pytest_demo.py"])

运行结果
什么是Pytest及Pytest常用方法_第8张图片

八、pytest的ini配置文件

pytest.ini文件是pytest的主配置文件,可以改变pytest的默认行为。

1、pytest.ini的放置位置

一般放在项目工程的根目录(即当前项目的顶级文件夹下)。

2、pytest.ini的作用

指定pytest的运行方式。
(在cmd输入pytest后,会读取pytest.ini中的配置信息,按指定的方式去运行)

九、python编程之ini文件处理-configparser模块应用

1、configparser模块是什么

可以用来操作后缀为 .ini 的配置文件;
python标准库(就是python自带的意思,无需安装);

2、configparser模块基本使用

详情请查看另外一篇文章:https://blog.csdn.net/weixin_40608713/article/details/120930460?spm=1001.2014.3001.5501

十、pytest执行测试的方法

pytest.main(args,plugins)

参数说明
1、args :传一个list对象,list 里面是多个命令行的参数。
【包括运行的测试用例(例如:test_a.py);运行测试用例的命令行参数(例如:-vs)】
举例:pytest.main(["-vs", "test_demo.py"])
2、plugins :传一个list对象,list 里面是初始化的时候需注册的插件,可传多个。
举例:

pytest.main(["-vs", "test_demo.py"], plugins=[MyPlugins()])  # plugins指定加载自定义插件MyPlugins()

什么是Pytest及Pytest常用方法_第9张图片

十一、fixtrue修饰器标记的方法

fixtrue修饰器标记的方法通常用于在其他函数、模块、类或者整个工程调用时会优先执行,通常会被用于完成预置处理和重复操作。例如:登录,执行SQL等操作。
fixture的scope参数
scope参数:标记方法的作用域。
有4个可选值:function(默认,函数)、class(类)、module(模块)、package/session(包),默认为function。

1、作用域为函数scope=‘function’

(1)用法一:@pytest.fixture(scope=‘function’,autouse=True)

注意: autouse=True,表示该模块中所有的函数在执行之前都会执行login函数。

# 文件名:pytest-demo.py
import pytest
 
@pytest.fixture(scope='function',autouse=True)
# autouse=True,表示该模块中所有的函数在执行之前都会执行login函数
def login():
    print('登录系统')
 
def test_01():
    print('测试用例一')
 
class TestCase:
 
    def test_03(self):
        print('测试用例三')
 
    def test04(self):
        print('测试用例四')
 
if __name__ == '__main__':
    pytest.main(['-s','pytest-demo.py'])

运行结果
什么是Pytest及Pytest常用方法_第10张图片

(2)用法二:在使用的时候再加修饰器@pytest.mark.usefixtures(“方法名”)

注意:如果没传autouse=True,那么就是默认不自动执行login函数,只有在加了修饰器@pytest.mark.usefixtures(“login”),才会执行login函数。

# 文件名:test_scope_function.py

@pytest.fixture(scope="function")  # 如果没传autouse=True,那么就是默认不执行login函数,只有在加了修饰器@pytest.mark.usefixtures("login"),才会执行login函数

def login():
    print("登录系统")


def test01():
    print("测试用例一")


@pytest.mark.usefixtures("login")
class TestCase:
    def test02(self):
        print("测试用例二")

    def test03(self):
        print("测试用例三")


if __name__ == "__main__":
    pytest.main(["-s", "test_scope_function.py"])

运行结果
什么是Pytest及Pytest常用方法_第11张图片

(3)用法三:@pytest.fixture() 不传参数,在需要调用login函数的地方以参数的形式传入了执行的方法login

# 文件名:test_scope_function.py
@pytest.fixture()  # 用法三,不传参数,在需要调用login函数的地方以参数的形式传入了执行的方法login
def login():
    print("登录系统")
    return "success"


def test01(login):  # 用法三:以参数的形式传入了执行的方法login
    print("测试用例一")
    print(login)

class TestCase:
    def test02(self, login):  # 用法三:以参数的形式传入了执行的方法login
        print("测试用例二")
        print(login)

    def test03(self):
        print("测试用例三")


if __name__ == "__main__":
    pytest.main(["-s", "test_scope_function.py"])

运行结果
什么是Pytest及Pytest常用方法_第12张图片

2、作用域为类scope=‘class’

(1)用法一:@pytest.fixture(scope=‘class’,autouse=True)

# 文件名:test_scope_class.py
import pytest

@pytest.fixture(scope="class", autouse=True)  # 在TestCase1类和TestCase2类中,login方法都只会被执行一次。函数test_01也会执行一次。
def login():
    print("登录系统")


def test01():
    print("测试用例一")


class TestCase01:
    def test02(self):
        print("测试用例二")

    def test03(self):
        print("测试用例三")


class TestCase02:
    def test04(self):
        print("测试用例四")

    def test05(self):
        print("测试用例五")


if __name__ == "__main__":
    pytest.main(["-s", "test_scope_class.py"])

运行结果
什么是Pytest及Pytest常用方法_第13张图片

(2)用法二:在使用的时候再加修饰器@pytest.mark.usefixtures(“方法名”)

# 文件名:test_scope_class.py
@pytest.fixture()  # 方法二,不传参数
def login():
    print("登录系统")


def test01():
    print("测试用例一")


@pytest.mark.usefixtures("login")  
# 方法二:此方式函数不会被执行,但是被作用的类中的每个函数执行之前都会执行一次,在测试类前面添加:@pytest.mark.usefixtures('login') 其中login为函数名。
class TestCase01:
    def test02(self):
        print("测试用例二")

    def test03(self):
        print("测试用例三")


class TestCase02:
    def test04(self):
        print("测试用例四")

    def test05(self):
        print("测试用例五")


if __name__ == "__main__":
    pytest.main(["-s", "test_scope_class.py"])

运行结果
什么是Pytest及Pytest常用方法_第14张图片

3、作用域为module时表示整个模块中都只会执行一次

文件名:test_scope_module.py
import pytest
@pytest.fixture(scope="module", autouse=True)  # 作用域为module
def login():
    print("登录系统")


def test01():
    print("测试用例一")


class TestCase:
    def test02(self):
        print("测试用例二")

    def test03(self):
        print("测试用例三")


if __name__ == "__main__":
    pytest.main(["-s", "test_scope_module.py"])

运行结果
什么是Pytest及Pytest常用方法_第15张图片

4、作用域为package时表示整个包都只会执行一次

# 文件名:test_scope_package.py
import pytest
@pytest.fixture(scope="package", autouse=True)  # 作用域为包
def login():
    print("登录系统")


def test01():
    print("测试用例一")


class TestCase1:
    def test02(self):
        print("测试用例二")

    def test03(self):
        print("测试用例三")


class TestCase2:
    def test04(self):
        print("测试用例二")

    def test05(self):
        print("测试用例三")


if __name__ == "__main__":
    pytest.main(["-s", "test_scope_package.py"])

运行结果
什么是Pytest及Pytest常用方法_第16张图片

5、在N个用例中指定某一个用例执行

@pytest.fixture()  # 不传参数,在需要调用login函数的地方以参数的形式传入了执行的方法login
def login():
    print("登录系统")
    return "success"


def test01(login):  # 以参数的形式传入了执行的方法login
    print("测试用例一")
    print(login)


class TestCase:
    def test02(self, login):  # 以参数的形式传入了执行的方法login
        print("测试用例二")
        print(login)

    def test03(self):
        print("测试用例三")


if __name__ == "__main__":
    pytest.main(["-s", "test_scope_function.py"])

运行结果

什么是Pytest及Pytest常用方法_第17张图片

十二、pytest之内置fixture函数之request

request :是 pytest 的内置 fixture , “为请求对象提供对请求测试上下文的访问权,并且在fixture被间接参数化的情况下具有可选的“param”属性。”
request.param: 获取测试的请求参数。

# 文件名:test_request_param.py
import pytest

# Fixture参数之params参数可实现参数化:(可以为list和tuple,或者字典列表,字典元祖等)

"""
request 是 pytest 的内置 fixture , "为请求对象提供对请求测试上下文的访问权,并且在fixture被间接参数化的情况下具有可选的“param”属性。"
"""

# 测试数据
test_data = ["user1", "user2"]


@pytest.fixture(params=test_data)
def register_users(request):  # 特别注意:这里的request参数名是固定的,然后request.param的param没有s哦
    # 获取当前的测试数据
    user = request.param  # request.param 用于获取测试的请求参数
    print("拿着这个账号%s 去注册" % user)
    result = "success"
    return user, result


# test_register()方法被执行2次,此结果类似于ddt数据驱动的功能
def test_register(register_users):
    # print("register_users 执行后返回的结果为 %s " % register_users)
    user, result = register_users
    print("在测试用例里面获取到的测试数据user为 %s" % user)
    print(result)
    assert result == "success"


if __name__ == '__main__':
    pytest.main(["-vs", "test_request_param.py"])

运行结果
什么是Pytest及Pytest常用方法_第18张图片

十三、@pytest.mark.parametrize()方法实现参数化

parametrize(argnames,argvalues,indirect=False,ids=None,scope=None)

常用参数

argnames:参数名

argvalues:参数值(可以为list和tuple,或者字典列表,字典元祖等),参数值有N个,用例就会执行N次。

方法一

# 方法一:
lis = [("admin01", "abc123"), ("admin02", "a123456")] # 元组列表


@pytest.mark.parametrize("username,password", lis)
def test_p(username, password):
    print(username, password)


if __name__ == "__main__":
    pytest.main(["-vs", "test_pytest_mark_parametrize.py"])

运行结果
什么是Pytest及Pytest常用方法_第19张图片
方法二

# 方法二:
test_data = [{"user01": "123456"}, {"user02": "654321"}]  # 字典列表


@pytest.mark.parametrize("testdata", test_data)
def test_p1(testdata):
    print(testdata)


if __name__ == "__main__":
    pytest.main(["-vs", "test_pytest_mark_parametrize.py"])

运行结果
什么是Pytest及Pytest常用方法_第20张图片

十四、request.config 是获取测试的配置文件参数

# @File    : conftest.py

import pytest


# 将自定义参数添加到pytest配置对象中去(钩子hook函数)
def pytest_addoption(parser):
    parser.addoption(
        "--env", action="store", default="dev", help="env:表示测试环境,默认dev环境"
    )

# 从配置对象中读取自定义参数,方法一:
@pytest.fixture()
def env(request):
    return request.config.getoption("--env")

# 从配置对象中读取自定义参数,方法二:
# @pytest.fixture()
# def env(pytestconfig):
#     return pytestconfig.getoption("env")

# @File    : test_option.py

# 在测试用例中想要获得参数--env的值,就可以调用env函数

from fixture_demo.pytest_addoption.conftest import *


def test_option(env):
    if env == 'dev':
        print("当前测试环境为:{},域名切换为开发环境".format(env))
    elif env == 'test':
        print("当前测试环境为:{},域名切换为测试环境".format(env))
    else:
        print("环境错误,当前环境: {}不存在\n".format(env))


if __name__ == '__main__':
    pytest.main(['-s', '--env=test', 'test_option.py'])

运行结果:
什么是Pytest及Pytest常用方法_第21张图片

你可能感兴趣的:(pytest学习,python,pytest,python测试框架)