HTMLTestRunner_Chart 基於unittest的測試報告

HTMLTestRunner_Chart 基於unittest的測試報告,使用詳情見demo

參考鏈接:

http://tungwaiyip.info/software/HTMLTestRunner.html
https://github.com/GoverSky/HTMLTestRunner_cn

GitHub下載地址: https://github.com/githublitao/HTMLTestRunner_Chart

優化報告內容

  1. 測試報告中文顯示,優化一些斷言失敗正文亂碼問題
  2. 新增錯誤和失敗截圖,展示到html報告裏
  3. 增加餅圖統計
  4. 失敗後重試功能
  5. 保存近10次測試結果,並通過柱狀圖展示
  6. 切換測試日期,展示歷史測試結果
    兼容python2.x 和3.x

注意:

  1. 在是python3.x 中,如果在這裏setUp裏初始化driver ,因爲3.x版本 unittest 運行機制不同,會導致用力失敗時截圖失敗,目前只有採用捕獲異常來截圖,或者在setUpClass裏初始化driver
  2. 初始化必須命名爲driver

報告首頁:

報告截圖

用例截圖:

用例截圖

失敗餅圖:

失敗餅圖

歷史走勢:

歷史走勢

失敗重試:

  1. 生成報告的參數裏面加了一個參數retry=1,這個表示用例失敗後,會重新跑一次。
if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(case_01)
    runner = HTMLTestRunner(
        title="帶截圖,餅圖,折線圖,歷史結果查看的測試報告",
        description="",
        stream=open("./demo.html", "wb"),
        verbosity=2,
        retry=0,
        save_last_try=True)
    runner.run(suite)

保存測試結果到json文件:

    def mkdir_json(self):
        is_exists = os.path.exists(self.path)
        # 判斷結果
        if not is_exists:
            try:
                # 如果不存在則創建目錄
                # 創建目錄操作函數
                with open(self.path, "w+") as f:
                    f.write("var data = []")
                return True
            except Exception as e:
                print(e)
                return False
        else:
            return True

    def Write(self, title, heading, desc, data):
        try:
            with open(self.path, "r+") as f:
                all_data = f.read().split(" = ", 1)
                data_json = all_data[1]
                data_json = eval(data_json)
                if len(data_json) >= 10:
                    del data_json[0]
                description = dict()
                description["startTime"] = heading[0][1]
                description["duration"] = heading[1][1]
                if PY3K:
                    description["title"] = title
                    description["status"] = heading[2][1]
                    description["desc"] = desc
                    description["data"] = data
                    status = heading[2][1].split(" ")
                    for j in range(0, len(status)):
                        if status[j] == "通過":
                            description["success"] = str(status[j + 1])
                        if status[j] == "失敗":
                            description["fail"] = str(status[j + 1])
                        if status[j] == "錯誤":
                            description["error"] = str(status[j + 1])
                else:
                    description["title"] = title.encode("gbk")
                    description["status"] = heading[2][1].encode("gbk")
                    description["desc"] = desc.encode("gbk")
                    description["data"] = data.encode("gbk")
                    status = heading[2][1].split(" ")
                    for j in range(0, len(status)):
                        if status[j] == u"通過":
                            description["success"] = str(status[j + 1])
                        if status[j] == u"失敗":
                            description["fail"] = str(status[j + 1])
                        if status[j] == u"錯誤":
                            description["error"] = str(status[j + 1])
                data_json.append(description)
                data_json = str(data_json)
                f.seek(0)
                f.truncate()
                f.write(str("var data = " + data_json))
        except IndexError:
            sys.stderr.write("JSON初始化內容有誤! 初始化內容’var data = []‘")

錯誤/失敗截圖,修改addError和addFail函數:

    def addFailure(self, test, err):
        self.failure_count += 1
        self.status = 1
        TestResult.addFailure(self, test, err)
        _, _exc_str = self.failures[-1]
        output = self.complete_output()
        self.result.append((1, test, output, _exc_str))
        if not getattr(test, "driver",""):
            pass
        else:
            try:
                driver = getattr(test, "driver")
                test.imgs.append(driver.get_screenshot_as_base64())
            except Exception as e:
                pass
        if self.verbosity > 1:
            sys.stderr.write('F  ')
            sys.stderr.write(str(test))
            sys.stderr.write('\n')
        else:
            sys.stderr.write('F')

錯誤重試,修改stopTest函數:

    def stopTest(self, test):
        # Usually one of addSuccess, addError or addFailure would have been called.
        # But there are some path in unittest that would bypass this.
        # We must disconnect stdout in stopTest(), which is guaranteed to be called.
        if self.retry:
            if self.status == 1:
                self.trys += 1
                if self.trys <= self.retry:
                    if self.save_last_try:
                        t = self.result.pop(-1)
                        if t[0]==1:
                            self.failure_count-=1
                        else:
                            self.error_count -= 1
                    test=copy.copy(test)
                    sys.stderr.write("Retesting... ")
                    sys.stderr.write(str(test))
                    sys.stderr.write('..%d \n' % self.trys)
                    doc = test._testMethodDoc or ''
                    if doc.find('_retry')!=-1:
                        doc = doc[:doc.find('_retry')]
                    desc ="%s_retry:%d" %(doc, self.trys)
                    if not PY3K:
                        if isinstance(desc, str):
                            desc = desc.decode("utf-8")
                    test._testMethodDoc = desc
                    test(self)
                else:
                    self.status = 0
                    self.trys = 0
        self.complete_output()

HTML模板導入JSON歷史結果,如果JSON出現錯誤,則歷史結果和走勢圖錯誤:

<head>
    <title>%(title)s</title>
    <meta name="generator" content="%(generator)s"/>
    <meta http-equiv="Content-Type" content="text/html;charset="utf-8"/>
    <script type="text/javascript" src="%(jsonpath)s" charset="gbk"></script>
    <link href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/echarts/3.8.5/echarts.common.min.js"></script>
    <!-- <script type="text/javascript" src="js/echarts.common.min.js"></script> -->
    
    %(stylesheet)s
    
</head>

使用demo:

from selenium import webdriver
import unittest

# from HTMLTestRunner_Chart import HTMLTestRunner
from HTMLTestRunner_Chart import HTMLTestRunner


class case_01(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Chrome()

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()

    def add_img(self):
        self.imgs.append(self.driver.get_screenshot_as_base64())
        return True

    def setUp(self):
        # 在是python3.x 中,如果在這裏初始化driver ,因爲3.x版本 unittest 運行機制不同,會導致用力失敗時截圖失敗
        # self.driver = webdriver.Chrome()
        self.imgs = []
        self.addCleanup(self.cleanup)

    # def tearDown(self):
    #     self.driver.quit()

    def cleanup(self):
        pass

    def test_case1(self):
        """ 百度搜索"""
        print("測試"*10)
        self.driver.get("https://www.baidu.com")
        self.add_img()
        self.driver.find_element_by_id('kw').send_keys(u'百度一下')
        self.add_img()
        self.driver.find_element_by_id('su').click()
        # time.sleep(1)
        self.add_img()
        # self.assertTrue(False)

    def test_case2(self):
        """163郵箱"""
        self.driver.get("https://mail.163.com/")
        raise TypeError
        # self.assertTrue(False)

    def test_case3(self):
        """ 博客園"""
        self.driver.get("https://blog.csdn.net/qw943571775")
        self.imgs.append(self.driver.get_screenshot_as_base64())
        # raise TypeError

    def test_case4(self):
        u""" 淘寶"""
        self.driver.get("http://www.taobao.com/")
        self.add_img()
        self.assertTrue(True)
        # raise TypeError

    def test_case5(self):
        u""" testerhome"""
        self.driver.get("http://testerhome.com/")
        self.add_img()
        raise TypeError
        # self.assertTrue(False)


if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(case_01)
    runner = HTMLTestRunner(
        title="帶截圖,餅圖,折線圖,歷史結果查看的測試報告",
        description="",
        stream=open("./demo.html", "wb"),
        verbosity=2,
        retry=0,
        save_last_try=True)
    runner.run(suite)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章