Allure
模塊下載
pip?install?allure-pytest
包下載
https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/
此處我選擇下載最新的,版本上可以選擇不是最新的,2.9.0的。下載zip或者tgz后綴格式的都可以。
配置環(huán)境變量
找到解壓縮后的包》》》找到環(huán)境變量》》》找到系統(tǒng)環(huán)境變量》》》找到Path》》》把a(bǔ)llure的bin目錄添加進(jìn)去
D:\allure-2.9.0\bin
allure需要依賴JDK,所以,電腦需要先配置好JDK環(huán)境。
執(zhí)行命令
首先,配置文件中:
addopts?=?-vs?--alluredir?./report/xml
意思是使用在當(dāng)前文件目錄中生成一個(gè)report文件,并且在report下生成一個(gè)xml文件。至于生成報(bào)告的路徑可以自己設(shè)定修改./report/xml,這里生成的是生成測試報(bào)告前的數(shù)據(jù)文件,還不是完整的測試報(bào)告。 其次,生成測試報(bào)告:
import?pytest
import?os
if?__name__?==?'__main__':
????pytest.main()
????#?os.system('allure?serve?./report')
????os.system('allure?generate?--clean?./report/xml?-o?./report/html')
使用os模塊生成.html測試文件,也就是我們說的測試報(bào)告。--clean覆蓋的意思,如果不加:Allure: Target directory D:\pytest_.\report\html for the report is already in use, add a '--clean' option to overwrite,再就是使用-o參數(shù)生成測試報(bào)告文件地址是./report/html。
當(dāng)然還有一種,也是用os模塊生成,但是會自動(dòng)打開測試報(bào)告:
os.system('allure?serve?./report')
此處不要將./report改成某某絕對路徑,例如:D:\pytest_\no_Case
Generating?report?to?temp?directory...
Report?successfully?generated?to?C:\Users\admin\AppData\Local\Temp\6235808475101309995\allure-report
Starting?web?server...
2023-01-04?12:33:56.667:INFO::main:?Logging?initialized?@1480ms?to?org.eclipse.jetty.util.log.StdErrLog
Server?started?at?<http://172.16.100.48:49279/>.?Press?<Ctrl+C>?to?exit
雖然也能生成測試報(bào)告成功,并且在C盤的指定目錄下,但是測試報(bào)告是沒有內(nèi)容的。因?yàn)榇颂幍拿钪械?/report是存放測試數(shù)據(jù)的地方,是allure拿來生成測試報(bào)告的數(shù)據(jù)取貨點(diǎn)。
關(guān)于測試數(shù)據(jù)重復(fù)
在運(yùn)行的時(shí)候,如果不清除之前的數(shù)據(jù),那么測試報(bào)告中的數(shù)據(jù)就會一直存在,且會展示在測試報(bào)告中,我們只需要使用--clean-alluredir即可。
addopts?=?-vs?--alluredir?./report/xml?--capture=sys?--clean-alluredir
關(guān)于測試報(bào)告中沒有數(shù)據(jù)
?1、目錄結(jié)構(gòu)錯(cuò)誤,也就是說測試數(shù)據(jù)在./report/xml中,生成測試報(bào)告文件的時(shí)候?qū)戝e(cuò)了路徑,寫在了./report/xmll等,這樣會導(dǎo)致加載錯(cuò)誤。 2、版本問題。下載使用的版本過低,而pip時(shí)是新版本,也可能導(dǎo)致測試數(shù)據(jù)沒有的情況。
?
測試報(bào)告的一些內(nèi)容
Allure用例描述 | ||
---|---|---|
使用方法 | 參數(shù)值 | 參數(shù)說明 |
@allure.epic() | epic描述 | 定義項(xiàng)目、當(dāng)有多個(gè)項(xiàng)目是使用。往下是feature |
@allure.feature() | 模塊名稱 | 用例按照模塊區(qū)分,有多個(gè)模塊時(shí)給每個(gè)起名字 |
@allure.story() | 用例名稱 | 一個(gè)用例的描述 |
@allure.title(用例的標(biāo)題) | 用例標(biāo)題 | 一個(gè)用例標(biāo)題 |
@allure.testcase() | 測試用例的連接地址 | 自動(dòng)化用例對應(yīng)的功能用例存放系統(tǒng)的地址 |
@allure.issue() | 缺陷地址 | 對應(yīng)缺陷管理系統(tǒng)里邊的缺陷地址 |
@allure.description() | 用例描述 | 對測試用例的詳細(xì)描述 |
@allure.step() | 操作步驟 | 測試用例的操作步驟 |
@allure.severity() | 用例等級 | blocker 、critical 、normal 、minor 、trivial |
@allure.link() | 定義連接 | 用于定義一個(gè)需要在測試報(bào)告中展示的連接 |
@allure.attachment() | 附件 | 添加測試報(bào)告附件 |
關(guān)于中英文
此處是可選的。
測試報(bào)告代碼示例
此節(jié)跟上一節(jié)測試報(bào)告的一些內(nèi)容有著密不可分的關(guān)系!
from?loguru?import?logger
import?allure
def?test01():
????"""我是test01"""
????logger.debug('This?is?<DEBUG>?information')
????time.sleep(1)
def?test02():
????"""這是第二個(gè)用例"""
????print("--02--")
@allure.story("這是03用例")
def?test03():
????"""這是第三個(gè)用例"""
????print("--03--")
@allure.story("這是04用例")
def?test04():
????"""這是第四個(gè)用例"""
????print("--04--")
@allure.feature("這是func類模塊")
class?Testfunc:
????@allure.title("添加功能")
????@allure.step("操作步驟1:這是func類用例步驟a1")
????@allure.description("添加數(shù)據(jù)操作")
????@allure.link("https://blog.csdn.net/weixin_52040868")
????def?test_a1(self):
????????"""這是Testfunc中的a1用例"""
????????print("數(shù)據(jù)--添加--成功!")
????????print("SUCCESS")
????@allure.step("操作步驟1:這是用例步驟b1")
????def?test_b1(self):
????????"""這是Testfunc中的b1用例"""
????????print("數(shù)據(jù)--刪除--成功!")
????????print("SUCCESS")
allure基礎(chǔ)使用先對而言沒有特別的麻煩,但是比較的復(fù)雜,因?yàn)檠b飾器太多了。在上述中已經(jīng)有體現(xiàn)了。運(yùn)行結(jié)果:
看到了嗎,allure的裝飾器雖然繁瑣,看是用習(xí)慣了,在測試報(bào)告中看起來還是比較的賞心悅目的,仔細(xì)看你會發(fā)現(xiàn)@allure.description("添加數(shù)據(jù)操作")跟""""""中的描述一樣,說明默認(rèn)情況下allure會默認(rèn)將用例中的""""""收集起來用于描述。
關(guān)于日志
import?logging
import?sys
logger?=?logging.getLogger()
logger.setLevel(logging.DEBUG)
def?test_06():
????logger.info('Logged?INFO?message')
????logger.warning('Logged?WARNING?message')
????logger.error('Logged?ERROR?message')
????print('Message?outputted?to?stdout')
????print('Message?outputted?to?stderr',?file=sys.stderr)
????assert?1?==?1
?說明: 1、圖片中體現(xiàn)了三處日志信息,分別是自定義的log,stdout以及stderr 2、stdout,stderr只需要一個(gè)命令參數(shù)即可:--capture=sys 3、自定義的log,只需要自己將logging日志信息寫好即可如上代碼所示(簡略版本)
?
關(guān)于stdout/stderr捕獲
有三種方法 pytest 可以執(zhí)行捕獲:
-
fd (文件描述符)級別捕獲(默認(rèn)):將捕獲到操作系統(tǒng)文件描述符1和2的所有寫入。
-
sys 級別捕獲:僅寫入python文件 sys.stdout 和 sys.stderr 將被捕獲。不捕獲對文件描述符的寫入。
-
tee-sys 捕獲:Python寫入 sys.stdout 和 sys.stderr 將被捕獲,但是寫入也將傳遞到實(shí)際 sys.stdout 和 sys.stderr . 這允許輸出被“實(shí)時(shí)打印”并捕獲以供插件使用,例如junitxml(pytest 5.4中的新功能)。
pytest?-s??????????????????#?disable?all?capturing
pytest?--capture=sys???????#?replace?sys.stdout/stderr?with?in-mem?files
pytest?--capture=fd????????#?also?point?filedescriptors?1?and?2?to?temp?file
pytest?--capture=tee-sys???#?combines?'sys'?and?'-s',?capturing?sys.stdout/stderr
???????????????????????????#?and?passing?it?along?to?the?actual?sys.stdout/stderr
詳細(xì)可以參考:捕獲stdout/stderr輸出 — pytest documentation
關(guān)于用例名稱story
此項(xiàng)在測試套中是看不到的,只有在功能這一塊可以看到。所以在使用@allure.story()的時(shí)候需要注意。一般性情況下可以拿來左一個(gè)歸類的操作。
關(guān)于操作步驟step
import?pytest
from?selenium?import?webdriver
from?selenium.webdriver.chrome.service?import?Service
from?selenium.webdriver.common.by?import?By
data?=?['https://www.baidu.com']
class?Test_browser:
????def?setup_method(self):
????????s?=?Service(r'D:\pytest_\Case\geckodriver.exe')
????????self.driver?=?webdriver.Firefox(service=s)
????@pytest.mark.parametrize("url",data)
????def?test_start_browser(self,url):
????????with?allure.step(f"打開網(wǎng)址:{url}"):
????????????self.driver.get(url)
????????with?allure.step("輸入元素"):
????????????self.driver.find_element(By.ID,'kw').send_keys('拾|貳')
????????with?allure.step("步驟截圖"):
????????????allure.attach(self.driver.get_screenshot_as_png(),'截圖',allure.attachment_type.PNG)
????def?teardown_method(self):
????????self.driver.quit()
?此處我也沒有再用allure裝飾器了,用的是with語句,上下文管理協(xié)議,這樣可以幫助我們在測試報(bào)告上精確到每一步的操作,就是寫起來比較的麻煩:
?
用例等級
class?Test_severity:
????@allure.severity(allure.severity_level.BLOCKER)
????def?test_BLOCKER(self:
????????"""最嚴(yán)重等級"""
????????print("BLOCKER")
????@allure.severity(allure.severity_level.CRITICAL)
????def?test_CRITICAL(self):
????????"""嚴(yán)重"""
????????print("CRITICAL")
????@allure.severity(allure.severity_level.NORMAL)
????def?test_NORMAL(self):
????????"""普通"""
????????print("NORMAL")
????@allure.severity(allure.severity_level.MINOR)
????def?test_MINOR(self):
????????"""不嚴(yán)重"""
????????print("MINOR")
????@allure.severity(allure.severity_level.TRIVIAL)
????def?test_TRIVIAL(self):
????????"""最不嚴(yán)重"""
????????print("TRIVIAL")
也可以在測試套中看到:
快速回歸示例
在用例很多的時(shí)候,可以使用這個(gè)方法進(jìn)行標(biāo)記,只回歸部分或執(zhí)行部分模塊的測試用例:
?--allure-severities blocker,critical,執(zhí)行什么等級的用例就在后面寫什么級別的。在pytest.ini中完整的命令示范:
?
addopts?=?-vs?--alluredir?./report/xml?--capture=sys?--clean-alluredir?--allure-severities?blocker,critical
關(guān)于severities部分命令也可以寫成:
--allure-severities=blocker,critical
關(guān)于用例等級的代碼寫法
上述的@allure.severity寫的太復(fù)雜、繁瑣了,也可以寫成這樣:
class?Test_severity:
????@allure.severity("blocker")
????def?test_BLOCKER(self):
????????"""最嚴(yán)重等級"""
????????print("BLOCKER")
????@allure.severity("critical")
????def?test_CRITICAL(self):
????????"""嚴(yán)重"""
????????print("CRITICAL")
關(guān)于測試報(bào)告的用例參數(shù)展示
import?pytest
import?allure
datas?=?[
????????["QINGAN",?'login',?{"user":?"SHIER",?"pwd":?"123456"}],
????????["SHIER",?'login1',?{"pwd":?"654321",?"user":?"QINGAN"}]
????]
class?Test_severity:
????@allure.severity("blocker")
????@pytest.mark.parametrize("user,text,datas",datas)
????def?test_BLOCKER(self,user,text,datas):
????????"""最嚴(yán)重等級"""
????????assert?user
????????assert?text
????????assert?datas
????????print("BLOCKER")
對于數(shù)據(jù)驅(qū)動(dòng),在測試報(bào)告上展示測試數(shù)據(jù)還是很有必要的!
測試數(shù)據(jù)展示
import?pytest
import?allure
datas?=?[
????????["QINGAN",?'login',?{"user":?"SHIER",?"pwd":?"123456"}],
????????["SHIER",?'login1',?{"pwd":?"654321",?"user":?"QINGAN"}]
????]
class?Test_severity:
????@allure.severity("blocker")
????@allure.step("測試數(shù)據(jù)")
????@pytest.mark.parametrize("user,text,datas",datas)
????def?test_BLOCKER(self,user,text,datas):
????????"""最嚴(yán)重等級"""
????????assert?user
????????assert?text
????????assert?datas
????????print("BLOCKER")
測試報(bào)告截圖
from?selenium?import?webdriver
from?selenium.webdriver.chrome.service?import?Service
from?selenium.webdriver.common.by?import?By
from?time?import?sleep
class?Test_browser:
????def?setup_method(self):
????????s?=?Service(r'D:\pytest_\Case\geckodriver.exe')
????????self.driver?=?webdriver.Firefox(service=s)
????def?test_start_browser(self):
????????self.driver.get("https://www.baidu.com")
????????self.driver.find_element(By.ID,'kw').send_keys('拾|貳')
????????sleep(1)
????????allure.attach(self.driver.get_screenshot_as_png(),'截圖',allure.attachment_type.PNG)
????def?teardown_method(self):
????????self.driver.quit()
?用到了一個(gè)新的方法,attach,命令已經(jīng)在上述體現(xiàn)出來了,attachment_type.PNG是可選的,PNG,MP4,GIF等等,這些都不常用,最常用的還是圖片PNG。
?
錯(cuò)誤自動(dòng)截圖
"""conftest.py"""
import?pytest
import?allure
import?os
from?selenium?import?webdriver
from?selenium.webdriver.chrome.service?import?Service
@pytest.fixture(scope='session')
def?browser():
????global?driver
????s?=?Service(r'D:\pytest_\Case\geckodriver.exe')
????driver?=?webdriver.Firefox(service=s)
????yield?driver
????driver.quit()
@pytest.hookimpl(tryfirst=True,?hookwrapper=True)
def?pytest_runtest_makereport(item,?call):
????'''
????獲取每個(gè)用例狀態(tài)的鉤子函數(shù)
????:param?item:
????:param?call:
????'''
????#?獲取鉤子方法的調(diào)用結(jié)果
????outcome?=?yield
????rep?=?outcome.get_result()
????#?僅僅獲取用例call?執(zhí)行結(jié)果是失敗的情況,?不包含?setup/teardown
????if?rep.when?==?"call"?and?rep.failed:
????????mode?=?"a"?if?os.path.exists("failures")?else?"w"
????????with?open("failures",?mode)?as?f:
????????????#?let's?also?access?a?fixture?for?the?fun?of?it
????????????if?"tmpdir"?in?item.fixturenames:
????????????????extra?=?"?(%s)"?%?item.funcargs["tmpdir"]
????????????else:
????????????????extra?=?""
????????????f.write(rep.nodeid?+?extra?+?"\n")
????????#?添加allure報(bào)告截圖
????????if?hasattr(driver,?"get_screenshot_as_png"):
????????????with?allure.step('用例失敗截圖'):
????????????????allure.attach(driver.get_screenshot_as_png(),?"失敗圖片",?allure.attachment_type.PNG)
此處跟pytest-html用的是類似的方法,具體已經(jīng)在pytest-html中已經(jīng)體現(xiàn)。唯一不同的就是集成了allure庫,以此來達(dá)到嵌入圖片的操作。
關(guān)于測試報(bào)告logo與標(biāo)題
里面的1.jpg是我更換過的圖片,原來的是custom-logo.svg,更改后,點(diǎn)開styles.css文件:
.side-nav__brand?{
??background:?url('logo.png')?no-repeat?10px?center?!important;??????#?url括號內(nèi)寫的就是自己圖片的名字,我這里的是logo.png
??height:?40px;
??background-size:?contain?!important;
}
.side-nav__brand?span{
????display:?none;
?margin:?20px;
}
.side-nav__brand:after{
????content:?"拾貳";????#?這是的內(nèi)容對應(yīng)的是我logo后面的內(nèi)容,在接下來的截圖中可以看到,如果不寫這個(gè)樣式,默認(rèn)的就是allure
?position:?relative;
?top:?0;
?left:16%;
?bottom:0;
?right:0;
}
將url里面的custom-logo.svg改成自己的預(yù)先準(zhǔn)備號的圖片名字。如果未生效,請把上述代碼中的注釋部分刪掉并保存。
.side-nav__brand?{
??background:?url('logo.png')?no-repeat?10px?center?!important;
??height:?40px;
??background-size:?contain?!important;
}
.side-nav__brand?span{
????display:?none;
?margin:?20px;
}
.side-nav__brand:after{
????content:?"拾貳";
?position:?relative;
?top:?0;
?left:16%;
?bottom:0;
?right:0;
}
然后再找到:
plugins:
??-?junit-xml-plugin
??-?xunit-xml-plugin
??-?trx-plugin
??-?behaviors-plugin
??-?packages-plugin
??-?screen-diff-plugin
??-?xctest-plugin
??-?jira-plugin
??-?xray-plugin
??-?custom-logo-plugin
將- custom-logo-plugin添加進(jìn)去保存即可,接下來重寫運(yùn)行一下用例生成測試報(bào)告就可以看到更改了。
看到了嗎,這就改過來了。至于名稱,可以根據(jù)自己需要進(jìn)行調(diào)整:
#?CSS文件的此處,主要是left
top:?0;
left:16%;
bottom:0;
right:0;
網(wǎng)頁標(biāo)題與測試報(bào)告文案修改
#?-*-?coding:?utf-8?-*-
"""run.py文件"""
import?pytest
import?os
from?time?import?sleep
import?json
#?測試報(bào)告文案獲取的文件地址
title_filepath?=?r"D:\pytest_\report\html\widgets\summary.json"
#?這里主要是去拿到你的HTML測試報(bào)告的絕對路徑【記得換成你自己的】
report_title_filepath?=?r"D:\pytest_\report\html\index.html"
#?設(shè)置報(bào)告窗口的標(biāo)題
def?set_windos_title(new_title):
????"""
????設(shè)置打開的?Allure?報(bào)告的瀏覽器窗口標(biāo)題文案
????"""
????#?定義為只讀模型,并定義名稱為:?f
????with?open(report_title_filepath,?'r+',encoding="utf-8")?as?f:
????????#?讀取當(dāng)前文件的所有內(nèi)容
????????all_the_lines?=?f.readlines()
????????f.seek(0)
????????f.truncate()
????????#?循環(huán)遍歷每一行的內(nèi)容,將?"Allure?Report"?全部替換為?→?new_title(新文案)
????????for?line?in?all_the_lines:
????????????f.write(line.replace("Allure?Report",?new_title))
#?獲取?summary.json?文件的數(shù)據(jù)內(nèi)容
def?get_json_data(name):
????#?定義為只讀模型,并定義名稱為f
????with?open(title_filepath,?'rb')?as?f:
????????#?加載json文件中的內(nèi)容給params
????????params?=?json.load(f)
????????#?修改內(nèi)容
????????params['reportName']?=?name
????????#?將修改后的內(nèi)容保存在dict中
????????dict?=?params
????#?返回dict字典內(nèi)容
????return?dict
#?寫入json文件
def?write_json_data(dict):
????#?定義為寫模式,名稱定義為r
????with?open(title_filepath,?'w',?encoding="utf-8")?as?r:
????????#?將dict寫入名稱為r的文件中
????????json.dump(dict,?r,?ensure_ascii=False,?indent=4)
if?__name__?==?'__main__':
????pytest.main()
????os.system('allure?generate?--clean?./report/xml?-o?./report/html')
????sleep(3)
????#?自定義測試報(bào)告標(biāo)題
????set_windos_title("清安自動(dòng)化測試")
????#?自定義測試報(bào)告標(biāo)題
????report_title?=?get_json_data("清安自動(dòng)化測試報(bào)告")
????write_json_data(report_title)
?title_filepath、report_title_filepath可以修改成先對路徑,絕對路徑并不靠譜??梢允褂肙S模塊進(jìn)行先對定位。這兩個(gè)文件所在的位置,是自己設(shè)定的allure測試報(bào)告生成的位置:
?
文章來源:http://www.zghlxwxcb.cn/news/detail-706898.html
?當(dāng)然,可以不寫在run文件中,可以單獨(dú)寫一個(gè)執(zhí)行修改文件,然后進(jìn)行調(diào)用。文章來源地址http://www.zghlxwxcb.cn/news/detail-706898.html
?
到了這里,關(guān)于Pytest-Allure測試報(bào)告的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!