日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

自动化测试报告 html模板,PyTestReport 自动化测试报告框架

發(fā)布時(shí)間:2025/4/16 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自动化测试报告 html模板,PyTestReport 自动化测试报告框架 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

PyTestReport

一個(gè)由HTMLTestRunner項(xiàng)目為靈感,并基于HTMLTestRunner進(jìn)行二次開(kāi)發(fā)的一個(gè)項(xiàng)目。主要在 API 調(diào)用、報(bào)告樣式、擴(kuò)展性等方面進(jìn)行了增強(qiáng)。

點(diǎn)擊查看HTMLTestRunner的官網(wǎng)。HTMLTestRunner是基于 Python 單元測(cè)試官方實(shí)現(xiàn)的TextTestResult為參考,實(shí)現(xiàn)了對(duì)應(yīng)的HTMLTestResult版本。

安裝與使用

安裝

通過(guò) pip 安裝 pip installPyTestReport

通過(guò)安裝包

可通過(guò)發(fā)布的安裝包進(jìn)行安裝,具體安裝包可在 dist 目錄查找。

pip installPyTestReport-0.1.X-py3-none-any.whl

通過(guò)源碼(最新版本) pip installgit+https://github.com/five3/PyTestReport.git

或者

git clone https://github.com/five3/PyTestReport.git

cdPyTestReport

python setup.py build

python setup.py install

使用

PyTestReport 可用通過(guò)多種方式運(yùn)行,分別如下:

單元測(cè)試 (unittest, pytest)

lib 庫(kù)引入

命令行

REST API

樣例說(shuō)明

單元測(cè)試樣例 (unittest) import unittest

import pytestreport

class MyTest(unittest.TestCase):

def testTrue(self):

self.assertTrue(True)

if __name__ == '__main__':

pytestreport.main(verbosity=2)

以這種方式執(zhí)行之后,默認(rèn)會(huì)在當(dāng)前文件夾下生成一個(gè)PyTestReport.html日志文件,且這個(gè)文件名和樣式模板都不可以重新指定的。

注意:這種方式執(zhí)行時(shí),如果使用 Pycharm 等 IDE,確保不是以 IDE 的內(nèi)建單元測(cè)試框架來(lái)執(zhí)行的;或者直接通過(guò)命令行來(lái)執(zhí)行。

import unittest

from pytestreport import TestRunner

class MyTest(unittest.TestCase):

def testTrue(self):

self.assertTrue(True)

if __name__ == '__main__':

suite = unittest.TestSuite()

suite.addTests(unittest.TestLoader().loadTestsFromTestCase(MyTest))

with open(r'/path/to/report.html', 'wb') as fp:

runner = TestRunner(fp, title='測(cè)試標(biāo)題', description='測(cè)試描述', verbosity=2)

runner.run(suite)

這種方式適合批量加載和執(zhí)行測(cè)試用例,從測(cè)試文件的外部來(lái)導(dǎo)入測(cè)試用例并執(zhí)行。這里可以指定具體的結(jié)果文件路徑和測(cè)試標(biāo)識(shí)等信息。

這里使用的是默認(rèn)模板主題,如果想要使用其它模板主題,可以通過(guò)制定模板的主題文件來(lái)實(shí)現(xiàn)。比如:使用遺留模板的方式如下所示。

from pytestreport import TestRunner

...

runner = TestRunner(fp, title='測(cè)試標(biāo)題', description='測(cè)試描述', verbosity=2, theme='legency')

單元測(cè)試樣例(pytest)

對(duì)于 pytest 框架,收集其測(cè)試結(jié)果信息是通過(guò) pytest 插件形式實(shí)現(xiàn)的。使用之前只要確保正常安裝了 PyTestReport 即可。具體使用方式如下:

import pytest

def testTrue():

assert True

def testFalse():

assert False

def testError():

1 / 0

@pytest.mark.skip(reason="misunderstood the API")

def testSkip():

assert 1 == 1

@pytest.mark.xfail(reason="Xpass")

def testXPass():

assert True

@pytest.mark.xfail(reason="Xfail")

def testXFail():

assert False

if __name__ == '__main__':

pytest.main(["-s", "pytest_Demo.py", "--pytest_report", "Pytest_Report.html"])

需要注意的是,pytest 框架想要使用本測(cè)試報(bào)告框架,在調(diào)用時(shí)需要帶上--pytest_report參數(shù),并指定一個(gè)報(bào)告的文件路徑即可。當(dāng)然你也可以同時(shí)指定一個(gè)非默認(rèn)主題。比如:

import pytest

if __name__ == '__main__':

pytest.main(["-s", "pytest_Demo.py", "--pytest_report", "Pytest_Report.html",

"--pytest_title", "report title", "--pytest_desc", "report desc",

"--pytest_theme", "new_theme"])

另外,你也可以通過(guò)命令行的方式來(lái)啟動(dòng) pytest 執(zhí)行單元測(cè)試。比如:

pytest -s pytest_Demo.py --pytest_report Pytest_Report.html --pytest_theme new_theme

API 庫(kù)引入樣例 from pytestreport.api import make_report

data = {

"generator": "PyTestReport 0.1.4",

"title": "默認(rèn)主題",

"description": "默認(rèn)主題描述",

"report_summary": {

"start_time": "2019-05-12 23:07:49",

"duration": "0:00:00.002000",

"suite_count": 1,

"status": {

"pass": 1,

"fail": 0,

"error": 0,

"skip": 0,

"count": 1

}

},

"report_detail": {

"tests": [

{

"summary": {

"desc": "utDemo.UTestPass",

"count": 1,

"pass": 1,

"fail": 0,

"error": 0,

"skip": 0,

"cid": "testclass1",

"status": "pass"

},

"detail": [

{

"has_output": False,

"tid": "testpass.1.1",

"desc": "testTrue",

"output": "",

"status": "pass",

"status_code": 0

}

]

}

],

"count": "1",

"pass": "1",

"fail": "0",

"error": "0",

"skip": "0"

}

}

with open('API_Report.html', 'wb') as fp:

make_report(fp, data)

# will be create API_Report.html file at current directory.

同樣的,你也可以指定特定的主題或者樣式。比如:

...

with open('API_Report.html', 'wb') as fp:

make_report(fp, data, theme='new_theme', stylesheet='new_stylesheet_2.css')

命令行樣例

命令行樣式,以 data 的 json 文件為參數(shù),同時(shí)可選的參數(shù)有主題,樣式、js 等。

PyTestReport.shell /path/to/data/file.json [reportfile theme htmltemplate stylesheet javascript]

# will be create html report at current directory, the content of data.json should same as the data object in API sample.

實(shí)際運(yùn)行時(shí),需要把符合規(guī)范的測(cè)試結(jié)果數(shù)據(jù)存放到 data.json 文件中。比如:當(dāng)前 data.json 的數(shù)據(jù)已與 API 樣例中的 data 數(shù)據(jù)等同。

PyTestReport.shell data.json output.html

REST API 樣例 暫未支持

開(kāi)發(fā)相關(guān)

PyTestReport對(duì)原項(xiàng)目進(jìn)行了改進(jìn),使用了 Jinjia2 作為模板引擎。且 CSS、JS、HTML 文件都進(jìn)行了分離,所以可以通過(guò)改變單獨(dú)或者全部文件來(lái)達(dá)到修改模板的目的。當(dāng)然這里的修改通常指新增一個(gè)文件,而在執(zhí)行時(shí)只要指定使用該新文件即可。

目前默認(rèn)保留了 2 個(gè)主題的模板:一個(gè)是HTMLTestRunner原來(lái)的模板樣式 (legency),一個(gè)是依據(jù)原模板進(jìn)行 UI 優(yōu)化的模板樣式 (default)。

另外,后期會(huì)收集和添加其它更豐富的模板,也歡迎大家來(lái)踴躍的為該項(xiàng)目添加新模板和樣式。

如何更新樣式

樣式文件被存放在static/css/目錄下,默認(rèn)保留了 2 個(gè)樣式:default.css, legency.css。想要修改樣式的方式 2 兩種:

直接修改當(dāng)前主題對(duì)應(yīng)的 css 文件

復(fù)制當(dāng)前主題的 css 文件,在進(jìn)行修改(推薦)

第一種方式修改之后重新執(zhí)行單元測(cè)試會(huì)直接生效。第二種方式則需要修改下實(shí)例化PyTestReport.TestRunner的 style 參數(shù)。比如:

from pytestreport import TestRunner

...

runner = TestRunner(fp, title='測(cè)試標(biāo)題', description='測(cè)試描述', verbosity=2, stylesheet='new_style.css')

如何更新 JS

JS 文件被存放在static/js/目錄下,默認(rèn)保留了 2 個(gè) JS:default.js, legency.js。修改 JS 的方式和修改樣式一樣有 2 種,同樣我們推薦復(fù)制并修改新 JS 文件的方式。指定新 JS 文件的使用方式如下:

from pytestreport import TestRunner

...

runner = TestRunner(fp, title='測(cè)試標(biāo)題', description='測(cè)試描述', verbosity=2, javaScript='new_js.js')

如何更新模板

HTML 的模板被存放在templates目錄下,默認(rèn)保留了 2 個(gè)模板:default.html, legency.html。

如果你選擇修改模板,那么一般情況下你可能同時(shí)也需要修改 CSS 或 JS 文件。所以我們更推薦的方式是直接新增一個(gè)主題(包括 html、css、js),并且在主題功能完善之后發(fā)送一個(gè) pull request,貢獻(xiàn)到本項(xiàng)目中提供給更多的人使用!

新模板的使用方式如下:

from pytestreport import TestRunner

...

runner = TestRunner(fp, title='測(cè)試標(biāo)題', description='測(cè)試描述', verbosity=2,

htmltemplate='new_theme.html', stylesheet='new_theme.css', javascript='new_theme.js')

或者

from pytestreport import TestRunner

...

runner = TestRunner(fp, title='測(cè)試標(biāo)題', description='測(cè)試描述', verbosity=2, theme='new_theme')

這里需要注意的是,如果新模板需要引用第三方庫(kù)(js、css),請(qǐng)優(yōu)先使用 CDN 鏈接而非本地靜態(tài)文件。

Jinjia2 模板傳入數(shù)據(jù)格式

使用 Jinjia2 模板來(lái)渲染 HTML 報(bào)告時(shí),會(huì)傳入相應(yīng)的測(cè)試結(jié)果集的數(shù)據(jù)對(duì)象。這里列出一個(gè)簡(jiǎn)要的樣例及說(shuō)明,為希望添加新主題的同學(xué)提供參考。

{"generator":"PyTestReport 0.1.3","title":"默認(rèn)主題",#本次單元測(cè)試的主標(biāo)題"description":"默認(rèn)主題描述",#本次單元測(cè)試的描述"stylesheet":"\nbody { font-family: verdana, arial, helvetica, sans-serif; font-size: 80%; }\ntable { font-size: 100%; }\npre { }\n\n/* -- heading ---------------------------------------------------------------------- */\n.heading {\nmargin: 10px;\n}\n.heading .attribute {\nmargin-top: 1ex;\nmargin-bottom: 0;\n}\n\n/* -- css div popup ------------------------------------------------------------------------ */\na.popup_link {\n}\na.popup_link:hover {\ncolor: red;\n}\n.popup_window {\ndisplay: none;\nposition: relative;\nleft: 0px;\ntop: 0px;\n/*border: solid #627173 1px; */\npadding: 10px;\nbackground-color: #E6E6D6;\nfont-family:\"Lucida Console\",\"Courier New\", Courier, monospace;\ntext-align: left;\nfont-size: 8pt;\nwidth: 500px;\n}\n\n/* -- report ------------------------------------------------------------------------ */\n#show_detail_line {\nmargin-top: 3ex;\nmargin-bottom: 1ex;\n}\n#result_table {\nwidth: 80%;\nborder-collapse: collapse;\nborder: 1px solid #4682B4;\n}\n#header_row {\nfont-weight: bold;\ncolor: white;\nbackground-color: #4682B4;\n}\n#result_table td {\nborder: 1px solid #a09d9d;\npadding: 2px;\n}\n#total_row { font-weight: bold; }\n.passClass { background-color: #00ff3733; }\n.failClass { background-color: #f5091f3d; }\n.errorClass { background-color: #0662bb2e; }\n.skipClass { background-color: #40403f38; }\n.passCase { color: #28a745; }\n.failCase { color: #dc3545; font-weight: bold; }\n.errorCase { color: #0c6cff; font-weight: bold; }\n.skipCase { color: #40403f; }\n.hiddenRow { display: none; }\n.testcase { margin-left: 2em; }\n\n/* -- ending ---------------------------------------------------------------------- */\n#ending {\nmin-height: 30px;\n}\n","javascript":"\noutput_list = Array();\n/* level - 0:Summary; 1:Failed; 2:Skip; 3:All */\n\nfunction showCase(level) {\ntrs = document.getElementsByTagName(\"tr\");\nfor (var i = 0; i < trs.length; i++) {\ntr = trs[i];\nid = tr.id;\n\nif (level === 0 && tr.getAttribute('type') === 'case') {\ntr.className = 'hiddenRow';\n} else if (level === 1) {\nif (id.substr(0,2) === 'ft') {\ntr.className = '';\n} else if (tr.getAttribute('type') === 'case') {\ntr.className = 'hiddenRow';\n}\n} else if (level === 2) {\nif (id.substr(0,2) === 'et') {\ntr.className = '';\n} else if (tr.getAttribute('type') === 'case') {\ntr.className = 'hiddenRow';\n}\n} else if (level === 3) {\nif (id.substr(0,2) === 'st') {\ntr.className = '';\n} else if (tr.getAttribute('type') === 'case') {\ntr.className = 'hiddenRow';\n}\n} else if (level === 4 && tr.getAttribute('type') === 'case') {\ntr.className = '';\n}\n}\n}\n\nfunction showClassDetail(cid, count) {\nvar tr_list = document.querySelectorAll('tr[cid='+cid+']');\nvar toHide = 1;\n\nfor (var i = 0; i < count; i++) {\nif (tr_list[i].className) {\ntoHide = 0;\n}\n}\nfor (var i = 0; i < count; i++) {\nif (toHide) {\ntr_list[i].className = 'hiddenRow';\n} else {\ntr_list[i].className = '';\n}\n}\n}\n\nfunction showTestDetail(div_id){\nvar details_div = document.getElementById(div_id)\nvar displayState = details_div.style.display\n// alert(displayState)\nif (displayState != 'block' ) {\ndisplayState = 'block'\ndetails_div.style.display = 'block'\n}\nelse {\ndetails_div.style.display = 'none'\n}\n}\nfunction html_escape(s) {\ns = s.replace(/&/g,'&');\ns = s.replace(//g,'>');\nreturn s;\n}\n\n\n","report_summary":{#報(bào)告總體概要數(shù)據(jù)"start_time":"2019-05-12 23:07:49","duration":"0:00:00.002000","suite_count":1,"status":{"pass":1,"fail":0,"error":0,"skip":0,"count":1}},"report_detail":{#報(bào)告詳情數(shù)據(jù)"tests":[{"summary":{#測(cè)試用例類(lèi)的概要數(shù)據(jù)"desc":"utDemo.UTestPass",#測(cè)試用例類(lèi)的名稱(chēng)"count":1,"pass":1,"fail":0,"error":0,"skip":0,"cid":"testclass1",#唯一標(biāo)識(shí)測(cè)試用例類(lèi)的id:testclass1--表示排序后的第1個(gè)測(cè)試用例類(lèi)"status":"pass"},"detail":[#測(cè)試用例的詳情{"has_output":false,#標(biāo)識(shí)該測(cè)試用例是否有輸出內(nèi)容,通常PASS是沒(méi)有輸出內(nèi)容的。"tid":"testpass.1.1",#唯一標(biāo)識(shí)測(cè)試用例的id,格式為:test{測(cè)試結(jié)果狀態(tài)}.{所屬測(cè)試用例類(lèi)的序號(hào)}.{當(dāng)前測(cè)試用例的序號(hào)}"desc":"testTrue",#測(cè)試用例名稱(chēng)"output":"",#輸出內(nèi)容,如果該測(cè)試用例有輸出的話(huà)"status":"pass","status_code":0#測(cè)試結(jié)果狀態(tài)碼,0為PASS,1為FAIL,2為ERROR,3為SKIP}]}],"count":"1","pass":"1","fail":"0","error":"0","skip":"0"}}

另外,在你進(jìn)行新主題模板調(diào)試時(shí),也可以通過(guò)如下的方式獲取真實(shí)的模板數(shù)據(jù)和渲染之后的 html 內(nèi)容。

import json

from pytestreport import TestRunner

...

runner = TestRunner(fp, title='默認(rèn)主題', description='默認(rèn)主題描述', verbosity=2)

result = runner.run(suite)

print(json.dumps(result.pytestreport_data, ensure_ascii=False, indent=2)) # 傳入Jinjia2模板的數(shù)據(jù)對(duì)象print(result.pytestreport_html) # 渲染成功之后的HTML內(nèi)容

模板展示

默認(rèn)主題

合作

對(duì)此項(xiàng)目感興趣的朋友,歡迎為加入我們的行列,貢獻(xiàn)你的一份力量。你可以:

添加新的測(cè)試報(bào)告模板

添加新的測(cè)試報(bào)告樣式

開(kāi)發(fā)并擴(kuò)展可用功能

提出需求和寶貴意見(jiàn)

另外使用過(guò)程中如果有任何問(wèn)題或疑惑,你可以:

在 github 上給本項(xiàng)目提 ISSUE

發(fā)送郵件至 five3@163.com

總結(jié)

以上是生活随笔為你收集整理的自动化测试报告 html模板,PyTestReport 自动化测试报告框架的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。