在测试报告中插入Log

HTMLTestRunner测试报告优化

欢迎关注公众号[喵先生课堂]

HTMLTestRunner.py下载(https://github.com/Gelomen/HTMLTestReportCN-ScreenShot)

创建HTMLTestRunner测试项目:

打开test_case.py 模块添加如下case代码:

import unittest

class TestDemo(unittest.TestCase):

    def test_one(self):
        assert 1 == 1

    def test_two(self):
        assert 'H' in "Helloword!"
        
    def test_three(self):
        assert 5 == 10

打开run.py模块,添加如下代码:

import os
import time
from HTMLTestRunner import HTMLTestRunner
from test_case import TestDemo
import unittest



# 项目根目录
base_path = os.path.dirname(os.path.abspath(__file__))
# 测试报告存放目录
report_path = os.path.join(base_path, "report")
# 测试报告名称
report_filename = os.path.join(report_path, str(time.strftime("%Y%m%d%H%M%S", time.localtime())) + ".html")

# 创建测试集合
case_suite = unittest.TestSuite()
case_suite.addTest(TestDemo("test_one"))
case_suite.addTest(TestDemo("test_two"))
case_suite.addTest(TestDemo("test_three"))


# 使用HTMLTestRunner运行测试并生成测试报告
def start():
    with open(report_filename, 'wb') as file:
        runner = HTMLTestRunner(stream=file, title='自动化测试报告', description='用例执行情况:')
        runner.run(case_suite)

if __name__ == '__main__':

    start()

运行run.py后在report文件夹下生成一个以 .html结尾的测试报告

图片

通过浏览器打开该HTML测试报告,样子如下:

图片

到此为止我们的项目准备工作完成,开始进行Html测试报告的优化工作

测试报告插入log:

通过测试报告可以看出,执行失败的case可以在测试报告中看到错误信息,但执行通过的case却没有信息输出。现在我们要将log信息打印进测试报告中。

* 添加log模块:

首先我们需要在case中打印log,为了更好的进行log输出,我们在项目中新建 log.py文件,随后再新建Log文件夹用来存放log文件。

* log模块封装:

打开log.py文件,复制下面代码并添加

# !/usr/bin/python

# -*- coding:utf-8 -*-
import logging
import os.path
import time


class Logger(object):

    # 初始化加载
    def __init__(self):

        # 创建一个 logger 对象
        self.logger = logging.getLogger("test")  # loggger 对象为被执行的对象类
        self.logger.setLevel(logging.DEBUG)  # 设置日志模式为调试模式

        # 创建一个 handler,用于写入日志文件
        rq = time.strftime('%Y%m%d%H%M', time.localtime(time.time()))  # 设置日期格式
        log_path = os.path.join(os.getcwd(),'log/')

        # 判断 log 文件夹是否创建,未创建则进行创建
        isExists = os.path.exists(log_path)
        if not isExists:
            try:
                os.makedirs(log_path)
            except Exception as e:
                print("创建文件夹失败", e)
                
        log_name = log_path + rq + '.log'
        fh = logging.FileHandler(log_name)
        fh.setLevel(logging.INFO)

        # 创建一个 handler,用于输出到控制台
        ch = logging.StreamHandler()
        ch.setLevel(logging.INFO)

        # 定义 handler 输出格式
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(process)d - %(processName)s - %(message)s ')
        fh.setFormatter(formatter)
        ch.setFormatter(formatter)
        # 给logger 添加 handler
        self.logger.addHandler(fh)
        self.logger.addHandler(ch)


    def d(self, msg, *args, **kwargs):
        self.logger.debug(msg, *args, **kwargs)

    def i(self, msg, *args, **kwargs):
        self.logger.info(msg, *args, **kwargs)

    def w(self, msg, *args, **kwargs):
        self.logger.warning(msg, *args, **kwargs)

    def c(self, msg, *args, **kwargs):
        self.logger.critical(msg, *args, **kwargs)

    def e(self, msg, *args, **kwargs):
        self.logger.error(msg, *args, **kwargs)

此时我们在 test_case.py模块中添加一些log信息

import unittest
from log import Logger

log=Logger()#为了简单演示,log初始化暂时放在了这里
class TestDemo(unittest.TestCase):

    def test_one(self):
        log.i("case name:test_one")
        assert 1 == 1

    def test_two(self):
        log.i("case name:test_two")
        assert 'H' in "Helloword!"

    def test_three(self):
        log.i("case name:test_three")
        assert 5 == 10

运行run.py文件,此时我们可以在控制台输出的log信息,同时在 log/文件夹下也可以看到生成的.log文件,但测试报告中还是没显示log信息,

控制台log:

2021-12-14 15:23:39,614 - test - INFO - 17952 - MainProcess - case name:test_one 
  S  test_one (test_case.TestDemo)
2021-12-14 15:23:39,614 - test - INFO - 17952 - MainProcess - case name:test_two 
  S  test_two (test_case.TestDemo)
2021-12-14 15:23:39,615 - test - INFO - 17952 - MainProcess - case name:test_three 
  F  test_three (test_case.TestDemo)

--------------------- 测试结束 ---------------------
------------- 合计耗时: 0:00:00.000980 -------------

log/文件夹中的log信息:

图片

开始在测试报告中添加log信息:

想要在测试报告中也输出log信息,需要对HTMLTestRunner.py进行修改,打开HTMLTestRunner.py文件。

  • 首先导入logging模块
图片
  • 找到 class _TestResult(TestResult):,在init方法中添加
self.logger = logging.getLogger('test')

如下:

class _TestResult(TestResult):
    # note: _TestResult is a pure representation of results.
    # It lacks the output and reporting ability compares to unittest._TextTestResult.
    def __init__(self, verbosity=1):
        ... ... ...
        ... ... ...
        self.logger = logging.getLogger('test')
图片
  • 在 def startTest(self, test): 方法后面添加如下代码:
def startTest(self, test):
        stream = sys.stderr
        # stdout_content = " Testing: " + str(test)
        # stream.write(stdout_content)
        # stream.flush()
        # stream.write("\n")
        TestResult.startTest(self, test)
        # just one buffer for both stdout and stderr
        self.outputBuffer = io.StringIO()
        stdout_redirector.fp = self.outputBuffer
        stderr_redirector.fp = self.outputBuffer
        self.stdout0 = sys.stdout
        self.stderr0 = sys.stderr
        sys.stdout = stdout_redirector
        sys.stderr = stderr_redirector
        self.test_start_time = round(time.time(), 2)
        # ---添加 logging 输出以及格式化----
        self.log_cap = io.StringIO()
        self.ch = logging.StreamHandler(self.log_cap)
        self.ch.setLevel(logging.DEBUG)
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(process)d - %(processName)s - %(message)s ')
        self.ch.setFormatter(formatter)
        self.logger.addHandler(self.ch)

如图:

图片
  • 找到 def complete_output(self):函数,在函数的返回值中加入logging存在内存中的输出,用换行符隔开。
def complete_output(self):
        """
        Disconnect output redirection and return buffer.
        Safe to call multiple times.
        """
        self.test_end_time = round(time.time(), 2)
        if self.stdout0:
            sys.stdout = self.stdout0
            sys.stderr = self.stderr0
            self.stdout0 = None
            self.stderr0 = None
            #---添加 log out put ---
            return self.outputBuffer.getvalue() + '\n' + self.log_cap.getvalue()

如图:

图片
  • 每个用例执行完后,清除handler,在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.
        # --- 清除log的handle ---
        self.complete_output()
        self.logger.removeHandler(self.ch)

如图:

图片

此时以修改完毕,我们保存后再次运行run.py生成新的测试报告并打开,可以看到 "通过"状态的case也展示了log信息

图片

项目整体结构如下:

图片

欢迎关注公众号[喵先生课堂]

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,841评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,415评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,904评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,051评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,055评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,255评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,729评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,377评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,517评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,420评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,467评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,144评论 3 317
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,735评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,812评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,029评论 1 256
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,528评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,126评论 2 341

推荐阅读更多精彩内容