pytest使用總結筆記


 

簡介

pytest是python的一種單元測試框架,與python自帶的unittest測試框架類似,但是比unittest框架使用起來更簡潔,效率更高。並且pytest兼容unittest的用例,支持的插件也更多

安裝

pip install pytest

簡單上手,創建個test_sample.py文件

def func(x):
    return x + 1

def test_answer():
    assert func(3) == 5

運行測試,直接在當前文件夾運行pytest

collected 1 item

test_sample.py F                                                     [100%]

================================= FAILURES =================================
_______________________________ test_answer ________________________________

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

test_sample.py:6: AssertionError
============================ 1 failed in 0.12s =============================

pytest運行規則:查找當前目錄及其子目錄下以test_*.py或*_test.py文件,找到文件后,在文件中找到以test開頭函數並執行。

以類來封裝用例

# content of test_class.py
class TestClass:
    def test_one(self):
        x = "this"
        assert "h" in x

    def test_two(self):
        x = "hello"
        assert hasattr(x, "check")

運行可以使用pytest [file_path]指定文件,-q是靜默模式,不會打印用例輸出

$ pytest -q test_class.py
.F                                                                   [100%]
================================= FAILURES =================================
____________________________ TestClass.test_two ____________________________

self = <test_class.TestClass object at 0xdeadbeef>

    def test_two(self):
        x = "hello"
>       assert hasattr(x, "check")
E       AssertionError: assert False
E        +  where False = hasattr('hello', 'check')

test_class.py:8: AssertionError
1 failed, 1 passed in 0.12s

用例設計原則

  • 文件名以test_*.py文件和*_test.py
  • 以test_開頭的函數
  • 以Test開頭的類
  • 以test_開頭的方法
  • 所有的包pakege必須要有__init__.py文件

 

執行用例

1.執行某個目錄下所有的用例

pytest 文件名/

2.執行某一個py文件下用例

pytest 腳本名稱.py

3.-k 按關鍵字匹配

pytest -k "MyClass and not method"

這將運行包含與給定字符串表達式匹配的名稱的測試,其中包括Python使用文件名,類名和函數名作為變量的運算符。 上面的例子將運行TestMyClass.test_something但不運行TestMyClass.test_method_simple

4.按節點運行

每個收集的測試都分配了一個唯一的nodeid,它由模塊文件名和后跟說明符組成來自參數化的類名,函數名和參數,由:: characters分隔。

運行.py模塊里面的某個函數

pytest test_mod.py::test_func

運行.py模塊里面,測試類里面的某個方法

pytest test_mod.py::TestClass::test_method

5.標記表達式

pytest -m slow

將運行用@ pytest.mark.slow裝飾器修飾的所有測試,slow是自己命名的標記,可以自定義

import pytest

@pytest.mark.finished
def test_send_http():
    pass  


def test_something_quick():
    pass

運行測試時使用-m選項可以加上邏輯

>pytest -m "finished and commit"   //匹配finished和commit運行

>pytest -m "finished and not merged"  //finished運行,merged不運行

6.從包里面運行

pytest --pyargs pkg.testing

這將導入pkg.testing並使用其文件系統位置來查找和運行測試。

7.在第一個(或N個)失敗后停止

pytest -x            # stop after first failure
pytest --maxfail=2    # stop after two failures

8.跳過測試

使用pytest.mark.skip標記需要跳過的用例

@pytest.mark.skip(reason="not finished")
def test_send_http():
    pass 

也支持使用 pytest.mark.skipif 為測試函數指定被忽略的條件

@pytest.mark.skipif(finishflag==Fasle,reason="not finished")
def test_send_http():
    pass 

9.腳本調用執行

直接使用

pytest.main()

像命令行一樣傳遞參數

pytest.main(["-x", "mytestdir"])

 

用例編寫

斷言

pytest直接使用python assert語法來寫

def f():
    return 3

def test_function():
    assert f() == 4

斷言中添加消息

assert a % 2 == 0, "value was odd, should be even"

預設與清理

與unittest中的setup和teardown類似,pytest也有這樣的環境清理方法,主要有

  • 模塊級(setup_module/teardown_module)開始於模塊始末,全局的

  • 函數級(setup_function/teardown_function)只對函數用例生效(不在類中)

  • 類級(setup_class/teardown_class)只在類中前后運行一次(在類中)

  • 方法級(setup_method/teardown_method)開始於方法始末(在類中)

  • 類里面的(setup/teardown)運行在調用方法的前后

import pytest

class TestClass:
    
    def setup_class(self):
        print("setup_class:類中所有用例執行之前")

    def teardown_class(self):
        print("teardown_class:類中所有用例執行之前")

    def setup_method(self):
        print("setup_method:  每個用例開始前執行")

    def teardown_method(self):
        print("teardown_method:  每個用例結束后執行")

    def setup(self):
        print("setup: 每個用例開始前執行")

    def teardown(self):
        print("teardown: 每個用例結束后執行")

    def test_one(self):
        print("執行第一個用例")

    def test_two(self):
        print("執行第二個用例")

def setup_module():
    print("setup_module:整個.py模塊只執行一次")

def teardown_module():
    print("teardown_module:整個.py模塊只執行一次")

def setup_function():
    print("setup_function:每個方法用例開始前都會執行")

def teardown_function():
    print("teardown_function:每個方法用例結束前都會執行")

def test_three():
        print("執行第三個用例")

使用pytest -s test_sample.py運行,-s參數是為了顯示用例的打印信息,下面是輸出,可以看出幾個方法之間的優先級

test_sample.py setup_module:整個.py模塊只執行一次
setup_class:類中所有用例執行之前
setup_method:  每個用例開始前執行
setup: 每個用例開始前執行
執行第一個用例
.teardown: 每個用例結束后執行
teardown_method:  每個用例結束后執行
setup_method:  每個用例開始前執行
setup: 每個用例開始前執行
執行第二個用例
.teardown: 每個用例結束后執行
teardown_method:  每個用例結束后執行
teardown_class:類中所有用例執行之前
setup_function:每個方法用例開始前都會執行
執行第三個用例
.teardown_function:每個方法用例結束前都會執行
teardown_module:整個.py模塊只執行一次

注意:setup_method和teardown_method的功能和setup/teardown功能是一樣的,一般二者用其中一個即可;函數里面用到的setup_function/teardown_function與類里面的setup_class/teardown_class互不干涉

參數化

使用pytest.mark.parametrize(argnames, argvalues)可以實現函數的參數化

@pytest.mark.parametrize('text',['test1','test2','test3'])
def test_one(text):
    print(text)

argnames就是形參名稱,argvalues就是待測的一組數據

 

固件fixture

基本使用

固件Fixture是一些函數,pytest 會在執行測試函數之前(或之后)加載運行它們。主要是為一些單獨測試用例需要預先設置與清理的情況下使用的。

不同於上面的setup和teardown的就是,可以自定義函數,可以指定用例運行,使用方法如下

@pytest.fixture()
def text():
    print("開始執行")          #使用pytest.fixture()裝飾一個函數成為fixture

def test_one():
    print("執行第一個用例")

def test_two(text):          #用例傳入fixture函數名,以此來確認執行
    print("執行第二個用例")

使用yield可以實現固件的拆分運行,yield前在用例前執行,yield后再用例后執行

@pytest.fixture()
def text():
    print("開始執行")
    yield                 #yield 關鍵詞將固件分為兩部分,yield 之前的代碼屬於預處理,會在測試前執行;yield 之后的代碼屬於后處理,將在測試完成后執行
    print("執行完畢")

def test_one():
    print("執行第一個用例")

def test_two(text):
    print("執行第二個用例")

統一管理

固件可以直接定義在各測試腳本中,就像上面的例子。更多時候,我們希望一個固件可以在更大程度上復用,這就需要對固件進行集中管理。Pytest 使用文件 conftest.py 集中管理固件。

不用顯式調用 conftest.py,pytest 會自動調用,可以把 conftest 當做插件來理解

./conftest.py

@pytest.fixture()
def text():
    print("開始執行")
    yield
    print("執行完畢")

./test_sample.py

def test_one():
    print("執行第一個用例")

def test_two(text):
    print("執行第二個用例")

作用域

fixture可以通過 scope 參數聲明作用域,比如

  • function: 函數級,每個測試函數都會執行一次固件;
  • class: 類級別,每個測試類執行一次,所有方法都可以使用;
  • module: 模塊級,每個模塊執行一次,模塊內函數和方法都可使用;
  • session: 會話級,一次測試只執行一次,所有被找到的函數和方法都可用。
./conftest.py

@pytest.fixture(scope="module")
def text():
    print("開始執行")
    yield
    print("執行完畢")

./test_sample.py

def test_one(text):
    print("執行第一個用例")

def test_two(text):
    print("執行第二個用例")

執行情況

test_sample.py 開始執行
執行第一個用例
.執行第二個用例
.執行完畢

如果對於類使用作用域,需要使用 pytest.mark.usefixtures(對函數和方法也適用)

./conftest.py

@pytest.fixture(scope="class")
def text():
    print("開始執行")
    yield
    print("執行完畢")

./test_sample.py

@pytest.mark.usefixtures('text')
class TestClass:

    def test_one(self):
        print("執行第一個用例")

    def test_two(self):
        print("執行第二個用例")

自動運行

將fixture的autouse參數設置為True時,可以不用傳入函數,自動運行

./conftest.py

@pytest.fixture(scope="module",autouse=True)
def text():
    print("開始執行")
    yield
    print("執行完畢")

./test_sample.py

def test_one():
    print("執行第一個用例")

def test_two():
    print("執行第二個用例")

參數化

使用fixture的params參數可以實現參數化

./conftest.py

@pytest.fixture(scope="module",params=['test1','test2'])
def text(request):
    print("開始執行")
    yield request.param
    print("執行完畢")

./test_sample.py

def test_one(text):
    print("執行第一個用例")
    print(text)

def test_two(text):
    print("執行第二個用例")

固件參數化需要使用 pytest 內置的固件 request,並通過 request.param 獲取參數。

結果如下

test_sample.py 開始執行
執行第一個用例
test1
.執行第二個用例
.執行完畢
開始執行
執行第一個用例
test2
.執行第二個用例
.執行完畢

 

生成報告

HTML報告

安裝pytest-html

pip install pytest-html

使用方法是,直接在命令行pytest命令后面加--html=<文件名字或者路徑>.html參數就可以了

pytest --html=report.html

結果如下

上面生成的報告包括html和一個assets文件(里面是報告CSS樣式),如果要合成一個文件可以添加下面的參數

pytest --html=report.html --self-contained-html

 

XML報告

使用命令可以生成XML格式報告

pytest --junitxml=report.xml

 

allure報告

1.首先安裝java環境

下載JDK  http://www.oracle.com/technetwork/java/javase/downloads/index.html 

安裝對應系統的包,如windowsx64是xxx-windows-x64.exe

一路下一步安裝就可以了

然后在環境變量中添加下面變量

變量名:JAVA_HOME
變量值:C:\Program Files (x86)\Java\jdk1.8.0_91        // 要根據自己的實際路徑配置

變量名:CLASSPATH
變量值:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;      //記得前面有個"."

變量名:Path
變量值:%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;

然后再cmd中運行 java -versionjavajavac 幾個命令沒有報錯即可

 

2.安裝allure

下載allure 會跳轉到github,找到link下載

解壓包后進入bin文件,復制路徑並添加到環境變量Path中

 cmd運行allure命令,沒有報錯即正確

 

3.pytest使用

安裝插件

pip install allure-pytest 

如果timeout就加   --index-url https://pypi.douban.com/simple  用豆瓣源

進入測試py文件目錄,運行

pytest --alluredir ./report

運行完成后生成report文件,-alluredir后面跟的是文件路徑,可以自定義

使用allure查看報告,直接啟動allure server后面加報告路徑就行

allure serve report(報告文件夾名)

等一會就生成報告

 

 

 

 

 

參考:

https://learning-pytest.readthedocs.io/zh/latest/index.html

https://docs.pytest.org/en/latest/contents.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM