0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一文了解Python的Pytest架構(gòu)及相關(guān)內(nèi)容

馬哥Linux運(yùn)維 ? 來源:cnblogs ? 2023-11-15 10:12 ? 次閱讀

在之前的文章里我們已經(jīng)學(xué)習(xí)了Python自帶測試框架UnitTest,但是UnitTest具有一定的局限性

這篇文章里我們來學(xué)習(xí)第三方框架Pytest,它在保留了UnitTest框架語法的基礎(chǔ)上有著更多的優(yōu)化處理

下面我們將從以下角度來介紹Pytest:

Pytest基本介紹

Pytest基本使用

Pytest進(jìn)階內(nèi)容

Pytest基本介紹

下面我們首先來簡單介紹Pytest及相關(guān)內(nèi)容

單元測試框架

我們首先需要知道測試一般分為四個(gè)方面的測試:

單元測試:稱模塊測試,針對(duì)軟件設(shè)計(jì)中的最小單位——程序模塊,進(jìn)行正確性檢查的測試工作

集成測試:稱組裝測試,通常在單元測試的基礎(chǔ)上,將所有程序模塊進(jìn)行有序的、遞增測試,重點(diǎn)測試不同模塊的接口部分

系統(tǒng)測試:將整個(gè)軟件系統(tǒng)看成一個(gè)整體進(jìn)行測試,包括對(duì)功能、性能以及軟件所運(yùn)行的軟硬件環(huán)境進(jìn)行測試

驗(yàn)收測試:指按照項(xiàng)目任務(wù)書或合同、供需雙方約定的驗(yàn)收依據(jù)文檔進(jìn)行的對(duì)整個(gè)系統(tǒng)的測試與評(píng)審,決定是否接收或拒收系統(tǒng)

而我們這篇文章主要針對(duì)的是單元測試:

Python:通常使用UnitTest和Pytest來進(jìn)行單元測試自動(dòng)化,但Pytest已經(jīng)成為主流

Java:通常使用Testng和Junit來進(jìn)行單元測試自動(dòng)化,但Testng已經(jīng)成為主流

最后我們需要明白單元測試框架的主要功能:

發(fā)現(xiàn)測試用例

執(zhí)行測試用例

判斷測試結(jié)果

生成測試報(bào)告

框架基本介紹

下面我們來簡單介紹Pytest框架:

pytest是一個(gè)非常成熟的單元測試框架,經(jīng)過多版本的迭代,主要優(yōu)點(diǎn)在于靈活和簡單

pytest具有極強(qiáng)的兼容性和生態(tài)環(huán)境,它可以結(jié)合selenium,requests,appium完成各種不同的自動(dòng)化

pytest具有更好的頁面展示效果,它可以生成自定義allure報(bào)告以及和Jenkins持續(xù)集成

下面我們給出一些和Pytest框架可以很好聚合的框架類型:

pytestpytest-html:主要用來生成html報(bào)告的插件

pytest-xdist:主要用來進(jìn)行多線程運(yùn)行的插件

pytest-ordering:主要用來改變用例的執(zhí)行順序的插件

pytest-rerunfailres:主要用來失敗用例重跑的插件

allure-pytest:主要用來生成美觀自定義的allure報(bào)告

我們可以采用一種比較簡便的方式來一次性下載這些框架:

# 首先我們需要將這些名稱全部放入一個(gè)txt文件中,假設(shè)我們放在requestment.txt文件中

# requestment.txt文件
pytest-html
pytest-xdist
pytest-ordering
pytest-rerunfailures

# 我們只需要在pycharm的console中輸入指令下載該文件夾中全部內(nèi)容即可
pip install -r requirements.txt

Pytest基本使用

下面我們來介紹Pytest的基本使用

Pytest默認(rèn)測試用例

下面我們首先講解Pytest默認(rèn)測試用例的格式:

# 首先我們的模塊名(文件名)通常被統(tǒng)一存放在一個(gè)testcases文件夾中,然后需要保證模塊名須以test_開頭或者_(dá)test結(jié)尾
# 例如我們下面的模塊名命名就是正確示例
test_demo1
demo2_test

# 然后我們需要注意我們模塊中的測試類類名必須以Test開頭,并且不能帶有init方法
# 例如我們下面的類名命名就是正確示例
class TestDemo1:
class TestLogin:

# 最后我們需要注意我們測試類中的測試方法名(Case名)必須以test_開頭
# 例如我們下面的模塊名命名就是正確示例
test_demo1(self)
test_demo2(self)

# 我們給出一個(gè)測試用例例子:
# 文件名為test_demo1
class TestDemo:
    def test_demo1(self):
        print("測試用例1")

    def test_demo2(self):
        print("測試用例2")
        
# 當(dāng)然我們上述的要求都不是必須相同的,在后續(xù)我們可以進(jìn)行修改,我們將在下述講解執(zhí)行方法時(shí)講解

然后我們?cè)賮碇v解一下Pytest的測試用例該如何執(zhí)行:

# 首先我們講解一下全局配置文件pytest.ini
# 我們可以在pytest.ini中進(jìn)行一些屬性的配置來修改Pytest的默認(rèn)屬性,我們需要在項(xiàng)目的根目錄下創(chuàng)建,名稱必須是pytest.ini

1 [pytest]
2 #參數(shù)
3 addopts = ‐vs # 這里指當(dāng)默認(rèn)使用指令時(shí)的一些輔助參數(shù),我們后面會(huì)講解
4 testpaths = ./testcases# 這里指默認(rèn)的執(zhí)行路徑,它會(huì)默認(rèn)執(zhí)行該文件夾下所有的滿足條件的測試case
5 python_files = test_*.py# 這里就是前面我們所說的文件命名規(guī)則
6 python_classes = Test*# 這里就是前面我們所說的類名命名規(guī)則
7 python_functions = test_*# 這里就是前面我們所說的Case命名規(guī)則
8 #標(biāo)記
9 markers =# 這里是冒煙規(guī)則,我們后面會(huì)講到
10 smoke:冒煙用例 
11 product_manage:商品管理


# 然后我們首先來講采用console命令行執(zhí)行Pytest的方法
# 最簡單的就是直接在console命令行輸入pytest,如果存在pytest.ini,它會(huì)根據(jù)文件內(nèi)容進(jìn)行執(zhí)行;如果沒有就按照默認(rèn)格式執(zhí)行
# 但是我們可以通過一些參數(shù)來強(qiáng)化pytest參數(shù)指令

# -vs: -v輸出詳細(xì)信息 -s輸出調(diào)試信息
pytest -vs

# -n: 多線程運(yùn)行(前提安裝插件:pytest-xdist)
pytest -vs -n=2

# --reruns num: 失敗重跑(前提安裝插件:pytest-rerunfailres)
pytest -vs --reruns=2

# -x: 出現(xiàn)一個(gè)用例失敗則停止測試
pytest -vs -x

# --maxfail: 出現(xiàn)幾個(gè)失敗才終止
pytest -vs --maxfail=2

# --html: 生成html的測試報(bào)告,后面 需要跟上所創(chuàng)建的文件位置及文件名稱(前提安裝插件:pytest-html)
pytest -vs --html ./reports/result.html

# -k: 運(yùn)行測試用例名稱中包含某個(gè)字符串的測試用例,我們可以采用or表示或者,采用and表示都
# 采用or就表示:我們的運(yùn)行用例名稱中包含or兩側(cè)的其中一個(gè)數(shù)據(jù)即可
# 采用and就表示:我們的運(yùn)行用例名稱中包含and兩側(cè)的所有數(shù)據(jù)才滿足條件
pytest -vs -k "qiuluo"
pytest -vs -k "qiuluo or weiliang"
pytest -vs -k "qiuluo and weiliang"

# -m:冒煙用例執(zhí)行,后面需要跟一個(gè)冒煙名稱
# 我們?cè)谶@里簡單介紹一下冒煙用例的執(zhí)行方法,我們這里其實(shí)就是一個(gè)分組執(zhí)行的方法
# 例如我們的用例劃分為user_manage用戶管理測試和product_manage商品管理測試,我們只希望執(zhí)行其中一組測試

# 首先我們需要在他們的不同方法上進(jìn)行@mark劃分,具體操作如下:
class TestDemo:
    
    # 我們?cè)贑ase上采用@pytest.mark. + 分組名稱,就相當(dāng)于該方法被劃分為該分組中
    # 注意:一個(gè)分組可以有多個(gè)方法,一個(gè)方法也可以被劃分到多個(gè)分組中
    @pytest.mark.user_manage
    def test_demo1(self):
        print("user_manage_test1")

    @pytest.mark.product_manage
    def test_demo2(self):
        print("product_manage_test1")
     
    @pytest.mark.user_manage
    @pytest.mark.product_manage
    def test_demo3(self):
        print("manage_test1")

# 我們?cè)趫?zhí)行中只需要采用前面我們所說的-m + 分組名稱即可
pytest -vs -m user_manage

# 這里插一句,我們?cè)谶\(yùn)行過程中可以采用拋出異常的方式來模擬測試失?。簉aise Exception() 拋出異常


# 最后我們也可以采用main方法來執(zhí)行pytest,同樣我們也可以使用參數(shù)來進(jìn)行調(diào)節(jié)
if __name__ == '__main__':
pytest.main()
    
if __name__ == '__main__':
pytest.main(["‐vs"])

最后我們插入一個(gè)簡單的案例跳過方法:

# pytest的跳過案例方法其實(shí)和unittest是完全相同的
# 我們只需要采用skip或skipif方法來指定參數(shù)并貼在方法上即可跳過

# @pytest.mark.skip(跳過原因)

# @pytest.mark.skipif(跳過條件,跳過原因)

# 我們給出一個(gè)示例
class TestDemo:
    
    workage2 = 5
    workage3 = 20
    
    @pytest.mark.skip(reason="無理由跳過")
    def test_demo1(self):
        print("我被跳過了")

    @pytest.mark.skipif(workage2<10,reason="工作經(jīng)驗(yàn)少于10年跳過")    
    def test_demo2(self):
        print("由于經(jīng)驗(yàn)不足,我被跳過了")
    
    @pytest.mark.skipif(workage3<10,reason="工作經(jīng)驗(yàn)少于10年跳過")
    def test_demo3(self):
        print("由于經(jīng)驗(yàn)過關(guān),我被執(zhí)行了")
        
    def test_demo3(self):
        print("我沒有跳過條件,所以我被執(zhí)行了")

Pytest前后置方法

首先我們需要先了解前后置是什么:

前后置就是針對(duì)不同層級(jí)方法執(zhí)行前和執(zhí)行后所需要執(zhí)行的步驟進(jìn)行封裝并執(zhí)行

這個(gè)層級(jí)通常被劃分為:文件層,類層,方法層

首先我們先來介紹Pytest通過固件來實(shí)現(xiàn)前后置的方法:

# 我們通常采用前后置來做一些方法前后的操作
# 如果我們采用方法層的前后置,那么它會(huì)在每個(gè)方法執(zhí)行前后去執(zhí)行該內(nèi)容
# 如果我們采用類層的前后置,那么它會(huì)在調(diào)用這個(gè)類內(nèi)所有方法的前后去執(zhí)行該內(nèi)容,但是無論該類的方法執(zhí)行多少次,它只會(huì)調(diào)用一次
# 例如我們做login測試時(shí),我們只需要在開始測試時(shí)打開一次瀏覽器,然后在測試結(jié)束時(shí)關(guān)閉一次瀏覽器,那么我們就采用類的前后置
# 我們做login測試時(shí),為了保證前置操作不對(duì)后續(xù)Case有影響,所以我們?cè)趫?zhí)行方法前打開該網(wǎng)頁,執(zhí)行方法后關(guān)閉該網(wǎng)頁,采用方法的前后置

# Pytest的固件前后置其實(shí)和unittest是基本相同的
# 首先是方法級(jí)別的固件前后置
# 它是在每個(gè)測試方法(用例代碼) 執(zhí)行前后都會(huì)自動(dòng)調(diào)用的結(jié)構(gòu)
# 方法執(zhí)行之前
def setUp(self):
每個(gè)測試方法執(zhí)行之前都會(huì)執(zhí)行
pass
# 方法執(zhí)行之后
def tearDown(self):
每個(gè)測試方法執(zhí)行之后都會(huì)執(zhí)行
pass
    
# 然后是針對(duì)類級(jí)別的固件前后置
# 它是在每個(gè)測試類中所有方法執(zhí)行前后 都會(huì)自動(dòng)調(diào)用的結(jié)構(gòu)(在整個(gè)類中執(zhí)行之前或之后執(zhí)行一次)
# 需要注意:類級(jí)別的固件前后置, 是一個(gè)類方法
# 類中所有方法之前
    @classmethod
    def setUpClass(cls):
    pass
# 類中所有方法之后
@classmethod
def tearDownClass(cls):
pass
    
# 最后是針對(duì)模塊級(jí)別的固件前后置
# 在每個(gè)代碼文件執(zhí)行前后執(zhí)行的代碼結(jié)構(gòu)
# 需要注意:模塊級(jí)別的需要寫在類的外邊直接定義函數(shù)即可
# 代碼文件之前
def setUpModule():
pass
# 代碼文件之后
def tearDownModule():
pass
    
# 下面我們采用一個(gè)用戶賬戶登錄的用例來簡單展示一下固件前后置

import unittest

class TestLogin(unittest.TestCase):
    
    # 在執(zhí)行該類前所需要調(diào)用的方法
    @classmethod
    def setUpClass(cls) -> None:
    print('------打開瀏覽器')
    
    # 在執(zhí)行該類后所需要調(diào)用的方法
    @classmethod
    def tearDownClass(cls) -> None:
    print('------關(guān)閉瀏覽器')
    
    # 每個(gè)測試方法執(zhí)行之前都會(huì)先調(diào)用的方法
    def setUp(self):
    print('輸入網(wǎng)址......')
    
    # 每個(gè)測試方法執(zhí)行之后都會(huì)調(diào)用的方法
    def tearDown(self) -> None:
    print('關(guān)閉當(dāng)前頁面......')
    
    # 測試Case1
    def test_1(self):
    print('輸入正確用戶名密碼驗(yàn)證碼,點(diǎn)擊登錄 1')
  
# 測試Case2
    def test_2(self):
    print('輸入錯(cuò)誤用戶名密碼驗(yàn)證碼,點(diǎn)擊登錄 2')

然后我們還需要講解一下Fixtrue實(shí)現(xiàn)前后置的方法:

# 首先我們需要知道Fixtrue所實(shí)現(xiàn)的功能基本和固件所實(shí)現(xiàn)的功能是一樣的,但是會(huì)更加方便
# 首先我們給出Fixture的完整格式,然后我們?cè)俜珠_介紹各個(gè)參數(shù)
@pytest.fixture(scope=None,autouse=False,params=None,ids=None ,name=None)

# scope:作用范圍
# 參數(shù)主要有三種:function函數(shù),class類,package/session包

# function:在函數(shù)層面上執(zhí)行前后置
# 我們通常采用yield進(jìn)行前后置劃分,yield前是前置,yield后是后置
@pytest.fixture(scope="function")
def exe_database_sql():
print("執(zhí)行SQL查詢")
yield
print("關(guān)閉數(shù)據(jù)庫連接")
# 我們還可以通過yield或return去返回一些參數(shù)在方法中使用
# 但是需要注意,yield返回參數(shù)后后置仍舊可以執(zhí)行,但是return返回參數(shù)后后置操作無法執(zhí)行
@pytest.fixture(scope="function")
def exe_database_sql():
print("執(zhí)行SQL查詢")
yield "success"
      # return "success" 執(zhí)行后無法執(zhí)行后置操作
print("關(guān)閉數(shù)據(jù)庫連接")
# 我們的方法在調(diào)用時(shí),可以直接使用exe_database_sql表示返回信息進(jìn)行輸出
def test_2(self,exe_database_sql):
    print(exe_database_sql)
        
# class:在類之前和之后執(zhí)行
@pytest.fixture(scope="class")
def exe_database_sql():
print("執(zhí)行SQL查詢")
yield
print("關(guān)閉數(shù)據(jù)庫連接")
        
# package/session:在整個(gè)項(xiàng)目會(huì)話之前和之后執(zhí)行
@pytest.fixture(scope="session")
def exe_database_sql():
print("執(zhí)行SQL查詢")
yield
print("關(guān)閉數(shù)據(jù)庫連接")

        
# autouse:是否自動(dòng)啟動(dòng)
# 該參數(shù)默認(rèn)為False,我們可以將其修改為True
# 該參數(shù)的功能主要在判斷該固件是否在自定義范圍內(nèi)可以自動(dòng)啟動(dòng)
# 若自動(dòng)啟動(dòng),則所有方法在執(zhí)行時(shí)都會(huì)自動(dòng)執(zhí)行該前后置;但若為False,則我們需要手動(dòng)啟動(dòng)

# 首先如果是自動(dòng)啟動(dòng),則我們無需關(guān)心任何參數(shù),我們的所有方法都會(huì)自動(dòng)調(diào)用
@pytest.fixture(scope="function",autoues=True)
def exe_database_sql():
print("執(zhí)行SQL查詢")
yield
print("關(guān)閉數(shù)據(jù)庫連接")
        
# 但若是關(guān)閉自動(dòng)啟動(dòng),我們?cè)诓煌膕cope下有不同的調(diào)用方法
@pytest.fixture(scope="function",autoues=Flase)
def exe_database_sql():
print("執(zhí)行SQL查詢")
yield
print("關(guān)閉數(shù)據(jù)庫連接")
        
# scope = function:我們需要在方法后加上該Fixture方法名
def test_2(self,exe_database_sql):
    print(exe_database_sql)
        
# scope = class:我們需要在對(duì)應(yīng)的類上添加@pytest.mark.usefixtures("exe_database_sql")裝飾器調(diào)用
@pytest.mark.usefixtures("exe_database_sql")
class TestDemo:
    pass

# scope = session:.一般會(huì)結(jié)合conftest.py文件來實(shí)現(xiàn),我們后面再介紹

# 還需要注意autouse僅限于在自己的類中使用上述方法,如果要跨類使用,那么我們也需要在conftest.py中配置


# params:實(shí)現(xiàn)參數(shù)化配置
# 通常我們的腳本都是根據(jù)導(dǎo)出的yaml文件進(jìn)行屬性填充,針對(duì)參數(shù)化我們后面再講,我們先將Fixture的參數(shù)化
# params通常后面跟上具體的數(shù)據(jù)(列表,元組等),然后我們?cè)谡{(diào)用時(shí)有固定的寫法
# 首先我們需要在Fixture方法參數(shù)中定義一個(gè)request,然后使用request.param來使用我們傳遞的params數(shù)據(jù)
class TestDemo:
    def read_yaml():
        return ["胡桃","胡桃寶寶","胡桃廚"]
    
    # 首先我們的參數(shù)需要獲取數(shù)據(jù):params=read_yaml()
    @pytest.fixture(scope="function",autouse=False,params=read_yaml())
    # 然后我們的Fixture方法需要一個(gè)request參數(shù)
def exe_database_sql(request):
        print("執(zhí)行SQL查詢")
        # 我們通過request.param獲取數(shù)據(jù),可以采用yield返回該數(shù)據(jù)
        yield request.param
        print("關(guān)閉數(shù)據(jù)庫連接")
        

# ids:參數(shù)別名id
# 不能單獨(dú)使用,必須和params一起使用,作用是對(duì)參數(shù)起別名 
# 我們?cè)诓捎胮ytest進(jìn)行測試數(shù)據(jù)輸出時(shí)會(huì)有對(duì)應(yīng)的方法調(diào)用n次,該n次采用不同的params參數(shù),這個(gè)ids就是修改了console控制臺(tái)展示數(shù)據(jù)
class TestDemo:
    def read_yaml():
        return ["胡桃","胡桃寶寶","胡桃廚"]
    
    # 當(dāng)我們書寫了ids,我們的控制輸出就不會(huì)再是上面的["胡桃","胡桃寶寶","胡桃廚"],而是我們所書寫的["1","2","3"]
    @pytest.fixture(scope="function",autouse=False,params=read_yaml(),ids=["1","2","3"])
def exe_database_sql(request):
        print("執(zhí)行SQL查詢")
        # 我們通過request.param獲取數(shù)據(jù),可以采用yield返回該數(shù)據(jù)
        yield request.param
        print("關(guān)閉數(shù)據(jù)庫連接")
        
# name:Fixture別名
# 作用是給fixtrue起別名,一旦使用了別名,那么fixtrue的名稱就不能再用了,只能用別名
class TestDemo:
    
    # 如果我們?cè)谶@里使用到了別名
    @pytest.fixture(scope="function",name="exe_datebase_sql_name")
def exe_database_sql(request):
        print("執(zhí)行SQL查詢")
        yield 
        print("關(guān)閉數(shù)據(jù)庫連接")
        
    # 我們這里就需要使用別名進(jìn)行操作,之前的名稱無法使用
def test_2(self,exe_datebase_sql_name):
    print(exe_database_sql)    

接下來我們就將會(huì)講解到我們剛剛提到的conftest.py文件:

# 首先我們需要知道conftest.py文件的名字是固定形式,不可改變
# conftest.py文件主要就是用來存儲(chǔ)我們的Fixture,然后我們會(huì)根據(jù)該文件的不同位置來判斷可以使用的方法
# conftest可以在不同的目錄級(jí)別下創(chuàng)建,如果我們?cè)诟夸浵聞?chuàng)建,那么所有case都會(huì)使用到該Fixture
# 但是如果我們?cè)趖estcases文件夾下的某個(gè)模塊文件下創(chuàng)建conftest.py,那么它的作用范圍就只包含在該目錄下

# 根目錄創(chuàng)建的conftest.py
# 我們?cè)谠撃夸浵碌腸onftest文件里寫的所有fixture可以在任意測試類下執(zhí)行
import pytest
@pytest.fixture(scope="function",name="exe_datebase_sql_name")
def exe_database_sql():
    print("全部方法運(yùn)行前均可以執(zhí)行")
    yield 
    print("全部方法運(yùn)行后均可以執(zhí)行")
# testcases文件下的所有測試類
# 這里需要注意:我們使用conftest下的Fixture時(shí),不需要import導(dǎo)包就可以使用
import pytest
class TestDemo1:
# 測試Case1
    def test_1(self,exe_datebase_sql_name):
    print('輸入正確用戶名密碼驗(yàn)證碼,點(diǎn)擊登錄 1' + exe_datebase_sql_name)
        
# testcases文件夾下的usercases文件夾下創(chuàng)建的conftest.py
# 我們?cè)谠撃夸浵聞?chuàng)建的conftest文件里寫的所有fixture僅可以在該目錄下的測試類中使用,在其他測試類中使用會(huì)出現(xiàn)報(bào)錯(cuò)
import pytest
@pytest.fixture(scope="function",name="usercases_fixture")
def exe_database_sql():
    print("usercases方法運(yùn)行前均可以執(zhí)行")
    yield 
    print("usercases方法運(yùn)行后均可以執(zhí)行")
# testcases文件下的usercases文件夾下的測試類
import pytest
class TestUserCases1:
# 測試Case1
    def test_1(self,usercases_fixture):
    print('輸入正確用戶名密碼驗(yàn)證碼,點(diǎn)擊登錄 1' + usercases_fixture)
        
# 最后我們簡單給出一個(gè)前后置執(zhí)行順序優(yōu)先級(jí):
fixture_session > fixture_class > setup_class > fixture_function > setup

然后最后我們給出前后置執(zhí)行的一個(gè)總體邏輯順序:

查詢當(dāng)前目錄下的conftest.py文件

查詢當(dāng)前目錄下的pytest.ini文件并找到測試用例的位置

查詢用例目錄下的conftest.py文件

查詢測試用例的py文件中是否有setup,teardown,setup_class,teardown_class

再根據(jù)pytest.ini文件的測試用例的規(guī)則去查找用例并執(zhí)行

Pytest進(jìn)階內(nèi)容

最后我們?cè)賮碇v解一些pytest比較關(guān)鍵性的一些進(jìn)階內(nèi)容

Allure效果美化

我們?cè)谑褂肞ytest所生成的頁面往往不夠美觀且展示信息雜亂不好分析,所以我們通常搭載allure來實(shí)現(xiàn)界面美化:

Allure框架是一個(gè)靈活輕量級(jí)多語言測試報(bào)告工具

它不僅可以以WEB的方式展示簡介的測試結(jié)果,而且允許參與開發(fā)過程的每個(gè)人從日常執(zhí)行的測試中最大限度的提取有用信息

下面我們就來學(xué)習(xí)如何安裝使用allure:

# 首先我們需要去下載在電腦上下載allure并配置好環(huán)境變量
# 我們這里給出官網(wǎng)下載地址:https://github.com/allure-framework/allure2/releases 
# 溫馨提醒:下載鏈接在github上,如果無法打開可以刷新重試或者使用加速器梯子等輔助工具
# 環(huán)境變量的配置只需要將bin文件所在目錄放在電腦的Path路徑下即可,這里不再展示

# 第二步我們需要在pycharm上下載allure-pytest插件(如果之前pip了那個(gè)整體文件,這里應(yīng)該是已經(jīng)下載過了)
pip install allure-pytest

# 第三步我們就可以直接來生成allure的測試結(jié)果展示界面了

# 1.我們通常首先需要生成一個(gè)allure臨時(shí)Json文件
# 我們通常會(huì)加上這么一串"‐‐alluredir=./temps ‐‐clean‐alluredir"
# ‐‐alluredir = 文件生成地址 : 表示我們將allure臨時(shí)文件生成在我們所指定的相對(duì)臨時(shí)目錄下
# ‐‐clean‐alluredir : 由于每次都會(huì)生成大量文件,所以我們會(huì)在生成前清除當(dāng)前目錄下的allure文件,保證我們數(shù)據(jù)都是最新數(shù)據(jù)

# 2.我們需要依靠臨時(shí)文件來生成allure.html網(wǎng)頁
# 我們通常在main方法中執(zhí)行
if __name__ == '__main__':
    # 正常運(yùn)行
    pytest.main()
    # 休眠:主要為了JSON臨時(shí)文件的生成
    time.sleep(3)
    # allure generate 固定語句 + allure臨時(shí)JSON文件目錄 + -o 輸出指令 + allure.html生成文件目錄 + --clean 清除舊數(shù)據(jù)
    os.system("allure generate ./temps ‐o ./reports ‐‐clean")

Parametrize數(shù)據(jù)驅(qū)動(dòng)

我們通常會(huì)采用Parametrize注解來進(jìn)行數(shù)據(jù)驅(qū)動(dòng),下面我們來詳細(xì)講解一下:

# 格式:@pytest.mark.parametrize(參數(shù)名稱,參數(shù)值)
# 意義:我們會(huì)將參數(shù)名稱作為id,然后根據(jù)參數(shù)值的個(gè)數(shù)去依次調(diào)用,存在n個(gè)參數(shù)值,我們將會(huì)調(diào)用n次case

# 1.參數(shù)值為列表或元組時(shí),參數(shù)名稱可以為一個(gè)
# 首先我們這里因?yàn)槭褂脝蝹€(gè)元素的列表(元組),我們的參數(shù)名可以為一個(gè)
@pytest.mark.parametrize('caseinfo',['胡桃','胡桃寶寶','芙芙','芙芙寶寶'])
# 在方法參數(shù)里,我們需要調(diào)用parametrize的參數(shù)名稱caseinfo,需要保證一模一樣
def test_01_get_token(self,caseinfo):
    # 在這里我們可以借助參數(shù)名稱caseinfo來代替列表中的元素
    # 列表中存在幾個(gè),我們?cè)摲椒▽?zhí)行幾次,例如現(xiàn)在列表是四個(gè)元素,那么我們方法將會(huì)重復(fù)執(zhí)行四次并每次按順序賦值不同的元素
print("獲取統(tǒng)一接口鑒權(quán)碼:"+caseinfo)
    
# 2.參數(shù)值為列表的多個(gè)時(shí),參數(shù)名稱可以為多個(gè)
# 這里我們列表中嵌套了一個(gè)列表,如果我們是單參數(shù)名稱,那么輸出時(shí)就會(huì)將第一個(gè)列表['胡桃廚','胡桃寶寶']輸出出去
# 但是如果我們是多參數(shù)名稱,系統(tǒng)會(huì)自動(dòng)將第一個(gè)列表的元素分開賦值給arg1,arg2便于我們分開使用,個(gè)人還是比較推薦的
@pytest.mark.parametrize('arg1,arg2',[['胡桃廚','胡桃寶寶'],['芙芙廚','芙芙寶寶']])
# 注意:這里當(dāng)然也需要和參數(shù)名稱對(duì)應(yīng)?。?!
def test_01_get_token(self,arg1,arg2):
print("獲取統(tǒng)一接口鑒權(quán)碼:"+str(arg1)+" "+str(arg2))

我們?cè)谶M(jìn)行數(shù)據(jù)驅(qū)動(dòng)時(shí)通常會(huì)結(jié)合Yaml文件來進(jìn)行數(shù)據(jù)獲取,這里我們簡單介紹一下Yaml文件:

# yaml是一種數(shù)據(jù)格式,擴(kuò)展名可以是yaml,yml
# 支持#注釋,通過縮進(jìn)表示層級(jí),區(qū)分大小寫,且yaml文件最后獲取的結(jié)果展示是一個(gè)字典列表格式
# yaml文件經(jīng)常用于書寫配置,例如Java的Spring中的配置文件,而我們也經(jīng)常采用yaml編寫自動(dòng)化測試用例

# yaml文件通常會(huì)出現(xiàn)兩種格式

# 字典格式:如果我們正常書寫yaml文件,如下就是字典模式
name: 胡桃

# 列表模式:如果我們采用yaml中的列表,那么我們?cè)趐y獲取時(shí)也將獲得列表
msjy:
    - name1: 胡桃
    - name2: 芙芙
    - ages1: 18
    - ages2: 19
# 我們也可以利用這個(gè)特性,直接在yaml中做多個(gè)列表,來多次提取
-
name:'xxx'
    age:18
-
name:'xxx'
    age:20

# 我們這里首先給出一個(gè)解析yaml文件的示例函數(shù):
import os.path
import yaml

# 這里是獲取當(dāng)前路徑,因?yàn)槲覀冃枰业綄?duì)應(yīng)的yaml文件,那么具體路徑就需要我們進(jìn)行拼接
def get_obj_path():
    # 這里我們使用了Python的os類來進(jìn)行當(dāng)前路徑獲取,最后返回結(jié)果其實(shí)是一個(gè)String字符串
    # 我們以'common'作為分界(common是當(dāng)前文件夾的名稱,我們將該Str進(jìn)行劃分,獲取前面的部分),獲取到前面的路徑部分來進(jìn)行拼接
    return os.path.dirname(__file__).split('common')[0]

# 然后我們這里定義一個(gè)方法來解析yaml文件
def read_yaml(yamlPath):
    with open(get_obj_path() + yamlPath,mode = 'r',encoding = 'utf-8') as f:
        # 這里需要我們pip install pyyaml
        value = yaml.load(steam=f,Loader=yaml.FullLoader)
        return value
    
# 然后我們這里采用一個(gè)main方法來執(zhí)行上述用例(其實(shí)應(yīng)該在其他測試類中執(zhí)行)
if __name__ = '__main__':
    # 調(diào)用read_yaml方法并給出yaml路徑
    print(read_yaml('testcase/user_manage/get_token.yaml'))

# 了解了所有東西之前我們就可以結(jié)合之前的Parametrize來進(jìn)行操作:
# 我們這里將所需要的數(shù)據(jù)變?yōu)閞ead_yaml讀取的yaml文件內(nèi)容
@pytest.mark.parametrize('caseinfo',read_yaml('testcase/user_manage/get_token.yaml'))
def test_01_get_token(self,caseinfo):
    # 這里我們就可以獲取到y(tǒng)aml文件內(nèi)容并輸出了
print("獲取統(tǒng)一接口鑒權(quán)碼:"+caseinfo)
    
# 當(dāng)然如果我們了解我們的yaml中擁有什么元素,我們還可以采用[]的方式具體表達(dá)出來
@pytest.mark.parametrize('caseinfo',read_yaml('testcase/user_manage/get_token.yaml'))
def test_01_get_token(self,caseinfo):
print("獲取統(tǒng)一接口鑒權(quán)碼:")
    # 這里我們可以直接獲取namekey對(duì)應(yīng)的value
    print("caseinfo[name]:"+ caseinfo['name'])
    # 這里我們可以分別獲取request層下的method,url,data分別對(duì)應(yīng)的value
    print("caseinfo[name]:"+ caseinfo['request']['method'])
    print("caseinfo[name]:"+ caseinfo['request']['url'])
    print("caseinfo[name]:"+ caseinfo['request']['data'])

編輯:黃飛

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 系統(tǒng)測試
    +關(guān)注

    關(guān)注

    2

    文章

    35

    瀏覽量

    14817
  • 集成測試
    +關(guān)注

    關(guān)注

    0

    文章

    25

    瀏覽量

    8242
  • 數(shù)據(jù)庫
    +關(guān)注

    關(guān)注

    7

    文章

    3816

    瀏覽量

    64458
  • python
    +關(guān)注

    關(guān)注

    56

    文章

    4797

    瀏覽量

    84757

原文標(biāo)題:一篇文章帶你了解Python常用自動(dòng)化測試框架——Pytest

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    大功率晶閘管封裝工藝相關(guān)內(nèi)容,有沒有哪位朋友可以幫忙

    大功率晶閘管封裝工藝相關(guān)內(nèi)容,有沒有哪位朋友可以幫忙
    發(fā)表于 04-01 10:11

    。。。。GSM的相關(guān)內(nèi)容(包含AT)

    GSM相關(guān)內(nèi)容(短消息,AT指令,例程)。。。。
    發(fā)表于 07-21 19:42

    量子力學(xué)經(jīng)典相關(guān)內(nèi)容附圖使之更易理解

    量子力學(xué)經(jīng)典相關(guān)內(nèi)容附圖使之更易理解2020-8-1
    發(fā)表于 08-01 22:24

    單片機(jī)之驅(qū)動(dòng)能力的相關(guān)內(nèi)容解析

    來源:互聯(lián)網(wǎng)單片機(jī)是個(gè)比較復(fù)雜的課題,但是如果你找到正確的學(xué)習(xí)方式你就會(huì)覺得單片機(jī)點(diǎn)都不難,下面跟著小編學(xué)習(xí)下單片機(jī)篇之驅(qū)動(dòng)能力的部分相關(guān)內(nèi)容~
    發(fā)表于 10-22 19:02

    GPIO中斷相關(guān)內(nèi)容 精選資料分享

    芯片:STM32 F412這里只寫GPIO中斷相關(guān)內(nèi)容打開STM32CubeMX,鼠標(biāo)左鍵點(diǎn)擊需要設(shè)置GPIO中斷的引腳,選擇GPIO_EXTI*,鼠標(biāo)右鍵點(diǎn)擊可以設(shè)置自定義LABEL設(shè)置GPIO
    發(fā)表于 08-13 08:54

    小白求助,機(jī)甲大師機(jī)器人軟件單元測試的相關(guān)內(nèi)容

    小白求助,機(jī)甲大師機(jī)器人軟件單元測試的相關(guān)內(nèi)容
    發(fā)表于 11-22 06:15

    簡單描述下Arduino相關(guān)內(nèi)容

    什么是Arduino,今天就針對(duì)初學(xué)者簡單描述下 Arduino 相關(guān)內(nèi)容。、初識(shí)Arduino要了解Arduino就先要了解什么是單片
    發(fā)表于 11-23 08:38

    串口硬件和協(xié)議的相關(guān)內(nèi)容

    1.概述串口通信是種非常常用的通信方式,本文首先介紹了串口硬件和協(xié)議的相關(guān)內(nèi)容,然后給出個(gè)單片機(jī)與上位機(jī)通過串口通信的示例。2.串口介紹參考這份文檔3.通信協(xié)議為了方便數(shù)據(jù)傳輸,定義了
    發(fā)表于 01-19 08:20

    分享個(gè)RK3288主板適配LVDS分辨率相關(guān)內(nèi)容

    分享個(gè)RK3288主板適配LVDS分辨率相關(guān)內(nèi)容
    發(fā)表于 03-04 07:24

    高云半導(dǎo)體時(shí)序約束的相關(guān)內(nèi)容

    本手冊(cè)主要描述高云半導(dǎo)體時(shí)序約束的相關(guān)內(nèi)容,包含時(shí)序約束編輯器(Timing Constraints Editor)的使用、約束語法規(guī)范以及靜態(tài)時(shí)序分析報(bào)告(以下簡稱時(shí)序報(bào)告)說明。旨在幫助用戶快速
    發(fā)表于 09-29 08:09

    永康泰沖擊波參數(shù)及相關(guān)內(nèi)容

    永康泰沖擊波參數(shù)及相關(guān)內(nèi)容,招標(biāo)文件參數(shù)。
    發(fā)表于 05-09 15:22 ?1次下載

    淺析彈簧管壓力儀表的相關(guān)內(nèi)容

    彈簧管壓力表屬于就地指示型壓力表,就地顯示壓力的大小,不帶遠(yuǎn)程傳送顯示、調(diào)節(jié)功能。在化工場合運(yùn)用非常廣泛,接下來就為大家全面的介紹下彈簧管壓力儀表的相關(guān)內(nèi)容。
    的頭像 發(fā)表于 09-17 09:35 ?3877次閱讀

    CANOpen系列教程01_ 初識(shí)CAN與CANOpen及相關(guān)內(nèi)容

    CANOpen系列教程01_初識(shí)CAN與CANOpen及相關(guān)內(nèi)容
    的頭像 發(fā)表于 03-07 16:15 ?8974次閱讀

    AXI_GP接口和AXI_HP接口的相關(guān)內(nèi)容

    學(xué)習(xí)關(guān)于ZYNQ IP核中的GP接口和HP接口的異同,介紹關(guān)于AXI_GP接口和AXI_HP接口的相關(guān)內(nèi)容
    的頭像 發(fā)表于 07-03 14:17 ?3101次閱讀

    LDO相關(guān)內(nèi)容介紹

    在電壓轉(zhuǎn)換電路中,LDO和DC-DC電路是最常用的兩種方式,本篇主要介紹LDO相關(guān)內(nèi)容。 LDO是線性電源的種,它可以實(shí)現(xiàn)電源電壓的轉(zhuǎn)換,不過主要用在降壓領(lǐng)域。它的全稱是Low Dropout
    的頭像 發(fā)表于 11-06 11:09 ?671次閱讀
    LDO<b class='flag-5'>相關(guān)內(nèi)容</b>介紹