pytest

  1. 導(dǎo)包 import unittest
  2. 測試類以Test開頭
  3. 測試方法名稱必須以test開頭

pytest命令行運行
pytest test_case.py
顯示詳細信息
pytest -v test_case.py
pytest -v --return 2 --html=./report/demo_test_report.html test_case.py

Pytest的setup和teardown函數(shù)

1.setup和teardown主要分為:模塊級,類級,功能級,函數(shù)級。
2.存在于測試類內(nèi)部

import pytest


class TestABC(object):
    # 測試類級開始
    def setup_class(self):
        print("------->setup_class")

    # 測試類級結(jié)束
    def teardown_class(self):
        print("------->teardown_class")

    # 函數(shù)級開始
    def setup(self):
        print("------->setup_method")

    # 函數(shù)級結(jié)束
    def teardown(self):
        print("------->teardown_method")

    def test_a(self):
        print("------->test_a")
        assert 1

    def test_b(self):
        print("------->test_b")
        assert 0


if __name__ == '__main__':
    pytest.main()
Pytest配置文件

pytest的配置文件通常放在測試目錄下,名稱為pytest.ini,命令行運行時會使用該配置文件中的配置.
文件第一行 [pytest]

  • 配置pytest命令行運行參數(shù)
    詳細信息輸出 -v
    addopts = -v
    空格分隔,可添加多個命令行參數(shù) -所有參數(shù)均為插件包的參數(shù)
    例如:addopts = -v --return 2 --html=./report/report.html
  • 配置測試搜索的路徑
    當前目錄下的scripts文件夾 -可自定義
    testpaths = ./scripts
  • 配置測試搜索的文件名
    以test_開頭,以.py結(jié)尾的所有文件 -可自定義
    python_files = test_*.py
    -配置測試搜索的測試類名
    以Test_開頭的類 -可自定義
    python_classes = Test_*
  • 配置測試搜索的測試函數(shù)名
    以test_開頭的方法 -可自定義
    python_functions = test_*
Pytest常用插件

插件列表:https://plugincompat.herokuapp.com

  • html測試報告
    插件名稱:pytest-html
    命令行格式:
    pytest --html=用戶路徑/report.html
    pytest --html=用戶路徑/report.xml
    例如:pytest -s --html=./report.html test_abc.py

  • Pytest控制函數(shù)執(zhí)行順序
    函數(shù)修飾符的方式標記被測試函數(shù)執(zhí)行的順序,默認情況下,pytest是根據(jù)測試方法名由小到大執(zhí)行的,可以通過第三方插件包改變其運行順序。
    插件名稱:pytest-ordering
    @pytest.mark.run(order=x)修飾函數(shù)

    @pytest.mark.run(order=2)
    def test_a(self):
        print('\n-----------a')
        assert 1

    @pytest.mark.run(order=1)
    def test_b(self):
        print('\n------------b')
        assert 0

"""
test_abc.py 
------------b
F
-----------a
.
"""
  • Pytest失敗重試
    通過命令行方式,控制失敗函數(shù)的重試次數(shù)
    插件名稱:pytest-rerunfailures
    命令行格式:pytest --reruns n
    n:為重試的次數(shù)
    例如:pytest -s --return 2 --html=./report.html test_abc.py
fixture

fixture修飾器來標記固定的工廠函數(shù),在其他函數(shù),模塊,類或整個工程調(diào)用它時會被激活并優(yōu)先執(zhí)行,通常會被用于完成預(yù)置處理和重復(fù)操作。
比如測試用例的前置條件 的方法,可以用fixture修飾,在需要該前置條件的測試方法前調(diào)用。

方法:fixture(scope="function", params=None, autouse=False, ids=None, name=None)
常用參數(shù):
scope:被標記方法的作用域
??function" (default):作用于每個測試方法,每個test都運行一次
??"class":作用于整個類,每個class的所有test只運行一次
??"module":作用于整個模塊,每個module的所有test只運行一次
??"session:作用于整個session(慎用),每個session只運行一次
params:(list類型)提供參數(shù)數(shù)據(jù),供調(diào)用標記方法的函數(shù)使用
autouse:是否自動運行,默認為False不運行,設(shè)置為True自動運行

import pytest


# --------------------------- 通過參數(shù)引用 函數(shù)級別 傳入before的測試方法執(zhí)行前會執(zhí)行before------------------------------
class TestAAA(object):
    @pytest.fixture()
    def before(self):
        print("------->before")

    def test_a1(self, before):
        print("------->test_a1")
        assert 1

    # 一般用這種方式
    @pytest.mark.usefixtures("before")
    def test_a2(self):
        print("------->test_a2")
        assert 1


# --------------------------- 通過函數(shù)引用 函數(shù)級別 TestBBB類中每個測試方法執(zhí)行前都會執(zhí)行before_outter_class------------------------------
@pytest.fixture()
def before_outter_class():
    print("------->outter class before")


@pytest.mark.usefixtures("before_outter_class")
class TestBBB(object):
    def setup(self):
        print('-------classBBB setup')

    def test_b1(self):
        print("------->test_b1")
        assert 1

    def test_b2(self):
        print("------->test_b2")
        assert 1


# --------------------------- 設(shè)置為默認運行 函數(shù)級別 每個測試方法執(zhí)行前都會自動執(zhí)行------------------------------
@pytest.fixture(autouse=True)
def before_outter_class_c():
    print("------->outter class before ccccc")


class TestCCC(object):
    def setup(self):
        print('-------classCCC setup')

    def test_c(self):
        print("------->test_c")
        assert 1


# --------------------------- 設(shè)置作用域 默認是函數(shù)級別------------------------------
# class級別 TestDDD類中測試方法執(zhí)行前執(zhí)行一次before_outter_class_d()
@pytest.fixture(scope='class', autouse=True)
def before_outter_class_d():
    print("------->outter class before ddddd")


class TestDDD(object):
    def setup(self):
        print('-------classDDDD setup')

    def test_d1(self):
        print("------->test_d1")
        assert 1

    def test_d2(self):
        print("------->test_d2")
        assert 1


# --------------------------- 返回值------------------------------
@pytest.fixture(params=[1, 2, 3])
def need_data(request):
    return request.param


class TestABC(object):

    def test_abc(self, need_data):
        print("------->test_abc")
        # 拿到返回值做一次斷言   會執(zhí)行3次
        assert need_data != 2
    
    # 注意:@pytest.mark.usefixtures("need_data") 這種方式拿不到返回值
    @pytest.mark.usefixtures("need_data")
    def test_abc222(self):
        print("------->test_abc222")
        assert False
跳過測試函數(shù)

方法:
skipif(condition, reason=None)
參數(shù):
condition:跳過的條件,必傳參數(shù)
reason:標注原因,必傳參數(shù)
使用方法:
@pytest.mark.skipif(condition, reason="xxx")

    # 跳過測試函數(shù)test_b
    @pytest.mark.skipif(condition=True, reason="就是不想執(zhí)行")
    def test_b(self):
        print("------->test_b")
        assert 0
標記為預(yù)期失敗函數(shù)

方法:
xfail(condition=None, reason=None, raises=None, run=True, strict=False)
常用參數(shù):
condition:預(yù)期失敗的條件,必傳參數(shù)
reason:失敗的原因,必傳參數(shù)
使用方法:
@pytest.mark.xfail(condition, reason="xx")

    # 標記為預(yù)期失敗函數(shù)test_c
    @pytest.mark.xfail(condition=2 > 1, reason="標注為預(yù)期失敗")
    def test_c(self):
        print("------->test_c")
        assert 0
函數(shù)數(shù)據(jù)參數(shù)化

方法:
parametrize(argnames, argvalues, indirect=False, ids=None, scope=None)
常用參數(shù):
argnames:參數(shù)名
argvalues:參數(shù)對應(yīng)值,類型必須為list
當參數(shù)為一個值時格式:[value]
當參數(shù)個數(shù)大于一個時,格式為:[(param_value1,param_value2.....),(param_value1,param_value2.....)]
使用方法:
@pytest.mark.parametrize(argnames,argvalues)
?? 參數(shù)值為N個,測試方法就會運行N次

# --------------------------- 單個參數(shù) ---------------------------------
class TestAAA(object):
    def setup_class(self):
        print("------->setup_class")

    def teardown_class(self):
        print("------->teardown_class")

    @pytest.mark.parametrize("a", [3, 6])  # a參數(shù)被賦予兩個值,函數(shù)會運行兩遍
    def test_a(self, a):  # 參數(shù)必須和parametrize里面的參數(shù)一致
        print("test data:a=%d" % a)
        assert a % 3 == 0


# --------------------------- 多個參數(shù) ---------------------------------
def get_test_data():
    return [(1, 2), (0, 3)]


class TestBBB:
    def setup_class(self):
        print("------->setup_class bbb")

    def teardown_class(self):
        print("------->teardown_class bbb")

    # 參數(shù)a,b均被賦予兩組值,函數(shù)會運行兩遍
    # @pytest.mark.parametrize("a,b", [(1, 2), (0, 3)])
    @pytest.mark.parametrize("a,b", get_test_data())
    # 參數(shù)必須和parametrize里面的參數(shù)一致
    def test_b(self, a, b):
        print("test data:a=%d,b=%d" % (a, b))
        assert a + b == 3
數(shù)據(jù)驅(qū)動
  • yaml
  1. yaml文件格式

語法規(guī)則
1.大小寫敏感
2.使用縮進表示層級關(guān)系
3.縮進時不允許使用Tab鍵,只允許使用空格。
4.縮進的空格數(shù)目不重要,只要相同層級的元素左側(cè)對齊即可

  1. 讀取yaml文件
    yaml.load(stream, Loader=Loader)
with open("../resouce/data.yaml", 'r') as f:
    data = yaml.load(f, Loader=yaml.FullLoader)
    print(type(data))
    print(data)
  1. 寫yaml文件
    yaml.dump(data,stream,**kwds)
    常用參數(shù):
    data:寫入數(shù)據(jù)類型為字典
    stream:打開文件對象
    encoding='utf-8' # 設(shè)置寫入編碼格式
    allow_unicode=True # 是否允許unicode編碼
data = {'Search_Data': {
    'search_test_003': {'expect': {'value': '不好了'}, 'value': '著火了'},
    'search_test_004': {'expect': [8, 8, 6], 'value': 666}}}
with open("../resouce/data.yaml", "w") as f:
    yaml.dump(data, f, encoding='utf-8', allow_unicode=True)
  1. 錨點&和引用*
    錨點:標注一個內(nèi)容,錨點名稱自定義
    引用:使用被標注的內(nèi)容<<: *錨點名
    data.yaml
     data: &imp
        value: 456
     name:
      value1: 123
      <<: *imp # "<<:" 合并到當前位置,"*imp" 引用錨點imp
    轉(zhuǎn)換為python代碼
     {'data': {'value': 456}, 'name': {'value': 456, 'value1': 123}}
生成測試報告
  • Allure
    Allure是一個獨立的報告插件,生成美觀易讀的報告,目前支持語言:Java, PHP, Ruby, Python, Scala, C#。
    幫助文檔:https://docs.qameta.io/allure/#_about
    生成Allure報告
    pytest --alluredir report # 在執(zhí)行命令目錄生成report文件夾,文件夾下包含xml文件
  • xml轉(zhuǎn)html工具安裝
  1. Mac版本
    (1)brew install allure
    (2)進入report上級目錄執(zhí)行命令:allure generate report/ -o report/html
    (3)report目錄下會生成index.html文件,即為可視化報告
  2. windows版本
    (1)下載壓縮包allure-2.5.0.zip 解壓
    (2)將壓縮包內(nèi)的bin目錄配置到path系統(tǒng)環(huán)境變量
    (3)進入report上級目錄執(zhí)行命令:allure generate report/ -o report/html
    (4)report目錄下會生成index.html文件,即為可視化報告

添加測試步驟
@allure.step(title="測試步驟001")
添加測試描述
allure.attach('描述', '我是測試步驟001的描述~~~')
添加嚴重級別
@pytest.allure.severity(Severity)
參數(shù) Severity:嚴重級別(BLOCKER,CRITICAL,NORMAL,MINOR,TRIVIAL)
使用方式:@pytest.allure.severity(pytest.allure.severity_level.CRITICAL)

test_all.py
        import allure, pytest
        class Test_allure:
            def setup(self):
                pass
            def teardown(self):
                pass
            @pytest.mark.parametrize("a",[1,2,3])
            @pytest.allure.severity(pytest.allure.severity_level.CRITICAL)
            @allure.step('我是測試步驟001')
            def test_al(self, a):
                allure.attach('描述', '我是測試步驟001的描述~~~')
                assert a != 2

allure嚴重級別.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容