第十一章 自動(dòng)化測(cè)試 Pytest
一,pytest配置項(xiàng)? pytest.ini
在主目錄ApiTest下面新建一個(gè)File(注意這里不是測(cè)試用例的?python?File?),命名為pytest.ini
[pytest]
testpaths=./test_xx(具體目錄/文件)#執(zhí)行時(shí)就只執(zhí)行該目錄下的測(cè)試用例
補(bǔ)充:點(diǎn)三角符號(hào)執(zhí)行多條測(cè)試用例,引入main函數(shù)
if __name__ =='__main__':
? ? ? ?pytest.main()
會(huì)把當(dāng)前py文件中的所有測(cè)試用例全部執(zhí)行
二,setup/teardown
前置操作和后置操作:
ui自動(dòng)化,前置打開(kāi)瀏覽器,后置關(guān)閉瀏覽器
接口自動(dòng)化, 前置登錄或插入測(cè)試數(shù)據(jù),后置清理垃圾數(shù)據(jù)
模塊級(jí)? ? setup_module/teardown_module? 開(kāi)始于模塊始末,生效一次
函數(shù)級(jí)? ? setup_function/teardown_function? ?對(duì)每條函數(shù)用例生效(不在類中)
類級(jí)? ? ? setup_class/teardown_class? ? 只在類中前后運(yùn)行一次(在類中)
方法級(jí)? ? setup_method/teardown_method? 開(kāi)始于方法始末(在類中)
具體使用:
(1)模塊級(jí)? ?不管有幾條測(cè)試用例,只執(zhí)行一次
def??setup_module():
? ? ? print(“準(zhǔn)備測(cè)試數(shù)據(jù)”)
def??eardown_module():
? ? ? print(“清理測(cè)試數(shù)據(jù)”)
會(huì)遇到清理測(cè)試數(shù)據(jù)在準(zhǔn)備測(cè)試數(shù)據(jù)前的情況,這種為控制臺(tái)顯示問(wèn)題,其實(shí)執(zhí)行順序是正確的
(2)函數(shù)級(jí)? 對(duì)每個(gè)函數(shù)都會(huì)執(zhí)行一次
def??setup_function():
? ? ? print(“準(zhǔn)備測(cè)試數(shù)據(jù)”)
def??eardown_function():
? ? ? print(“清理測(cè)試數(shù)據(jù)”)
(3)類級(jí)? 和模塊級(jí)類似,在類中只執(zhí)行一次
classTestMobile:
????def??setup_class(self):
????? ? ? print(“準(zhǔn)備測(cè)試數(shù)據(jù)”)
????def??eardown_class(self):
????? ? ? print(“清理測(cè)試數(shù)據(jù)”)
? ? ?def test_mobile(self):
?。。。
? ? ?def?test_baidu(self):
?。。。
需要放在類中的內(nèi)容圈起來(lái),用tab鍵調(diào)下格式,方法重要加上 self
(4)方法級(jí)? ??對(duì)類中的每個(gè)函數(shù)都會(huì)執(zhí)行一次
classTestMobile:
????def??setup_method(self):
????? ? ? print(“準(zhǔn)備測(cè)試數(shù)據(jù)”)
????def??eardown_method(self):
????? ? ? print(“清理測(cè)試數(shù)據(jù)”)
? ? ?def?test_mobile(self):
?。。。
? ? ?def?test_baidu(self):
?。。。
三,fixture
fixture是pytest用于將測(cè)試前后進(jìn)行預(yù)備,清理工作的代碼處理機(jī)制。
fixture相對(duì)于setup/teardown來(lái)說(shuō)有一下幾點(diǎn)優(yōu)勢(shì):
fixture命名更加靈活,局限性比較小
比如:一個(gè)測(cè)試.py文件中寫(xiě)了10條測(cè)試用例,只有5條想要執(zhí)行前置后置步驟,就不要需要分成兩個(gè)文件來(lái)處理
conftest.py 配置里面可以實(shí)現(xiàn)數(shù)據(jù)共享,不需要import就能自動(dòng)找到一些配置
fixture夾具,@pytest.fixture
(scope='function')? 每一個(gè)函數(shù)或方法都會(huì)調(diào)用
(scope='class')??每一個(gè)類調(diào)用一次
(scope='module')??每一個(gè).py文件會(huì)調(diào)用一次
(scope='session')? 多個(gè)文件調(diào)用一次,.py文件就是module
fixture的作用范圍:session>module>class>function
具體應(yīng)用:
import request
import pytest
@pytest.fixture
def func():
? ? ? ?print(“我是前置步驟”)
def?test_mobile(func):#傳func方法執(zhí)行前置
?。。。
def?test_baidu():#不傳func方法不執(zhí)行前置
?。。。
**
①def?func(autouse=true):#范圍內(nèi)所有函數(shù)都執(zhí)行,不管是否傳func,可以在測(cè)試方法中不用一一去添加fixture的名稱? ?
#autouse默認(rèn)為false
**
②def?func(scope=“function”)?: ==? ?def?func():
#scope默認(rèn)為function
四,YAML寫(xiě)法
(1)對(duì)象
key:
????child-key:value
????child-key2:value2
等于
{“key”:{“child-key”:“value”,“child-key2”:“value2”}}
(2)數(shù)組
key:
? ? -A
? ??-B
? ??-C
等于
{“key”:[A,B,C]}
(3)組合
key:
????-child-key:value
????child-key2:value2
等于
{“key”:[{“child-key”:“value”,“child-key2”:“value2”}]}
(4)數(shù)組嵌套
key:
? ? -
????????? ??-A
????????? ??-B
????????? ??-C
等于
{“key”:[[A,B,C]]}
具體用法:
在主目錄ApiTest下面新建一個(gè)普通文件夾Directory,命名為config
再在config文件下建立一個(gè)file,命名為data.yaml文件
(1)
hero:? ? ?#? ?對(duì)象
????name: 安琪拉
????word: 火焰是我最喜歡的玩具
? ? HP: 血量455.5
補(bǔ)充:也可以用字典形式來(lái)寫(xiě)
hero:{name: 安琪拉,word: 火焰是我最喜歡的玩具,HP: 血量455.5}
(2)
hero_name: #數(shù)組
? ? -安琪拉
? ??-小喬
? ??-李白
(3)
hero2:? ? ?#? ?組合(字典外面包一個(gè)數(shù)組)
????-name: 小喬
? ? ?word: 風(fēng),聽(tīng)從我的呼喚
? ? ?HP: 血量389.5
(4)
hero_name2: #數(shù)組嵌套(數(shù)組外面包一個(gè)數(shù)組)
? ? -
? ? ?-安琪拉
? ? ?-小喬
? ? ?-李白
五,YAML讀取方式:
第三方包安裝:pip install pyyaml
在主目錄ApiTest下面新建一個(gè)普通文件夾python package,命名為utils
#主要用來(lái)放各種工具
utils下在新建一個(gè)python file 命名為 read_data.py
import yaml
f=open("../config/data.yaml",encoding="UTF-8")#打開(kāi)文件
data=yaml.safe_load(f)
print(data)
print(data['hero'])#也可以打印具體的某個(gè)數(shù)據(jù)
補(bǔ)充:很多數(shù)據(jù)放在json的話就比較亂,層級(jí)也不容易看,所以用yaml更便捷一些
json:
[{
"key":"value"
}
]
六,參數(shù)化 parametrize
參數(shù)化可以組裝測(cè)試數(shù)據(jù),在測(cè)試前定義好測(cè)試數(shù)據(jù),并在測(cè)試用例中使用
#單次循環(huán)
@pytest.mark.parametrize("a",["b"])? ?#? ?(字符串??“”,數(shù)組? [])
def test_parametrize(a):
? ? ? print(a)
#多次循環(huán)
@pytest.mark.parametrize("a,b",[("c","d"),("e","f")])
def test_parametrize(a,b):
? ? ? print(a,b)
具體用法:
在testcase下面新建python package 命名為test_parametrize
再在下面新建python file? 命名為test_parametrize_01
import pytest
#單參數(shù)單次循環(huán)
@pytest.mark.parametrize("name",["小白"])
def test_parametrize(name):
? ? ? print(“測(cè)試parametrize,我的名字是”+name)
#單參數(shù)多次循環(huán)
@pytest.mark.parametrize("name",["小白",“哈基米”,“小喬”])
def?test_parametrize(name):
? ? ? print(“測(cè)試parametrize,我的名字是”+name)
#多參數(shù)單次循環(huán)
@pytest.mark.parametrize("name,age",[("哈基米",“3”)])
def?test_parametrize(name,age):
? ? ? print(“測(cè)試parametrize,我的名字是”+name+",年齡是"+age+“歲?!?
注意:?jiǎn)未窝h(huán)寫(xiě)法
@pytest.mark.parametrize("name,age",[["哈基米",“3”]]) #用[]數(shù)組也可以,()元組也可以
@pytest.mark.parametrize("name,age",["哈基米",“3”])#這樣寫(xiě)是錯(cuò)誤的
#多參數(shù)多次循環(huán)
@pytest.mark.parametrize("name,age",[["小白","35"],[“哈基米”,"3"],[“小喬”,"18"])
def?test_parametrize(name,age):
? ? ?print(f‘{name}的年齡是{age}’)
六,數(shù)據(jù)驅(qū)動(dòng)? 參數(shù)化?parametrize+yaml
①在data.yaml文件中定義參數(shù)
mobile_params:# 定義 number,appkey?
# 功能同params1={“number”:“13167894587”,“appkey”:“0c565f14687d84”}# python中字典數(shù)據(jù)類型
? ? - [13167894587,0c565f14687d84]
? ? - [13187465319,0c554ge9go0235]
②在測(cè)試用例中
import requests?
import get_data?
@pytest.mark.parametrize("number,appkey",get_data()['mobile_params'])
def test_mobile(number,appkey):
? ??params01={"shouji":number,"appkey":appkey}
????r = requests.get(url="https://www.baidu.com",params=params01)
????print (r.status_code)??
????print (r.json())
? ? assert r.status_code==200
七,allure報(bào)告
allure常用方法
1、title 標(biāo)題
可以自定義用例標(biāo)題,標(biāo)題默認(rèn)為函數(shù)名。@allure.title
2、description 描述
可以添加測(cè)試的詳細(xì)說(shuō)明
3、標(biāo)簽 @allure.feature
4、標(biāo)簽@allure.story
5、?標(biāo)簽 @allure.severity
定義用例的級(jí)別,Graphs主要有BLOCKER,CRITICAL,MINOR,NORMAL,TRIVIAL等幾種類型,默認(rèn)是NORMAL。
只運(yùn)行指定級(jí)別的用例 --allure_severities=critical,blocker
6、?動(dòng)態(tài)生成allure.dynamic
可以使用函數(shù)體內(nèi)的數(shù)據(jù)動(dòng)態(tài)生成
使用方式
1)安裝python插件
使用命令安裝
$ pip3 install allure-pytest
2)配置pytest.ini
[pytest]
testpaths = ./testcases
markes =
p0:高優(yōu)先級(jí)
test:測(cè)試環(huán)境
pro:生產(chǎn)環(huán)境
addopts = -vs -- alluredir./report? ? ? ? # 執(zhí)行測(cè)試用例的報(bào)告都會(huì)放在這個(gè)目錄下面
##如果單個(gè)函數(shù)運(yùn)行,會(huì)在當(dāng)前目錄下生成一個(gè)report文件
##還可以通過(guò)命令行運(yùn)行 pytest? testcase/test_case1.py? 終端執(zhí)行時(shí)會(huì)在根目錄生成report文件(pytest.ini中配置的路徑)
##report文件下包含:
attachment.txt? ? 日志輸出
container.json? ? ?測(cè)試用例前后操作,執(zhí)行時(shí)間,結(jié)束時(shí)間
result.json? ?本條測(cè)試用例的執(zhí)行結(jié)果
ps:在線json校驗(yàn)格式化工具: bejson.com
3)打開(kāi)報(bào)告
終端 輸入allure,顯示allure幫助文檔
①allure serve?./report? ?自動(dòng)打開(kāi)報(bào)告? # 也可以使用絕對(duì)路徑
②allure generate report? ? ?生成報(bào)告(allure-report文件在根目錄下)?
? ?allure?open??allure-report? 跟②結(jié)合使用
③allure?generate report?-o?allure-report1? (通過(guò)-o? 自定義報(bào)告名稱)
八,Jenkins配置
Jenkins創(chuàng)建項(xiàng)目
打開(kāi)Jenkins
(1)安裝allure插件
主頁(yè)--系統(tǒng)管理--插件管理(plugin manager)-- 可選插件--輸入allure,不用回車,自動(dòng)出現(xiàn),勾選安裝
主頁(yè)--系統(tǒng)管理--全局工具配置--配置Allure Commandline--新增Allure?Commandline--輸入別名?allure,勾選自動(dòng)安裝,版本選擇2.18.1--應(yīng)用,保存
(2)新建一個(gè)freestyle項(xiàng)目
主頁(yè)--create a job --? 任務(wù)名稱自定義,選擇第一個(gè)(自由風(fēng)格的軟件項(xiàng)目)--
①描述,
②勾選丟棄舊的構(gòu)建,保持構(gòu)建天數(shù):5,保持構(gòu)建最大個(gè)數(shù):5,
③增加源碼,
源碼管理 :repository url:git項(xiàng)目中克隆/下載,https,復(fù)制地址;
添加憑據(jù):username with password? ,輸入用戶名,密碼(git登錄用賬號(hào));
分支:*/master;
定時(shí)構(gòu)建:日程表:*9***(每天早上9點(diǎn)運(yùn)行);
構(gòu)建環(huán)境:勾選 delete workspace before build starts
構(gòu)建:執(zhí)行shell? ? ? ???
#!/bin/bash??
cd $ {WORKSPACE}? ?
pip3 install -r requirements.txt -- user
pytest? #如果需要指定用例目錄 加上用例path
構(gòu)建后操作:
path:report? #pytest.ini中定義的
點(diǎn)擊應(yīng)用,保存
之后就可以使用,點(diǎn)擊構(gòu)建
可以點(diǎn)擊allure report 查看報(bào)告