干貨 | 一文搞定 pytest 自動化測試框架(一)

干貨 | 一文搞定 pytest 自動化測試框架(一)

本文節(jié)選自霍格沃玆測試學院內(nèi)部教材,進階學習。

簡介

pytest 是一個成熟的全功能 Python 測試工具,可以幫助您編寫更好的程序。它與 Python 自帶的 Unittest 測試框架類似,但 pytest 使用起來更簡潔和高效,并且兼容 unittest 框架。pytest 有以下實用特性:

  • pytest 能夠支持簡單的單元測試和復雜的功能測試;
  • pytest 本身支持單元測試;
  • 可以結(jié)合 Requests 實現(xiàn)接口測試;
  • 結(jié)合 Selenium、Appium 實現(xiàn)自動化功能測試;
  • 使用 pytest 結(jié)合 Allure 集成到 Jenkins 中可以實現(xiàn)持續(xù)集成。工作中一般會使用持續(xù)集成來完成代碼集成到主干分支之后的回歸測試,通過自動化測試的手段來實現(xiàn)產(chǎn)品的快速迭代,同時還能保證產(chǎn)品的高質(zhì)量。
  • pytest 支持 315 種以上的插件;

參考網(wǎng)站:

安裝

pip install -U pytest

查看版本

pytest --version

用例的識別與運行

用例編寫規(guī)范:

  • 測試文件以 test_ 開頭(以 _test 結(jié)尾也可以)
  • 測試類以 Test 開頭,并且不能帶有 init 方法
  • 測試函數(shù)以 test_ 開頭
  • 斷言使用基本的 assert 即可

創(chuàng)建一個 python 文件,命名以 test_ 開頭(或者以 test 結(jié)尾),創(chuàng)建測試方法以 test 開頭,測試類需要以 Test 開頭。創(chuàng)建文件名為 test_add.py 文件,代碼如下:

#!/usr/bin/env python# -*- coding: utf-8 -*-def add(x, y):    return x + ydef test_add():    assert add(1, 10) == 11    assert add(1, 1) == 2    assert add(1, 99) == 100class TestClass:    def test_one(self):        x = "this"        assert "h" in x    def test_two(self):        x = "hello"        assert hasattr(x, "check")   

運行 test_add.py 文件,在命令行進入到這個文件所在的路徑,可以直接使用 pytest 命令運行,pytest 會找當前目錄以及遞查找子目錄下所有的 test_*.py 或 *_test.py 的文件,把其當作測試文件。在這些文件里,pytest 會收集符合編寫規(guī)范的函數(shù),類以及方法,當作測試用例并且執(zhí)行,執(zhí)行如下:

 $ pytest....test_add.py ..F  [100%]....self = <test_cases.test_add.TestClass object at 0x1091810d0>    def test_two(self):        x = "hello">       assert hasattr(x, "check")E       AssertionError: assert FalseE        +  where False = hasattr('hello', 'check')test_add.py:18: AssertionError===================================================== 1 failed, 2 passed in 0.05s ...

結(jié)果分析:執(zhí)行結(jié)果中,F(xiàn)代表用例未通過(斷言錯誤),.用例通過。如果有報錯會有詳細的錯誤信息。pytest 也支持 Unittest 模式的用例定義。

運行參數(shù)

pytest 帶有很多參數(shù),可以使用 pytest --help 來查看幫助文檔,下面介紹幾種常用的參數(shù):

無參數(shù)

讀取路徑下所有符合規(guī)則的文件,類,方法,函數(shù)全部執(zhí)行。使用方法如下:

pytest 或者 py.test

-v 參數(shù)

打印詳細運行日志信息,一般在調(diào)試的時候加上這個參數(shù),終端會打印出每條用例的詳細日志信息,方便定位問題。使用方法如下:

pytest -v 

-s 參數(shù)

帶控制臺輸出結(jié)果,當你的代碼里面有 print 輸出語句,如果想在運行結(jié)果中打印 print 輸出的代碼,在運行的時候可以添加 -s 參數(shù),一般在調(diào)試的時候使用,使用方法如下:

pytest -s 

-k 參數(shù)

跳過運行某個或者某些用例。

應用場景:在測試場景中,開發(fā)人員有一部分功能代碼還沒實現(xiàn),測試人員已經(jīng)將測試用例設計出來,或者測試人員發(fā)現(xiàn)了某功能上的 bug 需要開發(fā)人員修復之后再測試這部分有缺陷的測試用例,可以將這部分測試用例在運行的時候暫時跳過,等功能實現(xiàn)或者 bug 解決之后再加入運行。

使用方法如下:

pytest -k '類名' pytest -k '方法名' pytest -k '類名 and not 方法名' //運行類里所有的方法,不包含某個方法

-x 參數(shù)

遇到用例失敗立即停止運行。

應用場景:在回歸測試過程中,假如一共有10條基礎用例,當開發(fā)人員打完包提交測試的時候,需要先運行這10條基礎用例,全部通過才能提交給測試人員正式測試。如果有一條用例失敗,都將這個版本打回給開發(fā)人員。這時就可以添加 -x 參數(shù),一旦發(fā)現(xiàn)有失敗的用例即中止運行。

使用方法如下:

pytest -x

--maxfail 參數(shù)

用例失敗個數(shù)達到閥值停止運行。具體用法:

pytest --maxfail=[num] 

應用場景:在回歸測試過程中,假如一共有10條基礎用例,當開發(fā)人員打完包提交測試的時候,需要先運行這10條基礎用例,全部通過才能提交給測試人員正式測試。如果運行過程中有 [num] 條用例失敗,即中止運行,后面測試用例都放棄執(zhí)行,直接退出。這時可以使用 --maxfail 參數(shù)。

使用方法如下:

-m 參數(shù)

將運行有 @pytest.mark.[標記名] 這個標記的測試用例。

應用場景:在自動化測試過程中可以將測試用例添加標簽進行分類,比如登錄功能、搜索功能、購物車功能、訂單結(jié)算功能等,在運行的時候可以只運行某個功能的所有的測試用例,比如這個版本只想驗證登錄功能,那就在所有登錄功能的測試用例方法上面加上裝飾符 @pytest.mark.login ,運行的時候使用命令添加一個 -m 參數(shù),例如執(zhí)行 pytest -m login 命令就可以只執(zhí)行登錄功能這部分的測試用例。

使用方法如下:

pytest -m [標記名]  

運行模式

pytest 提供了多種運行模式,讓開發(fā)和調(diào)試更得心應手。指定某個模塊,執(zhí)行單獨一個 pytest 模塊。

應用場景:在編寫測試用例的時候,經(jīng)常會單獨調(diào)試某個類,或者某個方法,這時可以使用 Pycharm 里面自帶的調(diào)試方式,點擊用例方法名前面的綠色按鈕,也可以使用命令行的方式單獨運行某個用例。

pytest 中可以使用 pytest 文件名.py 單獨執(zhí)行某個 Python 文件,也可以使用 pytest 文件名.py::類名 單獨執(zhí)行某個文件中的類,使用 pytest 文件名.py::類名::方法名 單獨執(zhí)行類中的某個方法。

使用方法如下:

pytest 文件名.pypytest 文件名.py::類名pytest 文件名.py::類名::方法名

在 Pycharm 中運行 pytest 用例

干貨 | 一文搞定 pytest 自動化測試框架(一)

打開 Pycharm -> 設置 -> Tools -> Python Integrated Tools -> Testing: pytest

首先次設置成 pytest ,需要安裝 pytest,可以直接按照這個頁面的提示點擊“fix”,也可以在 Project interpreter 里面添加 pytest 依賴包。安裝完 pytest 之后,編寫的符合規(guī)則的測試用例都能被識別出來并且標出一個綠色的執(zhí)行按鈕,點擊這個按鈕也能執(zhí)行某個方法或者某個類。例如:

干貨 | 一文搞定 pytest 自動化測試框架(一)

Pycharm 設置運行方式為 pytest 之后,用例左側(cè)會顯示綠色按鈕,可以直接點擊這個按鈕來執(zhí)行這條用例。

pytest 框架結(jié)構(gòu)

與 unittest 類似,執(zhí)行用例前后會執(zhí)行 setup,teardown 來增加用例的前置和后置條件。pytest 框架中使用 setup,teardown 更靈活,按照用例運行級別可以分為以下幾類:

  • 模塊級(setup_module/teardown_module)在模塊始末調(diào)用
  • 函數(shù)級(setup_function/teardown_function)在函數(shù)始末調(diào)用(在類外部)
  • 類級(setup_class/teardown_class)在類始末調(diào)用(在類中)
  • 方法級(setup_method/teardown_methond)在方法始末調(diào)用(在類中)
  • 方法級(setup/teardown)在方法始末調(diào)用(在類中)

調(diào)用順序:

setup_module > setup_class >setup_method > setup > teardown > teardown_method > teardown_class > teardown_module

驗證上面的執(zhí)行順序,看下面的案例。

創(chuàng)建文件名為 test_run_step.py ,代碼如下:

#!/usr/bin/env python# -*- coding: utf-8 -*-def setup_module():    print("\nsetup_module,只執(zhí)行一次,當有多個測試類的時候使用")def teardown_module():    print("\nteardown_module,只執(zhí)行一次,當有多個測試類的時候使用")class TestPytest1(object):    @classmethod    def setup_class(cls):        print("\nsetup_class1,只執(zhí)行一次")    @classmethod    def teardown_class(cls):        print("\nteardown_class1,只執(zhí)行一次")    def setup_method(self):        print("\nsetup_method1,每個測試方法都執(zhí)行一次")    def teardown_method(self):        print("teardown_method1,每個測試方法都執(zhí)行一次")    def test_three(self):        print("test_three,測試用例")    def test_four(self):        print("test_four,測試用例")class TestPytest2(object):    @classmethod    def setup_class(cls):        print("\nsetup_class2,只執(zhí)行一次")    @classmethod    def teardown_class(cls):        print("\nteardown_class2,只執(zhí)行一次")    def setup_method(self):        print("\nsetup_method2,每個測試方法都執(zhí)行一次")    def teardown_method(self):        print("teardown_method2,每個測試方法都執(zhí)行一次")    def test_two(self):        print("test_two,測試用例")    def test_one(self):        print("test_one,測試用例")

上面的代碼執(zhí)行完成后,查看測試結(jié)果來分析執(zhí)行測試順序:

...plugins: html-2.0.1, rerunfailures-8.0, xdist-1.31.0, ordering-0.6, forked-1.1.3, allure-pytest-2.8.11, metadata-1.8.0collecting ... collected 4 itemstest_run.py::TestPytest1::test_three setup_module,只執(zhí)行一次,當有多個測試類的時候使用setup_class1,只執(zhí)行一次setup_method1,每個測試方法都執(zhí)行一次  PASSED      [ 25%]test_three,測試用例teardown_method1,每個測試方法都執(zhí)行一次test_run.py::TestPytest1::test_four setup_method1,每個測試方法都執(zhí)行一次    PASSED    [ 50%]test_four,測試用例teardown_method1,每個測試方法都執(zhí)行一次teardown_class1,只執(zhí)行一次test_run.py::TestPytest2::test_two setup_class2,只執(zhí)行一次setup_method2,每個測試方法都執(zhí)行一次    PASSED    [ 75%]test_two,測試用例teardown_method2,每個測試方法都執(zhí)行一次test_run.py::TestPytest2::test_one setup_method2,每個測試方法都執(zhí)行一次    PASSED     [100%]test_one,測試用例teardown_method2,每個測試方法都執(zhí)行一次teardown_class2,只執(zhí)行一次teardown_module,只執(zhí)行一次,當有多個測試類的時候使用============================== 4 passed in 0.03s ===============================...

從上面的結(jié)果可以看出 setup_module 和 teardown_module 在整個模塊只執(zhí)行一次,setup_class 和 teardown_class 在類里面只執(zhí)行一次,setup_method 和 teardown_method 在每個方法前后都會調(diào)用。

控制用例的執(zhí)行順序

pytest 加載所有的測試用例是亂序的,如果想指定用例的順序,可以使用 pytest-order 插件,指定用例的執(zhí)行順序只需要在測試用例的方法前面加上裝飾器 @pytest.mark.run(order=[num]) 設置order的對應的num值,它就可以按照 num 的大小順序來執(zhí)行。

應用場景:有時運行測試用例需要指定它的順序,比如有些場景需要先運行完登錄,才能執(zhí)行后續(xù)的流程比如購物流程,下單流程,這時就需要指定測試用例的順序。通過 pytest-ordering 這個插件可以完成用例順序的指定。

安裝

pip install pytest-ordering

案例

創(chuàng)建一個測試文件“test_order.py”,代碼如下:

import pytestclass TestPytest(object):    @pytest.mark.run(order=-1)    def test_two(self):        print("test_two,測試用例")    @pytest.mark.run(order=3)    def test_one(self):        print("test_one,測試用例")    @pytest.mark.run(order=1)    def test_three(self):        print("\ntest_three,測試用例")

執(zhí)行結(jié)果,如下查看執(zhí)行順序:

省略...plugins: html-2.0.1, rerunfailures-8.0, xdist-1.31.0, \ordering-0.6, forked-1.1.3, allure-pytest-2.8.11, metadata-1.8.0collecting ... collected 3 itemstest_order.py::TestPytest::test_three test_order.py::TestPytest::test_one test_order.py::TestPytest::test_two 省略...

從上面的執(zhí)行結(jié)果可以看出,執(zhí)行時以 order 的順序執(zhí)行:order=1,order=3,order=-1。

以上,更多進階內(nèi)容,在后續(xù)文章分享。
點擊領?。鹤詣踊?側(cè)開+性能+簡歷+面試核心教程資料
http://qrcode.testing-studio.com/f?from=jianshu&url=https://ceshiren.com/t/topic/3595

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

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