开放的编程资料库

当前位置:我爱分享网 > Python教程 > 正文

Python 使用 pytest

Pytest教程展示了如何使用pytest模块测试Python应用程序。

Python测试

Pytest是一个用于测试Python应用程序的Python库。它是nose和unittest的替代品。

pytest安装

Pytest使用以下命令安装:

$ pip install pytest 

这将安装pytest库。

pytest测试发现约定

如果未指定参数,则在testpaths(如果已配置)或当前目录中的位置搜索测试文件。或者,命令行参数可以用于目录、文件名或节点ID的任意组合。

在选定的目录中,pytest查找test_*.py*_test.py文件。在选定的文件中,pytest在类外部查找带test前缀的测试函数,并在带Test前缀的测试类中查找带test前缀的测试方法(没有__init__方法)。

运行测试

在没有参数的情况下,pytest查看当前工作目录(或其他一些预先配置的目录)和测试文件的所有子目录,并运行它找到的测试代码。

$ pytest

运行当前目录下的所有测试文件。

$ pytest min_max_test.py

我们可以通过将其名称作为参数来运行特定的测试文件。

$ pytest min_max_test.py::test_min

可以通过在::字符后提供其名称来运行特定函数。

$ pytest -m smoke

标记可用于对测试进行分组。然后使用pytest-m运行一组标记的测试。

$ pytest -k <expression>

此外,我们可以使用表达式来运行与测试函数和类名称匹配的测试。

Pythonpytest简单例子

在第一个示例中,我们将使用pytest测试两个简单的数学算法。

def max(values):

  _max = values[0]

  for val in values:
      if val > _max:
          _max = val

  return _max


def min(values):

  _min = values[0]

  for val in values:
      if val < _min:
          _min = val

  return _min

我们有一个带有自定义maxmin函数的模块。

#!/usr/bin/python

import algo

def test_min():
    values = (2, 3, 1, 4, 6)

    val = algo.min(values)
    assert val == 1

def test_max():
    values = (2, 3, 1, 4, 6)

    val = algo.max(values)
    assert val == 6

测试文件min_max_test.py的名称中有一个测试词。

def test_min():
  values = (2, 3, 1, 4, 6)

  val = algo.min(values)
  assert val == 1

另外,测试函数test_min有一个测试词。我们使用assert关键字来测试算法的值。

$ pytest min_max_test.py
================================================= test session starts =================================================
platform win32 -- Python 3.7.0, pytest-5.0.1, py-1.8.0, pluggy-0.12.0
rootdir: C:\Users\Jano\Documents\pyprogs\pytest
collected 2 items

min_max_test.py ..                                                                                               [100%]
  
============================================== 2 passed in 0.03 seconds ===============================================

这是输出。有两个测试都已成功通过。更详细的输出显示为pytest-vmin_max_test.py

Pytest跳过

使用skip装饰器,我们可以跳过指定的测试。跳过测试的原因有多种;例如,数据库/在线服务目前不可用,或者我们跳过Windows上的Linux特定测试。

#!/usr/bin/python

import algo
import pytest

@pytest.mark.skip
def test_min():
    values = (2, 3, 1, 4, 6)

    val = algo.min(values)
    assert val == 1

def test_max():
    values = (2, 3, 1, 4, 6)

    val = algo.max(values)
    assert val == 6

在示例中,test_min被跳过。

$ pytest min_max_test.py
================================================= test session starts =================================================
platform win32 -- Python 3.7.0, pytest-5.0.1, py-1.8.0, pluggy-0.12.0
rootdir: C:\Users\Jano\Documents\pyprogs\pytest
collected 2 items

min_max_test.py s.                                                                                               [100%]

========================================= 1 passed, 1 skipped in 0.04 seconds =========================================

在测试文件名后面的输出中,s代表skipped和.为通过。

Pytest标记

我们可以使用标记将测试组织成单元。

#!/usr/bin/python

# pytest -m a marking.py
# pytest -m b marking.py

import pytest

@pytest.mark.a
def test_a1():

    assert (1) == (1)

@pytest.mark.a
def test_a2():

    assert (1, 2) == (1, 2)

@pytest.mark.a
def test_a3():

    assert (1, 2, 3) == (1, 2, 3)

@pytest.mark.b
def test_b1():

    assert "falcon" == "fal" + "con"

@pytest.mark.b
def test_b2():

    assert "falcon" == f"fal{'con'}"

我们有两组由标记a和b标识的测试。这些单元由pytest-mamarking.pypytest-mbmarking.py运行。

Pytest参数化测试

通过参数化测试,我们可以向断言中添加多个值。我们使用@pytest.mark.parametrize标记。

#!/usr/bin/python

import algo
import pytest

@pytest.mark.parametrize("data, expected", [((2, 3, 1, 4, 6), 1), 
    ((5, -2, 0, 9, 12), -2), ((200, 100, 0, 300, 400), 0)])
def test_min(data, expected):

    val = algo.min(data)
    assert val == expected

@pytest.mark.parametrize("data, expected", [((2, 3, 1, 4, 6), 6), 
    ((5, -2, 0, 9, 12), 12), ((200, 100, 0, 300, 400), 400)])
def test_max(data, expected):

    val = algo.max(data)
    assert val == expected

在示例中,我们使用多个输入数据测试这两个函数。

@pytest.mark.parametrize("data, expected", [((2, 3, 1, 4, 6), 1), 
    ((5, -2, 0, 9, 12), -2), ((200, 100, 0, 300, 400), 0)])
def test_min(data, expected):

    val = algo.min(data)
    assert val == expected

我们将两个值传递给测试函数:数据和预期值。在我们的例子中,我们使用三个数据元组测试min函数。

$ pytest parameterized.py
================================================= test session starts =================================================
platform win32 -- Python 3.7.0, pytest-5.0.1, py-1.8.0, pluggy-0.12.0
rootdir: C:\Users\Jano\Documents\pyprogs\pytest
collected 6 items

parametrized.py ......                                                                                           [100%]

============================================== 6 passed in 0.03 seconds ===============================================

Pytest输出表明有六次运行。

Pytest固定装置

测试需要在一组已知对象的背景下运行。这组对象称为测试夹具

def sel_sort(data):

  if not isinstance(data, list):
      vals = list(data)
  else:
      vals = data

  size = len(vals)

  for i in range(0, size):

      for j in range(i+1, size):

          if vals[j] < vals[i]:
              _min = vals[j]
              vals[j] = vals[i]
              vals[i] = _min
  return vals
...  

对于此示例,我们将选择排序算法添加到algo.py模块。

#!/usr/bin/python

import algo
import pytest

@pytest.fixture
def data():

    return [3, 2, 1, 5, -3, 2, 0, -2, 11, 9]

def test_sel_sort(data):

    sorted_vals = algo.sel_sort(data)
    assert sorted_vals == sorted(data)

我们用夹具测试选择排序。

@pytest.fixture
def data():

    return [3, 2, 1, 5, -3, 2, 0, -2, 11, 9]

我们的测试夹具只是返回一些测试数据。请注意,我们通过名称引用此夹具:data

def test_sel_sort(data):

  sorted_vals = algo.sel_sort(data)
  assert sorted_vals == sorted(data)

test_sel_sort函数中,我们将数据夹具作为函数参数传递。

$ pytest fixtures.py
================================================= test session starts =================================================
platform win32 -- Python 3.7.0, pytest-5.0.1, py-1.8.0, pluggy-0.12.0
rootdir: C:\Users\Jano\Documents\pyprogs\pytest
collected 1 item

fixtures.py .                                                                                                    [100%]

============================================== 1 passed in 0.02 seconds ===============================================

Pytest布局

Python测试可以通过多种方式组织。测试可以集成在Python包中,也可以放在包外。

集成测试

接下来我们将展示如何在Python包中运行测试。

setup.py
utils
│   algo.py
│   srel.py
│   __init__.py
│
└───tests
        algo_test.py
        srel_test.py
        __init__.py

我们有这个包布局。测试位于包内的tests子目录中。

#!/usr/bin/python

from setuptools import setup, find_packages

setup(name="utils", packages=find_packages())

这是setup.py

def sel_sort(data):

    if not isinstance(data, list):
        vals = list(data)
    else:
        vals = data

    size = len(vals)

    for i in range(0, size):

        for j in range(i+1, size):

            if vals[j] < vals[i]:
                _min = vals[j]
                vals[j] = vals[i]
                vals[i] = _min
    return vals


def max(values):

    _max = values[0]

    for val in values:
        if val > _max:
            _max = val

    return _max


def min(values):

    _min = values[0]

    for val in values:
        if val < _min:
            _min = val

    return _min

这是algo.py文件。

def is_palindrome(val):

    return val == val[::-1]

我们还有另一个模块,其中包含一个函数来测试一个单词是否是回文。

#!/usr/bin/python

import utils.algo
import pytest

@pytest.fixture
def data():

    return [3, 2, 1, 5, -3, 2, 0, -2, 11, 9]

def test_sel_sort(data):

    sorted_vals = utils.algo.sel_sort(data)
    assert sorted_vals == sorted(data)

def test_min():
    values = (2, 3, 1, 4, 6)

    val = utils.algo.min(values)
    assert val == 1

def test_max():
    values = (2, 3, 1, 4, 6)

    val = utils.algo.max(values)
    assert val == 6

这些是utils.algo模块的测试。请注意,我们使用完整的模块名称。

#!/usr/bin/python

import utils.srel
import pytest

@pytest.mark.parametrize("word, expected", [('kayak', True), 
    ('civic', True), ('forest', False)])
def test_palindrome(word, expected):

    val = utils.srel.is_palindrome(word)
    assert val == expected

这是对is_palindrome函数的测试。



两个__init__.py文件都是空的。

$ pytest --pyargs utils
================================================= test session starts =================================================
platform win32 -- Python 3.7.0, pytest-5.0.1, py-1.8.0, pluggy-0.12.0
rootdir: C:\Users\Jano\Documents\pyprogs\pytest\structure
collected 6 items

utils\tests\algo_test.py ...                                                                                     [ 50%]
utils\tests\srel_test.py ...                                                                                     [100%]

============================================== 6 passed in 0.06 seconds ===============================================

我们使用pytest--pyargsutils命令运行测试。

包外测试

下一个示例显示了一个应用程序源代码布局,其中测试未集成到包中。

setup.py
src
└───utils
│       algo.py
│       srel.py
tests
    algo_test.py
    srel_test.py

在此布局中,我们在源代码树之外进行了测试。请注意,不需要__init__.py文件。

$ set PYTHONPATH=src
$ pytest

我们设置PYTHONPATH并运行pytest。

在本教程中,我们介绍了Pythonpytest库。

阅读Python教程或列出所有Python教程。

未经允许不得转载:我爱分享网 » Python 使用 pytest

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏