1. 程式人生 > 其它 >【pytest單元測試框架】(2)pytest 的基本使用方法

【pytest單元測試框架】(2)pytest 的基本使用方法

pytest 的基本使用方法

1、斷言

  在 unittest 單元測試框架中提供了豐富的斷言方法,如 assertEqual()、assertIn()、assertTrue()、assertIs()等。pytest 單元測試框架並沒有提供專門的斷言方法,而是直接使用Python 的 assert 進行斷言。   建立 test_assert.py 檔案
# -*- coding:utf-8 -*-
# filename: test_assert.py
# author: hello.yin
# date: 2021/11/18

import pytest

# 建立用於測試的功能函式


#
加法測試 def add(a, b): return a + b # 判斷素數 def is_prime(n): if n < 2: return False else: for i in range(2, n): if n % i == 0: return False else: return True # 判斷相等 def test_add1(): assert add(3, 5) == 8 # 判斷大於
def test_add2(): assert add(5, 5) > 10 # 判斷為True def test_isprime1(): assert is_prime(1) is False # 判斷為False def test_isprime2(): assert is_prime(7) is True # 判斷包含 def test_in(): a = "he" b = "hello" assert a in b # 判斷不包含 def test_not_in(): a = "yin" b = "hello
" assert a not in b if __name__ == "__main__": pytest.main()

  執行結果:

(base_practice) D:\00test\base_practice\pyTest>pytest test_assert.py
=============================================================== test session starts ===============================================================
platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: D:\00test\base_practice\pyTest
collected 6 items                                                                                                                                  

test_assert.py .F....                                                                                                                        [100%]

==================================================================== FAILURES =====================================================================
____________________________________________________________________ test_add2 ____________________________________________________________________

    def test_add2():
>       assert add(5, 5) > 10
E    assert 10 > 10
E     +  where 10 = add(5, 5)

test_assert.py:34: AssertionError
============================================================= short test summary info =============================================================
FAILED test_assert.py::test_add2 - assert 10 > 10
=========================================================== 1 failed, 5 passed in 0.06s ===========================================================
  上面的例子展示了 pytest 斷言的用法,藉助 Python 的運算子號和關鍵字即可輕鬆實現不同資料型別的斷言。

2、Fixture

  Fixture 通常用來對測試方法、測試函式、測試類和整個測試檔案進行初始化或還原測試環境。建立 test_fixtures_01.py 檔案。
# -*- coding:utf -8 -*-
# filename: /pyTest/test_fixtrue.py
# author: hello.yin
# date: 2021/11/18


# 功能函式
def mul(a, b):
    return a*b


# 模組級別
def setup_module(module):
    print("===========setup_module=========")


def teardown_module(module):
    print("============teardown_module========")


# 函式級別
def setup_function(function):
    print("==========setup_founction=========")


def teardown_function(function):
    print("==========setup_founction==========")


# 用例級別
def setup():
    print("==========setup=========")


def teardown():
    print("=========teardowm==========")


# 測試用例
def test_35():
    assert mul(3, 5) == 14

def test_45():
    assert mul(4, 5) == 20
  這裡主要用到模組級別和函式級別的 Fixture。
  • setup_module/teardown_module:在當前檔案中,在所有測試用例執行之前與之後執行。
  • setup_function/teardown_function:在每個測試函式之前與之後執行。
  • setup/teardown:在每個測試函式之前與之後執行。這兩個方法同樣可以作用於類方法。

  執行結果:

(base_practice) D:\00test\base_practice\pyTest>pytest test_fixtrue01.py
=============================================================== test session starts ===============================================================
platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: D:\00test\base_practice\pyTest
collected 2 items                                                                                                                                  

test_fixtrue01.py F.                                                                                                                         [100%]

==================================================================== FAILURES =====================================================================
_____________________________________________________________________ test_35 _____________________________________________________________________

    def test_35():
>       assert mul(3, 5) == 14
E    assert 15 == 14
E     +  where 15 = mul(3, 5)

test_fixtrue01.py:41: AssertionError
-------------------------------------------------------------- Captured stdout setup --------------------------------------------------------------
===========setup_module=========
==========setup_founction=========
==========setup=========
------------------------------------------------------------ Captured stdout teardown -------------------------------------------------------------
=========teardowm==========
==========setup_founction==========
============================================================= short test summary info =============================================================
FAILED test_fixtrue01.py::test_35 - assert 15 == 14
=========================================================== 1 failed, 1 passed in 0.05s ===========================================================

  pytest 是支援使用測試類的,同樣必須以“Test”開頭,注意首字母大寫。在引入測試類的情況下,Fixture 的用法如下。建立 test_fixtures_02.py 檔案。

# -*- coding:utf-8 -*-
# filename: test_fixtrue02.py
# author: hello.yin
# date: 2021/11/18


# 功能函式
def mul(a, b):
    return a*b


# 判斷函式類
class TestMul:

    @classmethod
    def setup_class(cls):
        print("===============setup_class===============")

    @classmethod
    def teardown_class(cls):
        print("===============teardown_class==============")

    @staticmethod
    def setup_method(self):
        print("==============setup_method=================")

    @staticmethod
    def teardown_method(self):
        print("==============teardown_method==============")

    @staticmethod
    def setup():
        print("==========setup=============")

    @staticmethod
    def teardown():
        print("===========teardown============")

    # 測試用例
    def test_mul35(self):
        assert mul(3, 5) == 16

    def test_mul45(self):
        assert mul(4, 5) == 20
這裡主要用到類級別和方法級別的 Fixture。
  • setup_class/teardown_class :在當前測試類的開始與結束時執行。
  • setup_method/teardown_method :在每個測試方法開始與結束時執行。
  • setup/teardown :在每個測試方法開始與結束時執行,同樣可以作用於測試函式。
執行結果:
(base_practice) D:\00test\base_practice\pyTest>pytest test_fixtrue02.py
=============================================================== test session starts ===============================================================
platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: D:\00test\base_practice\pyTest
collected 2 items                                                                                                                                  

test_fixtrue02.py F.                                                                                                                         [100%]

==================================================================== FAILURES =====================================================================
_______________________________________________________________ TestMul.test_mul35 ________________________________________________________________

self = <pyTest.test_fixtrue02.TestMul object at 0x0000026A7E40D108>

    def test_mul35(self):
>       assert mul(3, 5) == 16
E    assert 15 == 16
E     +  where 15 = mul(3, 5)

test_fixtrue02.py:41: AssertionError
-------------------------------------------------------------- Captured stdout setup --------------------------------------------------------------
===============setup_class===============
==============setup_method=================
==========setup=============
------------------------------------------------------------ Captured stdout teardown -------------------------------------------------------------
===========teardown============
==============teardown_method==============
============================================================= short test summary info =============================================================
FAILED test_fixtrue02.py::TestMul::test_mul35 - assert 15 == 16
=========================================================== 1 failed, 1 passed in 0.05s ===========================================================

3、 引數化

當一組測試用例有固定的測試資料時,就可以通過引數化的方式簡化測試用例的編寫。pytest 本身是支援引數化的,不需要額外安裝外掛。建立 test_parameterize.py 檔案。
# -*- coding:utf-8 -*-
# filename: test_parameterized.py
# author: hello.yin
# date: 20221/11/18

import pytest
import math


@pytest.mark.parametrize(
    "base, exponent, expected",
    ((2, 2, 4),
     (3, 3, 9),
     (2, 3, 8),
     (0, 9, 0)),
    ids=["case1", "case2", "case3", "case4"])
def test_row(base, exponent, expected):
    assert math.pow(base, exponent) == expected

  用法與 unittest 的引數化外掛類似,通過 pytest.mark.parametrize()方法設定引數。“base,exponent,expected”用來定義引數的名稱。通過陣列定義引數時,每一個元組都是一條測試用例使用的測試資料。ids 引數預設為 None,用於定義測試用例的名稱。math 模組的 pow()方法用於計算 xy(x 的 y 次方)的值。

  執行結果如下:
(base_practice) D:\00test\base_practice\pyTest>pytest -v test_parameterized.py
=============================================================== test session starts ===============================================================
platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 -- C:\Users\yzp\PycharmProjects\base_practice\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\00test\base_practice\pyTest
collected 4 items                                                                                                                                  

test_parameterized.py::test_row[case1] PASSED                                                                                                [ 25%]
test_parameterized.py::test_row[case2] FAILED                                                                                                [ 50%]
test_parameterized.py::test_row[case3] PASSED                                                                                                [ 75%]
test_parameterized.py::test_row[case4] PASSED                                                                                                [100%]

==================================================================== FAILURES =====================================================================
_________________________________________________________________ test_row[case2] _________________________________________________________________

base = 3, exponent = 3, expected = 9

    @pytest.mark.parametrize(
        "base, exponent, expected",
        ((2, 2, 4),
         (3, 3, 9),
         (2, 3, 8),
         (0, 9, 0)),
        ids=["case1", "case2", "case3", "case4"])
    def test_row(base, exponent, expected):
>       assert math.pow(base, exponent) == expected
E    assert 27.0 == 9
E      +27.0
E      -9

test_parameterized.py:18: AssertionError
============================================================= short test summary info =============================================================
FAILED test_parameterized.py::test_row[case2] - assert 27.0 == 9
=========================================================== 1 failed, 3 passed in 0.04s ===========================================================

4、 執行測試

  pytest 提供了豐富的引數執行測試用例,在前面的例子中已經使用到一些引數,例如,“-s”引數用於關閉捕捉,從而輸出列印資訊;“-v”引數用於增加測試用例冗長。    通過“pytest --help”可以檢視幫助:
 pytest––help
  pytest 提供的引數比較多,下面只介紹常用的引數:

4.1.執行名稱中包含某字串的測試用例

  在前面內容test_assert.py 檔案,其中有 42條是關於 add()功能的,並且在測試用例的名稱上包含了“add”字串,因此這裡可以通過“-k”來指定在名稱中包含“add”的測試用例。
(base_practice) D:\00test\base_practice\pyTest>pytest -k add test_assert.py
=============================================================== test session starts ===============================================================
platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: D:\00test\base_practice\pyTest
collected 6 items / 4 deselected / 2 selected                                                                                                      

test_assert.py .F                                                                                                                            [100%]

==================================================================== FAILURES =====================================================================
____________________________________________________________________ test_add2 ____________________________________________________________________

    def test_add2():
>       assert add(5, 5) > 10
E    assert 10 > 10
E     +  where 10 = add(5, 5)

test_assert.py:34: AssertionError
============================================================= short test summary info =============================================================
FAILED test_assert.py::test_add2 - assert 10 > 10
==================================================== 1 failed, 1 passed, 4 deselected in 0.04s ====================================================

4.2.減少測試的執行冗長

這一次執行日誌少了很多資訊,“-q”用來減少測試執行的冗長;也可以使用“--quiet”代替
(base_practice) D:\00test\base_practice\pyTest>pytest -q  test_assert.py
.F....                                                                                                                                       [100%]
==================================================================== FAILURES =====================================================================
____________________________________________________________________ test_add2 ____________________________________________________________________

    def test_add2():
>       assert add(5, 5) > 10
E    assert 10 > 10
E     +  where 10 = add(5, 5)

test_assert.py:34: AssertionError
============================================================= short test summary info =============================================================
FAILED test_assert.py::test_add2 - assert 10 > 10
1 failed, 5 passed in 0.03s

4.3. 如果出現一條測試用例失敗,則退出測試

  這在測試用例的除錯階段是有用的,當出現一條失敗的測試用例時,應該先通過除錯讓這條測試用例執行通過,而不是繼續執行後面的測試用例。
(base_practice) D:\00test\base_practice\pyTest>pytest -x  test_assert.py
=============================================================== test session starts ===============================================================
platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: D:\00test\base_practice\pyTest
collected 6 items                                                                                                                                  

test_assert.py .F

==================================================================== FAILURES =====================================================================
____________________________________________________________________ test_add2 ____________________________________________________________________

    def test_add2():
>       assert add(5, 5) > 10
E    assert 10 > 10
E     +  where 10 = add(5, 5)

test_assert.py:34: AssertionError
============================================================= short test summary info =============================================================
FAILED test_assert.py::test_add2 - assert 10 > 10
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
=========================================================== 1 failed, 1 passed in 0.04s ===========================================================

4.4.執行測試目錄

  測試目錄既可以指定相對路徑(如 ./test_dir ) , 也 可以指定絕對路徑(如D:\00test\base_practice\pyTest)
(base_practice) D:\00test\base_practice\pyTest>pytest D:\00test\base_practice\pyTest
=============================================================== test session starts ===============================================================
platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: D:\00test\base_practice\pyTest
collected 15 items                                                                                                                                 

test_assert.py .F....                                                                                                                        [ 40%]
test_fixtrue01.py F.                                                                                                                         [ 53%]
test_fixtrue02.py F.                                                                                                                         [ 66%]
test_parameterized.py .F..                                                                                                                   [ 93%]
test_sample.py F                                                                                                                             [100%]

==================================================================== FAILURES =====================================================================
____________________________________________________________________ test_add2 ____________________________________________________________________

    def test_add2():
>       assert add(5, 5) > 10
E    assert 10 > 10
E     +  where 10 = add(5, 5)

test_assert.py:34: AssertionError
_____________________________________________________________________ test_35 _____________________________________________________________________

    def test_35():
>       assert mul(3, 5) == 14
E    assert 15 == 14
E     +  where 15 = mul(3, 5)

test_fixtrue01.py:41: AssertionError
-------------------------------------------------------------- Captured stdout setup --------------------------------------------------------------
===========setup_module=========
==========setup_founction=========
==========setup=========
------------------------------------------------------------ Captured stdout teardown -------------------------------------------------------------
=========teardowm==========
==========setup_founction==========
_______________________________________________________________ TestMul.test_mul35 ________________________________________________________________

self = <pyTest.test_fixtrue02.TestMul object at 0x00000276153A5F88>

    def test_mul35(self):
>       assert mul(3, 5) == 16
E    assert 15 == 16
E     +  where 15 = mul(3, 5)

test_fixtrue02.py:41: AssertionError
-------------------------------------------------------------- Captured stdout setup --------------------------------------------------------------
===============setup_class===============
==============setup_method=================
==========setup=============
------------------------------------------------------------ Captured stdout teardown -------------------------------------------------------------
===========teardown============
==============teardown_method==============
_________________________________________________________________ test_row[case2] _________________________________________________________________

base = 3, exponent = 3, expected = 9

    @pytest.mark.parametrize(
        "base, exponent, expected",
        ((2, 2, 4),
         (3, 3, 9),
         (2, 3, 8),
         (0, 9, 0)),
        ids=["case1", "case2", "case3", "case4"])
    def test_row(base, exponent, expected):
>       assert math.pow(base, exponent) == expected
E    assert 27.0 == 9
E     +  where 27.0 = <built-in function pow>(3, 3)
E     +    where <built-in function pow> = math.pow

test_parameterized.py:18: AssertionError
___________________________________________________________________ test_answer ___________________________________________________________________

    def test_answer():
>       assert inc(3) == 5
E    assert 4 == 5
E     +  where 4 = inc(3)

test_sample.py:13: AssertionError
============================================================= short test summary info =============================================================
FAILED test_assert.py::test_add2 - assert 10 > 10
FAILED test_fixtrue01.py::test_35 - assert 15 == 14
FAILED test_fixtrue02.py::TestMul::test_mul35 - assert 15 == 16
FAILED test_parameterized.py::test_row[case2] - assert 27.0 == 9
FAILED test_sample.py::test_answer - assert 4 == 5
========================================================== 5 failed, 10 passed in 0.13s ===========================================================

4.5.指定特定類或方法執行

這裡指定執行 test_fixtures_02.py 檔案中 TestMul 類下的test_mul35()方法,檔名、類名和方法名之間用“::”符號分隔
(base_practice) D:\00test\base_practice\pyTest>pytest test_fixtrue02.py::TestMul::test_mul35
=============================================================== test session starts ===============================================================
platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: D:\00test\base_practice\pyTest
collected 1 item                                                                                                                                   

test_fixtrue02.py F                                                                                                                          [100%]

==================================================================== FAILURES =====================================================================
_______________________________________________________________ TestMul.test_mul35 ________________________________________________________________

self = <pyTest.test_fixtrue02.TestMul object at 0x0000027E785C9808>

    def test_mul35(self):
>       assert mul(3, 5) == 16
E    assert 15 == 16
E     +  where 15 = mul(3, 5)

test_fixtrue02.py:41: AssertionError
-------------------------------------------------------------- Captured stdout setup --------------------------------------------------------------
===============setup_class===============
==============setup_method=================
==========setup=============
------------------------------------------------------------ Captured stdout teardown -------------------------------------------------------------
===========teardown============
==============teardown_method==============
===============teardown_class==============
============================================================= short test summary info =============================================================
FAILED test_fixtrue02.py::TestMul::test_mul35 - assert 15 == 16
================================================================ 1 failed in 0.04s ================================================================

4.6.通過 main()方法執行測試

import pytest
    if __name__ == '__main__':
    pytest.main(['-s', './test_dir'])
建立 run_tests.py 檔案,在檔案中通過陣列指定引數,每個引數為陣列中的一個元素。

5、生成測試報告

pytest 支援生成多種格式的測試報告。

5.1生成 JUnit XML 檔案

> pytest ./test_dir --junit-xml=./report/log.xml

XML 型別的日誌主要用於存放測試結果,方便我們利用裡面的資料定製自己的測試報告。XML 格式的測試報告如圖所示。

執行結果:

(base_practice) D:\00test\base_practice\pyTest>pytest test_assert.py --junit-xml=./report/log.xml
=============================================================== test session starts ===============================================================
platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: D:\00test\base_practice\pyTest
collected 6 items                                                                                                                                  

test_assert.py .F....                                                                                                                        [100%]

==================================================================== FAILURES =====================================================================
____________________________________________________________________ test_add2 ____________________________________________________________________

    def test_add2():
>       assert add(5, 5) > 10
E    assert 10 > 10
E     +  where 10 = add(5, 5)

test_assert.py:34: AssertionError
---------------------------------------- generated xml file: D:\00test\base_practice\pyTest\report\log.xml ----------------------------------------
============================================================= short test summary info =============================================================
FAILED test_assert.py::test_add2 - assert 10 > 10
=========================================================== 1 failed, 5 passed in 0.06s ===========================================================

6、conftest.py

  conftest.py 是 pytest 特有的本地測試配置檔案,既可以用來設定專案級別的 Fixture,也可以用來匯入外部外掛,還可以用來指定鉤子函式。   建立 test_project/conftest.py 測試配置檔案。   需要說明的是,conftest.py 只作用於它所在的目錄及子目錄。

  建立 test_project/conftest.py 測試配置檔案

import pytest

@pytest.fixture()
def test_url():
    return "https://www.baidu.com"

  建立 test_project/test_sub.py 測試用例檔案

def test_baidu(test_url):
    print(test_url)
  這裡建立的函式可以直接呼叫 conftest.py 檔案中的 test_url()鉤子函式,測試結果如下
(base_practice) D:\00test\base_practice\pyTest>pytest -v -s test_project\
=============================================================== test session starts ===============================================================
platform win32 -- Python 3.7.4, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 -- C:\Users\yzp\PycharmProjects\base_practice\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\00test\base_practice\pyTest
collected 1 item                                                                                                                                   

test_project/test_sub.py::test_baidu https://www.baidu.com
PASSED

================================================================ 1 passed in 0.01s ================================================================

本部落格所有文章僅用於學習、研究和交流目的,歡迎非商業性質轉載。

本文來自部落格園,作者:hello_殷,轉載請註明原文連結:https://www.cnblogs.com/yinzuopu/p/15572779.html

本文版權歸作者和部落格園共有,歡迎轉載,但必須給出原文連結,並保留此段宣告,否則保留追究法律責任的權利。