Pytest学习

一、单元测试框架

1、什么是单元测试框架?

单元测试框架是在自动化测试或者白盒测试中对软件的最小单元(函数,方法)进行测试的框架

2、单元测试框架分类

  • python:unittest、pytest(主流)
  • java:Test(主流)、Junit

3、单元测试框架主要做什么?

  1. 发现测试用例
  2. 执行测试用例
  3. 判断测试结果
  4. 生成测试报告

二、Pytest

1、Pytest简介

  1. pytest是一个非常成熟的单元测试框架,灵活、简单
  2. 它可以结合selenium、requests,appium完成各种不同的自动化
  3. 它可以生成自定义的allure报告以及和Jenkins持续集成
  4. pytest有很多强大的插件

pytest

  • pytest-html(生成html报告的插件)
  • pytest-xdist(多线程运行的插件)
  • pytest-ordering(改变用例的执行顺序的插件)
  • pytest-rerunfailures(失败用例重跑的插件)
  • allure-pytest(生成美观自定义的allure报告)

2、插件安装

通过在项目的根目录下新建一个:requirements.txt文件保存插件,通过以下命令安装:

pip install -r requirements.txt

pip install -r requirements.txt
image.png

三、Pytest测试用例的规则及应用

1、规则

  1. 模块名必须以test_开头或者_test结尾
  2. 测试类必须以Test开头,并且不能带有init方法
  3. 测试用例必须以test_开头

2、应用

(Alt+Enter自动导包)

  1. 通过命令行方式执行
pytest

# -vs:-v表示输出详细信息,-s输出调试信息
pytest -vs

# -n:表示多线程运行(需安装插件pytest-xdist)
pytest -vs -n=2

# --reruns num:失败重跑(需安装插件pytest-rerunfailures)
# raise Exception('抛出异常')
pytest -vs --reruns=2

# -x:出现一个失败则停止测试
pytest -vs -x

# --maxfail:出现两次失败才终止
pytest -vs --maxfail=2

# --html:生成html测试报告(需安装插件pytest-html)
pytest -vs --html

# -k:运行测试用例名称包含包含某个字符串
pytest -vs -k "zhangsan"
pytest -vs -k "zhangsan" or "wangwu"

image.png
image.png
image.png

  1. 通过主函数main方式执行
import pytest

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

image.png

  1. 通过全局配置pytest.ini文件执行

注意:

  1. 一般放在项目的根目录下,名称必须是pytest.ini
  2. 当有中文出现,可能需要改变编码格式为GB2312
  3. pytest.ini文件可以改变默认的测试用例规则
  4. 不管是命令行运行还是主函数运行,都会加载这个配置文件
[pytest]
# 参数
# 命令
# -m "smoke表示只执行冒烟用例(在对应方法的上方加装饰器)
addopts = -vs -m "smoke"

# 路径
testpaths = ./testcases

# 模块名称
python_files = test_*.py

# 类名
python_classes = Test*

# 测试方法
python_functions = test_*

# 测试用例分组执行
# 标记
markers =
    smoke:冒烟用例
    mashang:马上教育
    mroduct_manage:商品管理模块用例
    user_manage:用户管理模块
import time

import pytest


class TestMashang:
    @pytest.mark.smoke
    def test_zhangsan(self):
        print('测试zhangsan')
        # raise Exception('我抛出异常啦')

    def test_wangwu(self):
        print('测试wangwu')

    @pytest.mark.smoke
    def test_lisi(self):
        # time.sleep(3)
        print('测试lisi')

四、Pytest跳过测试用例

import time

import pytest


class TestMashang:

    workage = 8

    def test_wangwu(self):
        print('测试wangwu')

    @pytest.mark.skip(reason='无理由跳过')
    def test_01(self):
        print('测试01')

    @pytest.mark.skipif(workage<10, reason='工作年限小于10年跳过')
    def test_01(self):
        print('测试02')

五、Pytest测试用例的前后置

1、前后置

class TestMashang:
    def setup_class(self):
        print('每个类之前执行一次')

    def teardown_class(self):
        print('每个类之后执行一次')

    def setup_method(self):
        print('每个用例之前执行一次')

    def teardown_method(self):
        print('每个用例之后执行一次')

    def test_zhangsan(self):
        print('测试zhangsan')

    def test_wangwu(self):
        print('测试wangwu')

2、使用fixture实现部分前后置

@pytest.fixture(scope.None, autouse=Fasse,params=None, ids=None, name=None)

2.1 scope

scope:作用域

  • function:在函数之前和之后执行
    • 手动调用的方式是在测试用例的参数中加入fixture的名称
    • 如果fixture有通过return或yield返回值的话,那么可以把这个值传递到测试用例中,值是通过固件的名称传递的
  • class:在类之前和之后执行
    • 手动调用的方式是在类的上面加上@pytest.mark.usefixtures(“exe_database_sql”)
  • package/session:在整个项目会话之前和之后执行
    • 一般会结合confitest.py文件来实现

2.2 autouse

autouse:自动执行,默认false(无需调用,自动执行)

import time

import pytest

from common.common_util import CommonUtil


@pytest.fixture(scope="function")
def exe_database_sql():
    print('执行sql查询')


class TestMashang(CommonUtil):
    def test_zhangsan(self):
        print('测试zhangsan')

    def test_lisi(self,exe_database_sql):
        print('测试lisi')
import time

import pytest

from common.common_util import CommonUtil


@pytest.fixture(scope="function",autouse=True)
def exe_database_sql():
    # 之前
    print('执行sql查询')
    yield
    # 之后
    print('关闭数据库连接')


class TestMashang(CommonUtil):
    def test_zhangsan(self):
        print('测试zhangsan')

    def test_wangwu(self):
        print('测试wangwu')

如果需要在另外一个py文件中调用需要结合contest.py文件使用

2.3 params

params:实现参数化

如何把值传到fixture?
通过fixture函数的参数里面加入request来接受参数,然后通过request.param来取值(这里的param没有s)

# 读取数据的方法
def read_yaml():
    return ["chenglong", 'zengzidan', 'caiyili']


@pytest.fixture(scope="function", autouse=False, params=read_yaml())
def exe_database_sql(request):
    print('执行sql查询')
    yield request.param
    print('关闭数据库连接')


class TestMashang():
    def test_wangwu(self, exe_database_sql):
        print('测试wangwu:'+exe_database_sql)
def read_yaml():
    # return ["chenglong", 'zengzidan', 'caiyili']
    return [{'a': 'b'}]
    
@pytest.fixture(scope="function", autouse=False, params=read_yaml())
def exe_database_sql(request):
    print('执行sql查询')
    yield request.param
    print('关闭数据库连接')


class TestMashang():
    def test_wangwu(self, exe_database_sql):
        print('测试wangwu'+str(exe_database_sql))

2.4 ids

ids:不能单独使用,必须params一起使用,作用是对参数起别名

# 读取数据的方法
def read_yaml():
    return ["chenglong", 'zengzidan', 'caiyili']


@pytest.fixture(scope="function", autouse=False, params=read_yaml(), ids=['ch', 'z', 'ca'])
def exe_database_sql(request):
    print('执行sql查询')
    yield request.param
    print('关闭数据库连接')

2.5 name

name:作用是给fixture起别名
特别注意:一旦使用了别名,那么fixture的名称就不能再用了,只能用别名

# 读取数据的方法
def read_yaml():
    return ["chenglong", 'zengzidan', 'caiyili']


@pytest.fixture(scope="function", autouse=False, params=read_yaml(), ids=['ch', 'z', 'ca'], name='db')
def exe_database_sql(request):
    print('执行sql查询')
    yield request.param
    print('关闭数据库连接')


class TestMashang():

    def test_wangwu(self, db):
        print('测试wangwu'+db)

3、fixture结合conftest.py文件使用

  1. conftest.py写在根目录下面
  2. conftest.py是专门用于存放fixture的配置文件,名称是固定的,不能变
  3. 在conftest.py文件里面所有的方法都不需要导包
  4. conftest.py文件可以有多个,并且多个conftest.py文件里面多个fixture可以被一个方法调用
import pytest


@pytest.fixture(scope="function", autouse=False, name='db')
def exe_database_sql(request):
    print('执行sql查询')
    yield request.param
    print('关闭数据库连接')
from common.common_util import CommonUtil


class TestApi(CommonUtil):
    def test_01_get_token(self, db):
        print('获取接口统一的鉴权码'+db)
a

4、优先级

setup_method、teardown_method、setup_class、teardown_class、fixture、conftest优先级
优先级高到低:

  1. 会话:fixture的session
  2. 类:fixture的class
  3. 类:setup_class
  4. 方法:fixture_function
  5. 方法:setup_method

六、Pytest的执行过程

  1. 查找当前目录下的conftest.py文件
  2. 查找当前目录下的pytest.ini文件。找到测试用例的位置
  3. 查找用例目录下的conftest.py文件
  4. 查询测试用例的py文件是否有setup_method、teardown_method、setup_class、teardown_class
  5. 再根据pytest.py文件的测试用例的规则去查找用例并执行

七、Pytest的断言

使用python自己的断言。assert

assert 1=1
assert  'a' in 'abc'
assert flag is True

八、报告生成

pytest结合allure-pytest插件生成美观的报告

  1. 安装allure-pytest插件
  2. 下载allure,下载之后解压,解压之后配置环境变量allure下载地址
  3. 验证allure是否安装成功
    1. 先在dos中验证:allure --version
    2. 在pycharm验证(如果失败,需重启Pycharm)
  4. 生成allure报告
  • 生成临时的json报告,在pytest.ini文件里面 加入以下内容
addopts = -vs --alluredir=./temp --clean-allure
# addopts = -vs --alluredir=./temp 生成临时报告
# --clean-allure 清空临时报告
  • 生成正式的allure报告,在main函数里面加入以下内容
os.system("allure generate ./temps -o ./reports --clean")
  • 定制化
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值