作者:劉紅妍
導讀
在自動化測驗實踐中,測驗資料是制造測驗場景的必要條件,本文主要講述了在溝通自動化框架如何分層,資料如何存盤,以及基于單元測驗pytest下如何執行,并通過實踐案例分享,提供資料驅動測驗的具體落地方案,
基本概念
資料驅動測驗(DDT)是一種方法,其中在資料源的幫助下重復執行相同順序的測驗步驟,以便在驗證步驟進行時驅動那些步驟的輸入值和/或期望值,在資料驅動測驗的情況下,環境設定和控制不是硬編碼的,換句話說,資料驅動的測驗是在框架中構建要與所有相關資料集一起執行的測驗腳本,該腳本利用了可重用的測驗邏輯,資料驅動的測驗提供了可重復性,將測驗邏輯與測驗資料分離以及減少測驗用例數量等優勢,
設計思路
2.1 測驗資料
在測驗程序中往往需要更加充分地測驗場景,而創建資料測驗,測驗資料包括輸入輸出,對輸出的自動化驗證等,創建測驗資料,可以通過手動拼裝,生產環境拷貝,或通過自動化工具生成,
2.2 資料存盤
資料驅動測驗中使用的資料源可以是Excel檔案,CSV檔案,Yaml檔案,資料池,ADO物件或ODBC源,
2.3 資料驅動優勢
-
如果應用程式開發還在進行當中,測驗者仍然可以進行腳本的撰寫作業,
-
減少了冗余和不必要的測驗腳本,
-
用較少的代碼生成測驗腳本,
-
所有資訊,如輸入、輸出和預期結果,都以適當的文本記錄形式進行存盤,
-
為應用程式的維護提供利了靈活性條件,
-
如果功能發生了變化,只需要調整特定的函式腳本,
實踐分享
基于Laputa框架現有測驗腳本,抽離測驗資料與測驗邏輯,實作資料驅動測驗,
Laputa框架簡介:Laputa框架基于 Pytest 集成了對API介面自動化, 以及對 Web應用, 移動端應用和 Windows 桌面應用 UI 等自動化的能力,具有可視化的Web界面工具, 便于配置執行規則,關聯執行腳本, 觸發用例執行,查看執行結果,提供CI集成服務,呼叫Jenkins API跟蹤持續集成結果,開放介面,實作流水線自動化測驗,
3.1 環境依賴
3.2.1 引數化配置方式
pytest引數化有兩種方式:
@pytest.fixture(params=[])
@pytest.mark.parametrize()
兩者都會多次執行使用它的測驗函式,但@pytest.mark.parametrize()使用方法更豐富一些,laputa更建議使用后者,
3.2.2 用 parametrize 實作引數化
parametrize( ) 方法原始碼:
【python】
def parametrize(self,argnames, argvalues, indirect=False, ids=None, scope=None):
- 主要引數說明
(1)argsnames :引數名,是個字串,如中間用逗號分隔則表示為多個引數名,
(2)argsvalues :引數值,引陣列成的串列,串列中有幾個元素,就會生成幾條用例,
- 使用方法
(1)使用 @pytest.mark.paramtrize() 裝飾測驗方法;
(2)parametrize('data', param) 中的 “data” 是自定義的引數名,param 是引入的引數串列;
(3)將自定義的引數名 data 作為引數傳給測驗用例 test_func;
(4)在測驗用例內部使用 data 的引數,
創建測驗用例,傳入三組引數,每組兩個元素,判斷每組引數里面運算式和值是否相等,代碼如下:
【python】
@pytest.mark.parametrize("test_input,expected",[("3+5",8),("2+5",7),("7*5",30)])
def test_eval(test_input,expected):
# eval 將字串str當成有效的運算式來求值,并回傳結果
assert eval(test_input) == expected
運行結果:
【python】
test_mark_paramize.py::test_eval[3+5-8]test_mark_paramize.py::test_eval[2+5-7]
test_mark_paramize.py::test_eval[7*5-35]
============================== 3 passed in 0.02s ===============================
整個執行程序中,pytest 將引數串列 ("3+5",8),("2+5",7),("7*5",30) 中的三組資料取出來,每組資料生成一條測驗用例,并且將每組資料中的兩個元素分別賦值到方法中,作為測驗方法的引數由測驗用例使用,
3.2.3 多次使用 parametrize
同一個測驗用例還可以同時添加多個 @pytest.mark.parametrize 裝飾器, 多個 parametrize 的所有元素互相組合(類似笛卡兒乘積),生成大量測驗用例,
場景:比如登錄場景,用戶名輸入情況有 n 種,密碼的輸入情況有 m 種,希望驗證用戶名和密碼,就會涉及到 n*m 種組合的測驗用例,如果把這些資料一一的列出來,作業量也是非常大的,pytest 提供了一種引數化的方式,將多組測驗資料自動組合,生成大量的測驗用例,示例代碼如下:
【python】
@pytest.mark.parametrize("x",[1,2])@pytest.mark.parametrize("y",[8,10,11])
def test_foo(x,y):print(f"測驗資料組合x: {x} , y:{y}")
運行結果:
【python】
test_mark_paramize.py::test_foo[8-1]
test_mark_paramize.py::test_foo[8-2]
test_mark_paramize.py::test_foo[10-1]
test_mark_paramize.py::test_foo[10-2]
test_mark_paramize.py::test_foo[11-1]
test_mark_paramize.py::test_foo[11-2]
分析如上運行結果,測驗方法 test_foo( ) 添加了兩個 @pytest.mark.parametrize() 裝飾器,兩個裝飾器分別提供兩個引數值的串列,2 * 3 = 6 種結合,pytest 便會生成 6 條測驗用例,在測驗中通常使用這種方法是所有變數、所有取值的完全組合,可以實作全面的測驗,
3.2.4 @pytest.fixture 與 @pytest.mark.parametrize 結合
下面講講結合 @pytest.fixture 與 @pytest.mark.parametrize 實作引數化,
如果測驗資料需要在 fixture 方法中使用,同時也需要在測驗用例中使用,可以在使用 parametrize 的時候添加一個引數 indirect=True,pytest 可以實作將引數傳入到 fixture 方法中,也可以在當前的測驗用例中使用,
parametrize 原始碼:
【python】
def parametrize(self,argnames, argvalues, indirect=False, ids=None, scope=None):
indirect 引數設定為 True,pytest 會把 argnames 當作函式去執行,將 argvalues 作為引數傳入到 argnames 這個函式里,創建“test_param.py”檔案,代碼如下:
【python】
# 方法名作為引數
test_user_data = https://www.cnblogs.com/Jcloud/p/['Tome', 'Jerry']
@pytest.fixture(scope="module")
def login_r(request):
# 通過request.param獲取引數
user = request.param
print(f"\n 登錄用戶:{user}")return user
@pytest.mark.parametrize("login_r", test_user_data,indirect=True)
def test_login(login_r):
a = login_r
print(f"測驗用例中login的回傳值; {a}")
assert a != "
運行結果:
【plain】
登錄用戶:Tome PASSED [50%]測驗用例中login的回傳值; Tome
登錄用戶:Jerry PASSED [100%]測驗用例中login的回傳值; Jerry
上面的結果可以看出,當 indirect=True 時,會將 login_r 作為引數,test_user_data 被當作引數傳入到 login_r 方法中,生成多條測驗用例,通過 return 將結果回傳,當呼叫 login_r 可以獲取到 login_r 這個方法回傳資料,
圖1 @pytest.fixture 與 @pytest.mark.parametrize 結合讀取資料圖例
3.2.5 conftest作用域
其作用范圍是當前目錄包括子目錄里的測驗模塊,
(1)如果在測驗框架的根目錄創建conftest.py檔案,檔案中的Fixture的作用范圍是所有測驗模塊,
(2)如果在某個單獨的測驗檔案夾里創建conftest.py檔案,檔案中Fixture的作用范圍,就僅局限于該測驗檔案夾里的測驗模塊,
(3)該測驗檔案夾外的測驗模塊,或者該測驗檔案夾外的測驗檔案夾,是無法呼叫到該conftest.py檔案中的Fixture,
(4)如果測驗框架的根目錄和子包中都有conftest.py檔案,并且這兩個conftest.py檔案中都有一個同名的Fixture,實際生效的是測驗框架中子包目錄下的conftest.py檔案中配置的Fixture,
3.3 代碼Demo
測驗資料存盤yaml檔案:
【YAML】
測驗流程:[
{"name":"B2B貧訓運輸三方司機流程","senior":{"createTransJobResource":"B2B","createType":"三方","platformType":2}},
{"name":"B2B貧訓運輸三方司機逆向流程","senior":{"isback":"True","createTransJobResource":"B2B","createType":"三方","platformType":2}},
]
測驗資料準備,定義統一讀取測驗資料方法:
【python】
def dataBuilder(key):dires = path.join(dires, "test_data.yaml")
parameters = laputa_util.read_yaml(dires)[key]
name = []
senior = []
for item in parameters:
name.append(item['name'] if 'name' in item else '')
senior.append(item['senior'] if 'senior' in item else '')
return name, senior
測驗用例標識,通過@pytest.mark.parametrize方法驅動用例:
【python】
class TestRegression:
case, param = dataBuilder('測驗流程')
@pytest.mark.parametrize("param", param, ids=case)
def test_regression_case(self, param):
# 調度
res = create_trans_bill(params)
trans_job_code = res['data']['jobcode']
carrier_type = params['createType'] if params['createType'] in ('自營', '三方') else '個體'
# 執行
work_info = select_trans_work_info_new(trans_job_code)
trans_work_code = work_info['trans_work_code']
if 'isback' in params and params['isback']:
execute_param.update(isBack=params['isback'])
execute_bill_core(**execute_param)
# 結算
if carrier_type != '自營':
trans_fee_code = CreateTransFeeBillBase.checkTF(trans_job_code)
receive_trans_bill_core(**bill_param)
總結
日常測驗程序中,無論是通過手動執行或者腳本執行,都需要利用資料驅動設計思路,這有助于提高測驗場景覆寫率,測驗用例的健壯性和復用性,及需求測驗效率,通過資料驅動測驗不僅可以得到更好的投資回報率,還可以達到質效合一的測驗流程,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/540014.html
標籤:其他
上一篇:Jenkins實踐指南-04-Groovy基礎知識03
下一篇:淺析靜態應用安全測驗
