美文网首页
pytest学习笔记

pytest学习笔记

作者: test小星星 | 来源:发表于2019-07-19 21:53 被阅读0次

使用环境

  • python3
  • pycharm
  • pytest

pytest编写规范

  • 测试文件以test_开头或以_test结尾
  • 测试类以Test开头,并且不能带有init方法
  • 测试函数以test_开头

实例

  1. 设置pycharm为pytest运行


    pytest
  2. 创建demo.py文件
# 加法
def add(a, b)
  return a + b
  1. 创建test_demo.py 文件
from src.demo import add
 
# 测试加法
def test_add():
    assert add(1, 2) == 3
    assert add(1, 0) == 1
    assert add(1, -1) == 0
  1. 使用pycharm执行test_demo文件
  2. 使用命令行执行pytest test_demo

常用的pytest第三方插件

插件安装方式pip install 插件名称

  • pytest-sugar 显示执行的进度条
    pytest-sugar
  • pytest-assume 一次性执行完所有测试用例,不会因为某个测试用例失败而终止后面的用例。如,上面的例子就会因为某个用例失败而终止
def test_add():
    assert add(1, 2) == 3
    assert add(1, 0) == 2
    assert add(1, -1) == 0

执行结果

执行结果 可以看出assert add(1, -1) == 0的测试用例并没有被执行。
使用pytest-assume
def test_add(self):
  pytest.assume(add(1, 2) == 3)
  pytest.assume(add(1, 0) == 2)
  pytest.assume(add(1, -1) == 0)
  • pytest-ordering 设置测试用例执行顺序
import pytest
class TestAdd():

    @pytest.mark.run(order=2)
    def test_add1(self):
        print('test_add1')
        pytest.assume(add(1, 2) == 3)

    @pytest.mark.run(order=1)
    def test_add2(self):
        print('test_add2')
        pytest.assume(add(1, -1) == 0)

# order=1先执行,order=2后执行
  • pytest-selenium
  • pytest-play
  • pytest-rerunfailures 重新运行失败的测试用例
# pytest-rerunfailures执行方式
pytest --reruns 3 test_demo.py  # 3代表失败后重新运行的次数,如果加上正常运行的次数总共是4次
  • pytest-allure 测试报告
  • pytest-datadir
  • pytest-datafiles

pytest参数化

通过@pytest.mark.parametrize装饰器传参

import pytest
# 加法
def add(a, b):
    return a + b

# 参数
@pytest.mark.parametrize(
  'a, b, re', [
        (3, 4, 7),
        (1, -1, 0),
        (1, 1.2, 2.2),
])
# 测试加法
def test_add(a, b, re):
    pytest.assume(add(a, b) == re)

通过读取文件的形式参数化
读json文件

import json
import pytest

# 读取json文件
def load_json():
    with open('test.json', 'r') as f:
        re = json.load(f)
    return re

# 加法运算
def add(a, b):
    return a + b

# 把读到文件的数据通过参数传递
@pytest.mark.parametrize('a, b, re', load_json())
# 测试加法运算
def test_add(a, b, re):
    pytest.assume(add(a, b) == re)

读yaml文件

import yaml
import pytest

# 读取yaml文件
def load_json():
    with open('test.yaml', 'r') as f:
        re = yaml.load(f)
    return re

# 加法运算
def add(a, b):
    return a + b

# 把读到文件的数据通过参数传递
@pytest.mark.parametrize('a, b, re', load_json())
# 测试加法运算
def test_add(a, b, re):
    pytest.assume(add(a, b) == re)

说明: pytest.mark.parametrize的第一个参数代表测试方法接收的参数个数,第二个参数为接收的数据内容。如果是通过读文件的形式传参需要注意读出来的文件内容是否和要传的参数类型一致。


pytest执行级别

  1. setup_module 模块级别

如果在单个模块中有多个测试函数和测试类,则可以选择实现以下方法(只会执行一次)

def setup_module():
""" 模块执行前准备工作 """

class Test1():
  """ 测试类1 """
class Test2():
  """ 测试类2 """

def teardown_module():
    """ 模块执行后的结束工作 """
  1. setup_class 类级别

在调用类的所有测试方法之前和之后调用以下方法(只会执行一次)

class TestDemo():
  @classmethod
  def setup_class(cls):
      """ 类方法执行前准备工作 """
  
  def test_add(self):
    "" 测试方法 """
  
  @classmethod
  def teardown_class(cls):
    """ 类方法执行后结束工作 """
  1. setup_method 方法级别

围绕每个方法执行之前之后调用以下方法(每个方法执行之前都会执行一次)

class Test1():
  def setup_method(self):
    """ 每个方法执行之前准备工作  """

  def test_add1(self):
    """ 测试方法1 """  
  
    def test_add2(self):
    """ 测试方法1 """ 
 
  def teardown_method(self):
    """ 每个方法执行之后结束工作 """
  1. setup_function 函数级别

在执行每个函数执行,调用以下方法(只会执行一次)

def setup_function():
    """ 函数执行前准备工作 """

def test_add1():
  """ 测试函数1 """ 

def test_add2():
  """ 测试函数2 """ 

def teardown_function():
    """ 函数执行后结束工 """

pytest fixtures

fixture函数的作用:

  • 完成setup和teardown操作,处理数据库、文件等资源的打开和关闭
  • 完成大部分测试用例需要完成的通用操作,例如login、设置config参数、环境变量等
  • 准备测试数据,将数据提前写入到数据库,或者通过params返回给test用例,等
  • 有独立的命名,可以按照测试的用途来激活,比如用于functions/modules/class/session

fixture 参数
scope参数
scope=function:每个test都运行,默认是function的scope
scope=class:每个class的所有test只运行一次
scope=module:每个module的所有test只运行一次
scope=session:每个session只运行一次

1. 定义一个函数级别的fixture

import pytest

# 定义fixture函数
@pytest.fixture()
def fixture_func():
    print("\n这是一个fixture函数,用来完成一些提前准备")

def test_1(fixture_func):
    print('测试用例1')
    assert 1==1
def test_2(fixture_func):
    print('测试用例2')
    assert 2==2

函数级别的fixture执行结果


函数级别执行结果

2. 定义一个模块级别的fixture

@pytest.fixture(scope="module")
def fixture_func():
    print("\n这是一个fixture函数,用来完成一些提前准备")

def test_1(fixture_func):
    print('测试用例1')
    assert 1==1

def test_2(fixture_func):
    print('测试用例2')
    assert 2 == 2

模块级别的fixture执行结果


module级别执行结果

3. 定义一个session级别fixture
(1) 先创建一个conftest.py文件,输入以下代码
说明:当有测试用例调用pytest.fixture函数时,pytest会自动去找conftest.py文件里找pytest.fixture函数,不需要import。

import pytest

@pytest.fixture(scope="session")
def fixture_func():
   print("\n这是一个fixture函数,用来完成一些提前准备")

(2) 创建第一个测试用例文件 test_demo.py

def test_1(fixture_func):
    print('测试用例1')
    assert 1 == 1

def test_2(fixture_func):
    print('测试用例2')
    assert 2 == 2

(3) 创建第二个测试用例文件 test_demo2.py

def test_1(fixture_func):
    print('测试用例3')
    assert 3 == 3

def test_2(fixture_func):
    print('测试用例4')
    assert 4 == 4

(4) 使用命令行执行测试用例

$ pytest -s test_*

(5) session级别fixture执行结果


session级别执行结果

4. 加上yield的fixture函数
以上几个级别都是相当于steup的方法,加上yield可以构造出相当于teardown的方法。如下

import pytest

def start_prepare():
    print("\n这是一个用来执行测试之前的准备工作")

def end_operation():
    print("\n这是一个用来执行测试结束时的结束工作")

# fixture函数
@pytest.fixture(scope="module")
def fixture_func():
    print("测试开始")
    # 当程序碰到yield会先执行yield前面的代码,等代码都执行完后回到yield处继续执行后面的代码
    yield start_prepare() 
    end_operation()
 

# 测试用例
def test_1(fixture_func):
    print('测试用例1')
    assert 1==1

def test_2(fixture_func):
    print('测试用例2')
    assert 2 == 2

yield 执行结果


yield执行结果

下面来看下函数级别的fixture函数加上yield后的结果

import pytest

def start_prepare():
    print("\n这是一个用来执行测试之前的准备工作")

def end_operation():
    print("\n这是一个用来执行测试结束时的结束工作")

@pytest.fixture()
def fixture_func():
    print("测试开始")
    yield start_prepare()
    end_operation()


# 测试用例
def test_1(fixture_func):
    print('测试用例1')
    assert 1==1

def test_2(fixture_func):
    print('测试用例2')
    assert 2 == 2

yield 执行结果


执行结果

说明:
当测试用例调用了fixture_func函数会先执行fixture_func函数的代码
执行顺序是:

  1. print("测试开始")
  2. start_prepare()
  3. print('测试用例1')
  4. assert 1==1
  5. yield
  6. end_operation()

5. 使用addfinalizer()方法实现类似teardown的方法

import pytest

def start_prepare():
    print("\n这是一个用来执行测试之前的准备工作")

@pytest.fixture()
def fixture_func(request):  # 注意需要加个request参数
    print("\n测试开始")

    def end_operation():
        print("\n这是一个用来执行测试结束时的结束工作")
    # 主要是这句代码来完成结束工作
    request.addfinalizer(end_operation)
    return start_operation()

# 测试用例
def test_1(fixture_func):
    print('测试用例1')
    assert 1==1

def test_2(fixture_func):
    print('测试用例2')
    assert 2 == 2

addfinalizer()方法执行结果


addfinalizer()执行结果

6. fixture参数化

import pytest

@pytest.fixture(params=[
    "参数1",
    "参数2"
])
def fixture_func(request):
    str = request.param
    print(f"\n{str}")


# 测试用例
def test_1(fixture_func):
    print('测试用例1')
    assert 1==1

执行结果,可以看出一个用例执行了两次

参数化执行结果

调用fixture的三种方式
方式1: 在测试用例中直接调用它,把fixture函数当做参数传入,例如上面的例子。

方式2:使用@pytest.mark.usefixtures("fixture函数名称")装饰器

import pytest


@pytest.fixture()
def fixture_func():
    print("\n测试前准备")


@pytest.mark.usefixtures("fixture_func")
def test_1():
    print("函数测试用例1")
    assert 1 == 1


@pytest.mark.usefixtures("fixture_func")
def test_2():
    print('函数测试用例2')
    assert 1 == 1


class Test1:
    @pytest.mark.usefixtures("fixture_func")
    def test_3(self):
        print('类测试用例1')
        assert 1 == 1

    @pytest.mark.usefixtures("fixture_func")
    def test_4(self):
        print('类测试用例2')
        assert 1 == 1


@pytest.mark.usefixtures("fixture_func")
class Test2:
    def test_5(self):
        print('类测试用例3')
        assert 1 == 1

    def test_6(self):
        print('类测试用例4')
        assert 1 == 1

执行结果


@pytest.mark.usefixtures()执行结果

方式3: 用autos调用fixture,autouse 默认设置为False。 当默认为False,就可以选择用上面两种方式来试用fixture。 当设置为True时,在一个session内的所有的test都会自动调用这个fixture,所以用该功能时要谨慎小心。
@pytest.fixture(scope="function", autouse=True)

import pytest


@pytest.fixture(scope="function", autouse=True)
def fixture_func():
    print("\n测试前准备")


def test_1():
    print("函数测试用例1")
    assert 1 == 1


def test_2():
    print('函数测试用例2')
    assert 1 == 1


class Test1:

    def test_3(self):
        print('类测试用例1')
        assert 1 == 1

    def test_4(self):
        print('类测试用例2')
        assert 1 == 1


class Test2:
    def test_5(self):
        print('类测试用例3')
        assert 1 == 1

    def test_6(self):
        print('类测试用例4')
        assert 1 == 1

执行结果


autouse=True执行结果

相关文章

  • Pytest学习笔记(非完整版)

    Pytest学习笔记 记录下pytest官方文档的阅读笔记,以便后续参考使用。非完整版,个人理解为主,难免有误,望...

  • pytest学习笔记

    一、介绍 pytest是一个非常成熟的全功能的Python测试框架,主要特点有以下几点: 1、简单灵活,容易上手;...

  • pytest学习笔记

    使用环境 python3 pycharm pytest pytest编写规范 测试文件以test_开头或以_tes...

  • pytest框架学习-基础入门

    查看所有Python相关学习笔记 pytest学习 一、相关内容的下载安装 1.1 基础安装 1.2 html报告...

  • pytest学习笔记--(一)

    这两天在学习pytest,之前有小用到pytest,觉得这个测试框架很灵巧,用在实现接口自动化(pytest+re...

  • pytest学习笔记--(2)

    继续文档的第二章 (一)pytest中可以在命令行中静态/动态添加option,这里没什么好讲的,略过... ...

  • pytest学习笔记---3

    接着上一篇的内容,这里主要讲下参数化,pytest很好的支持了测试函数中变量的参数化 一、pytest的参数化 1...

  • pytest学习博客列表

    本来打算自己写pytest的一些内容,但是在学习pytest过程中,发现了几个不错的pytest学习系列,所以就不...

  • Python_pytest学习笔记

    第一节课pytest基本介绍 第二节课pytest配置1.命令行参数 addopts = -s —reruns n...

  • 学习笔记-Pytest(一)简介

    1. pytest简介 pytest是python的一种单元测试框架,与python自带的unittest测试框架...

网友评论

      本文标题:pytest学习笔记

      本文链接:https://www.haomeiwen.com/subject/fjkhlctx.html