HTMLTestRunner python单元测试报告代码

HTMLTestRunner python单元测试报告代码

下面我写的是我自己改了以后的,这个链接是我没修改之前的!
源代码下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html
  补更,求关注!!!
在这里插入图片描述

效果图

  废话不多说直接看效果图 ↓
在这里插入图片描述

使用方法

  在当前路径下创建几个Case开头的.py文件

调用代码

# -*- coding: utf-8 -*-
import unittest
from utils import HTML_REPORT

output_result_path = "C:\\Users\\Administrator\\Desktop\\ZWCMS_SELENIUM_TEST_RESULT.html"
output_result_title = "test_title"

if __name__ == '__main__':
    suite = unittest.TestSuite()  # 创建测试套件
    all_cases = unittest.defaultTestLoader.discover('.', 'Case*.py')
    # 找到目录下所有的以 test 开头的 Python 文件里面的测试用例
    for case in all_cases:
        suite.addTests(case)  # 把所有的测试用例添加进来
    print(output_result_path)
    fp = open(output_result_path, 'wb')
    runner = HTML_REPORT.HTMLTestRunner(stream=fp, title=output_result_title)
    runner.run(suite)

测试代码

  测试一下,可复制成多个文件,文件名与 class 名不能冲突。

# -*- coding: utf-8 -*-
import unittest, time


class Test_Login(unittest.TestCase):
    def setUp(self):
        pass

    def test_1_base(self):
        assert 1 == 1

    def test_2_base(self):
        assert 1 == 1

    def test_3_base(self):
        assert 1 != 1

    def tearDown(self):
        pass


if __name__ == "__main__":
    unittest.main()

修改后的代码

# coding=utf-8

__author__ = u"那一丝寒意,冰封千里"
__version__ = "0.9.0"


# TODO: color stderr
# TODO: simplify javascript using ,ore than 1 class in the class attribute?
# coding=utf-8
import datetime
import io
import sys
import time
import unittest
import re
from xml.sax import saxutils


# ------------------------------------------------------------------------
# The redirectors below are used to capture output during testing. Output
# sent to sys.stdout and sys.stderr are automatically captured. However
# in some cases sys.stdout is already cached before HTMLTestRunner is
# invoked (e.g. calling logging.basicConfig). In order to capture those
# output, use the redirectors for the cached stream.
#
# e.g.
#   >>> logging.basicConfig(stream=HTMLTestRunner.stdout_redirector)
#   >>>

class OutputRedirector(object):
    """ Wrapper to redirect stdout or stderr """

    def __init__(self, fp):
        self.fp = fp

    def write(self, s):
        self.fp.write(s.encode())

    def writelines(self, lines):
        self.fp.writelines(lines)

    def flush(self):
        self.fp.flush()


stdout_redirector = OutputRedirector(sys.stdout)
stderr_redirector = OutputRedirector(sys.stderr)


# ----------------------------------------------------------------------
# Template

class Template_mixin(object):
    """
    Define a HTML template for report customerization and generation.

    Overall structure of an HTML report

    HTML
    +------------------------+
    |<html>                  |
    |  <head>                |
    |                        |
    |   STYLESHEET           |
    |   +----------------+   |
    |   |                |   |
    |   +----------------+   |
    |                        |
    |  </head>               |
    |                        |
    |  <body>                |
    |                        |
    |   HEADING              |
    |   +----------------+   |
    |   |                |   |
    |   +----------------+   |
    |                        |
    |   REPORT               |
    |   +----------------+   |
    |   |                |   |
    |   +----------------+   |
    |                        |
    |   ENDING               |
    |   +----------------+   |
    |   |                |   |
    |   +----------------+   |
    |                        |
    |  </body>               |
    |</html>                 |
    +------------------------+
    """

    STATUS = {
        0: '通过',
        1: '失败',
        2: '错误',
        3: '跳过'
    }

    DEFAULT_TITLE = 'Unit Test Report'
    DEFAULT_DESCRIPTION = ''

    # ------------------------------------------------------------------------
    # HTML Template

    HTML_TMPL = r"""
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>%(title)s</title>
    <meta name="generator" content="%(generator)s"/>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <link href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
    <script src="http://libs.baidu.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
    %(stylesheet)s
</head>
<body >
<script language="javascript" type="text/javascript">
output_list = Array();
// 默认显示所有的
let Case_level = 'a';
/*level 调整增加只显示通过用例的分类 --Findyou
0	概要 全部展开显示标题
2	通过
1	失败
4	错误
5	跳过
3	所有 全部展开显示所有信息
*/
function showCase(level) {

    trs = document.getElementsByTagName("tr");

    for (var i = 0; i < trs.length; i++) {
        tr = trs[i];
        id = tr.id;
        id_sub = id.substr(0, 2);
        if (id_sub == 'pt' || id_sub == 'ft' || id_sub == 'st' || id_sub == 'et') {

            // 展开所有通过的用例
            if (id_sub == 'pt') {
                if (level == 2) {
                    Case_level = 'p';
                    tr.className = '';
                } else {
                    tr.className = 'hiddenRow';
                }
            }
            // 展开所有失败的用例
            if (id_sub == 'ft') {
                if (level == 1) {
                    Case_level = 'f';
                    tr.className = '';
                } else {
                    tr.className = 'hiddenRow';
                }
            }
            // 展开所有跳过的用例
            if (id_sub == 'st') {
                if (level == 5) {
                    Case_level = 's';
                    tr.className = '';
                } else {
                    tr.className = 'hiddenRow';
                }
            }

            // 展开所有错误的用例
            if (id_sub == 'et') {
                if (level == 4) {
                    Case_level = 'e';
                    tr.className = '';
                } else {
                    tr.className = 'hiddenRow';
                }
            }
            // 展开所有用例
            if (level == 3) {
                Case_level = 'a';
                tr.className = '';
            }
        }
    }


    //加入【详细】切换文字变化 --Findyou
    detail_class=document.getElementsByClassName('detail');
	//console.log(detail_class.length)
	if (level == 3) {
		for (var i = 0; i < detail_class.length; i++){
			detail_class[i].innerHTML="收起"
		}
	}
	else{
			for (var i = 0; i < detail_class.length; i++){
			detail_class[i].innerHTML="详细"
		}
	}
}

function showClassDetail(cid, count) {
    let tr;
    let tid;
    var id_list = Array();
    var toHide = 1;
    for (var i = 0; i < count; i++) {
        //ID修改 点 为 下划线 -Findyou
        const tid0 = 't' + cid.substr(1) + '_' + (i + 1);


        if (Case_level == 'a') {

            tid = 'f' + tid0;
            tr = document.getElementById(tid);
            if (!tr) {
                tid = 'p' + tid0;
                tr = document.getElementById(tid);
            }
            if (!tr) {
                tid = 's' + tid0;
                tr = document.getElementById(tid);
            }
            if (!tr) {
                tid = 'e' + tid0;
                tr = document.getElementById(tid);
            }


        } else {
            tid = Case_level + tid0;
            tr = document.getElementById(tid)
        }

        if(tr){
            id_list.push(tid) ;
            // 判断到的标签是隐藏还是显示
            if (tr.className) {
                toHide = 0;
            }
        }
    }


    for (var i = 0; i < id_list.length; i++) {
        tid = id_list[i];
        //修改点击无法收起的BUG,加入【详细】切换文字变化 --Findyou
        if (toHide) {
            document.getElementById(tid).className = 'hiddenRow';
            document.getElementById(cid).innerText = "详细"
        }
        else {
            document.getElementById(tid).className = '';
            document.getElementById(cid).innerText = "收起"
        }
    }
}

function html_escape(s) {
    s = s.replace(/&/g,'&amp;');
    s = s.replace(/</g,'&lt;');
    s = s.replace(/>/g,'&gt;');
    return s;
}
</script>
%(heading)s
%(report)s
%(ending)s

</body>
</html>

"""
    # variables: (title, generator, stylesheet, heading, report, ending)

    # ------------------------------------------------------------------------
    # Stylesheet
    #
    # alternatively use a <link> for external style sheet, e.g.
    #   <link rel="stylesheet" href="$url" type="text/css">

    STYLESHEET_TMPL = """
<style type="text/css" media="screen">
body        { font-family: Microsoft YaHei,Tahoma,arial,helvetica,sans-serif;padding: 20px; font-size: 80%; }
table       { font-size: 100%; }

/* -- heading ---------------------------------------------------------------------- */
.heading {
    margin-top: 0ex;
    margin-bottom: 1ex;
}

.heading .description {
    margin-top: 4ex;
    margin-bottom: 6ex;
}

/* -- report ------------------------------------------------------------------------ */
#total_row  { font-weight: bold; }
.passCase   { color: #5cb85c; font-weight: bold; }
.errorCase  { color: #ff2222; font-weight: bold; }
.failCase   { color: #f0ad4e; font-weight: bold; }
.skipCase   { color: #aaaaaa; font-weight: bold; }
.hiddenRow  { display: none; }
.testcase   { margin-left: 2em; }
.passCase_button   { background: #5cb85c; font-weight: bold; color:#fff;}
.errorCase_button  { background: #ff2222; font-weight: bold; color:#fff;}
.failCase_button   { background: #f0ad4e; font-weight: bold; color:#fff;}
.skipCase_button   { background: #aaaaaa; font-weight: bold; color:#fff;}
</style>
"""

    #     # ------------------------------------------------------------------------
    #     # Heading
    #     #
    #
    #     HEADING_TMPL = """
    # <div class='heading'>
    #     <h1 style="font-family: Microsoft YaHei">%(title)s</h1>
    #     %(parameters)s
    #     <p class='description'>%(description)s</p>
    # </div>
    #
    # """

    # ------------------------------------------------------------------------
    # Heading
    #

    HEADING_TMPL = """<div class='heading'>
<h1>%(title)s</h1>
%(parameters)s
<p class='description'>%(description)s</p>
</div>

"""  # variables: (title, parameters, description)

    HEADING_ATTRIBUTE_TMPL = """<p class='attribute'><strong>%(name)s : </strong> %(value)s</p>
"""  # variables: (name, value)

    # ------------------------------------------------------------------------
    # Report
    #

    REPORT_TMPL = """
<p id='show_detail_line'>
<a class="btn btn-primary" href='javascript:showCase(0)'>概要{ %(passrate)s }</a>
<a class="btn btn-success" style='background:#5cb85c' href='javascript:showCase(2)'>通过{ %(Pass)s }</a>
<a class="btn btn-danger"  style='background:#f0ad4e' href='javascript:showCase(1)'>失败{ %(fail)s }</a>
<a class="btn btn-danger"  style='background:#ff2222' href='javascript:showCase(4)'>错误{ %(error)s }</a>
<a class="btn btn-warning" style='background:#aaaaaa' href='javascript:showCase(5)'>跳过{ %(skip)s }</a>
<a class="btn btn-info" href='javascript:showCase(3)'>所有{ %(count)s }</a>
</p>
<table id='result_table' class="table table-condensed table-bordered table-hover">
<colgroup>
<col align='left' />
<col align='right' />
<col align='right' />
<col align='right' />
<col align='right' />
<col align='right' />
</colgroup>
<tr id='header_row' class="text-center success" style="font-weight: bold;font-size: 14px;">
    <td>用例集/测试用例</td>
    <td>总计</td>
    <td>通过</td>
    <td>失败</td>
    <td>错误</td>
    <td>跳过</td>
    <td>详细</td>
</tr>
%(test_list)s
<tr id='total_row' class="text-center active">
    <td>总计</td>
    <td>%(count)s</td>
    <td>%(Pass)s</td>
    <td>%(fail)s</td>
    <td>%(error)s</td>
     <td>%(skip)s</td>
    <td>通过率:%(passrate)s</td>
</tr>
</table>
"""  # variables: (test_list, count, Pass, fail, error)

    REPORT_CLASS_TMPL = r"""
<tr class='%(style)s warning'>
    <td>%(desc)s</td>
    <td class="text-center">%(count)s</td>
    <td class="text-center">%(Pass)s</td>
    <td class="text-center">%(fail)s</td>
    <td class="text-center">%(error)s</td>
    <td class="text-center">%(skip)s</td>
    <td class="text-center"><a href="javascript:showClassDetail('%(cid)s',%(count)s)" class="detail" id='%(cid)s'>详细</a></td>

</tr>
"""  # variables: (style, desc, count, Pass, fail,skip, error, cid)

    REPORT_TEST_WITH_OUTPUT_TMPL = r"""
<tr id='%(tid)s' class='%(Class)s'>
    <td class='%(style)s'><div class='testcase'>%(desc)s</div></td>
    <td colspan='5' align='center'>
    <!--默认收起错误信息 -Findyou -->
    <button id='btn_%(tid)s' type="button"  class="btn btn-xs %(style)s_button" data-toggle="collapse" data-target='#div_%(tid)s'>%(status)s</button>
    <div id='div_%(tid)s' class="collapse"> 

    <pre>
    %(script)s
    </pre>
    </div>
    </td>
</tr>
"""  # variables: (tid, Class, style, desc, status)
    REPORT_TEST_NO_OUTPUT_TMPL = r"""
<tr id='%(tid)s' class='%(Class)s'>
    <td class='%(style)s'><div class='testcase'>%(desc)s</div></td>
    <td colspan='5' align='center'><span class="label label-success success">%(status)s</span></td>
    <td align='center'><a  %(hidde)s  href="%(image)s">picture_shot</a></td>
</tr>
"""  # variables: (tid, Class, style, desc, status)

    REPORT_TEST_OUTPUT_TMPL = r"""
%(output)s
"""

    # variables: (id, output)

    # ------------------------------------------------------------------------
    # ENDING
    #

    ENDING_TMPL = """
<div id='ending'>&nbsp;</div>
<div style=" position:fixed;right:50px; bottom:30px; width:20px; height:20px;cursor:pointer">
    <a href="#">
        <span class="glyphicon glyphicon-eject" style = "font-size:30px;" aria-hidden="true"></span>
    </a>
</div>
    """


# -------------------- The end of the Template class -------------------


TestResult = unittest.TestResult


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):
        TestResult.__init__(self)
        super().__init__(verbosity)
        self.stdout0 = None
        self.stderr0 = None
        self.success_count = 0
        self.skipped_count = 0  # add skipped_count
        self.failure_count = 0
        self.error_count = 0
        self.verbosity = verbosity

        # result is a list of result in 4 tuple
        # (
        #   result code (0: success; 1: fail; 2: error),
        #   TestCase object,
        #   Test output (byte string),
        #   stack trace,
        # )
        self.result = []

    def startTest(self, test):
        TestResult.startTest(self, test)
        # just one buffer for both stdout and stderr
        self.outputBuffer = io.BytesIO()
        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

    def complete_output(self):
        """
        Disconnect output redirection and return buffer.
        Safe to call multiple times.
        """
        if self.stdout0:
            sys.stdout = self.stdout0
            sys.stderr = self.stderr0
            self.stdout0 = None
            self.stderr0 = None
        return self.outputBuffer.getvalue()

    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.
        self.complete_output()

    def addSuccess(self, test):
        self.success_count += 1
        TestResult.addSuccess(self, test)
        output = self.complete_output()
        self.result.append((0, test, output, ''))
        if self.verbosity > 1:
            sys.stderr.write('P ')
            sys.stderr.write(str(test))
            sys.stderr.write('\n')
        # else:
        #     sys.stderr.write('P')

    def addSkip(self, test, reason):
        self.skipped_count += 1
        TestResult.addSkip(self, test, reason)
        output = self.complete_output()
        self.result.append((3, test, '', reason))
        if self.verbosity > 1:
            sys.stderr.write('skip ')
            sys.stderr.write(str(test))
            sys.stderr.write('\n')
        # else:
        #     sys.stderr.write('S')

    def addError(self, test, err):
        self.error_count += 1
        TestResult.addError(self, test, err)
        _, _exc_str = self.errors[-1]
        output = self.complete_output()
        self.result.append((2, test, output, _exc_str))
        if self.verbosity > 1:
            sys.stderr.write('E  ')
            sys.stderr.write(str(test))
            sys.stderr.write('\n')
        # else:
        #     sys.stderr.write('E')

    def addFailure(self, test, err):
        self.failure_count += 1
        TestResult.addFailure(self, test, err)
        _, _exc_str = self.failures[-1]
        output = self.complete_output()
        self.result.append((1, test, output, _exc_str))
        if self.verbosity > 1:
            sys.stderr.write('F  ')
            sys.stderr.write(str(test))
            sys.stderr.write('\n')


class HTMLTestRunner(Template_mixin):
    """
    """

    def __init__(self, stream=sys.stdout, verbosity=1, title=None, description=None, name=None):
        self.stream = stream
        self.verbosity = verbosity
        if title is None:
            self.title = self.DEFAULT_TITLE
        else:
            self.title = title
        if name is None:
            self.name = ''
        else:
            self.name = name
        if description is None:
            self.description = self.DEFAULT_DESCRIPTION
        else:
            self.description = description

        self.startTime = datetime.datetime.now()

    def run(self, test):
        "Run the given test case or test suite."
        result = _TestResult(self.verbosity)
        test(result)
        self.stopTime = datetime.datetime.now()
        self.generateReport(test, result)
        # print (sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime))
        return result

    def sortResult(self, result_list):
        # unittest does not seems to run in any particular order.
        # Here at least we want to group them together by class.
        rmap = {}
        classes = []
        for n, t, o, e in result_list:
            cls = t.__class__
            if not cls in rmap:
                rmap[cls] = []
                classes.append(cls)
            rmap[cls].append((n, t, o, e))
        r = [(cls, rmap[cls]) for cls in classes]
        return r

    def getReportAttributes(self, result):
        """
        Return report attributes as a list of (name, value).
        Override this to add custom attributes.
        """
        startTime = str(self.startTime)[:19]
        duration = str(self.stopTime - self.startTime)
        status = []
        if result.success_count: status.append('Pass %s' % result.success_count)
        if result.failure_count: status.append('Failure %s' % result.failure_count)
        if result.skipped_count: status.append('Skip %s' % result.skipped_count)
        if result.error_count:   status.append('Error %s' % result.error_count)
        if status:
            status = ' '.join(status)
        else:
            status = 'none'
        return [
            ('Start Time', startTime),
            ('Duration', duration),
            ('Status', status),
        ]

    def generateReport(self, test, result):
        report_attrs = self.getReportAttributes(result)  # 报告的头部
        generator = 'HTMLTestRunner %s' % __version__
        stylesheet = self._generate_stylesheet()  # 拿到css文件
        heading = self._generate_heading(report_attrs)
        report = self._generate_report(result)
        ending = self._generate_ending()
        output = self.HTML_TMPL % dict(
            title=saxutils.escape(self.title),
            generator=generator,
            stylesheet=stylesheet,
            heading=heading,
            report=report,
            ending=ending,
        )
        self.stream.write(output.encode('utf8'))

    def _generate_stylesheet(self):
        return self.STYLESHEET_TMPL

    def _generate_heading(self, report_attrs):
        a_lines = []
        for name, value in report_attrs:
            line = self.HEADING_ATTRIBUTE_TMPL % dict(
                name=saxutils.escape(name),
                value=saxutils.escape(value),
            )
            a_lines.append(line)
        heading = self.HEADING_TMPL % dict(
            title=saxutils.escape(self.title),
            parameters=''.join(a_lines),
            description=saxutils.escape(self.description),
        )
        return heading

    # 根据result收集报告
    def _generate_report(self, result):
        rows = []
        sortedResult = self.sortResult(result.result)
        i = 0
        for cid, (cls, cls_results) in enumerate(sortedResult):
            # subtotal for a class
            np = nf = ns = ne = 0  # np代表pass个数,nf代表fail,ns代表skip,ne,代表error
            for n, t, o, e in cls_results:
                if n == 0:
                    np += 1
                elif n == 1:
                    nf += 1
                elif n == 3:
                    ns += 1
                else:
                    ne += 1

            # format class description
            # if cls.__module__ == "__main__":
            #     name = cls.__name__
            # else:
            #     name = "%s.%s" % (cls.__module__, cls.__name__)
            name = cls.__name__
            try:
                core_name = self.name[i]
            except Exception:
                core_name = ''
            # doc = (cls.__doc__)+core_name and (cls.__doc__+core_name).split("\n")[0] or ""
            doc = (cls.__doc__) and cls.__doc__.split("\n")[0] or ""
            desc = doc and '%s: %s' % (name, doc) or name
            i = i + 1  # 生成每个TestCase类的汇总数据,对于报告中的
            row = self.REPORT_CLASS_TMPL % dict(
                style=ne > 0 and 'errorClass' or nf > 0 and 'failClass' or 'passClass',
                desc=desc,
                count=np + nf + ne + ns,
                Pass=np,
                fail=nf,
                error=ne,
                skip=ns,
                cid='c%s' % (cid + 1),
            )
            rows.append(row)
            # 生成每个TestCase类中所有方法的测试结果
            for tid, (n, t, o, e) in enumerate(cls_results):
                self._generate_report_test(rows, cid, tid, n, t, o, e)
        count = str(result.success_count + result.failure_count + result.error_count + result.skipped_count)
        passrate = round(int(result.success_count) / int(count) * 100, 1)
        report = self.REPORT_TMPL % dict(
            test_list=''.join(rows),
            passrate=str(passrate) + "%",
            count=count,
            Pass=str(result.success_count),
            fail=str(result.failure_count),
            error=str(result.error_count),
            skip=str(result.skipped_count)
        )
        return report

    def _generate_report_test(self, rows, cid, tid, n, t, o, e):

        # e.g. 'pt1.1', 'ft1.1', etc
        has_output = bool(o or e)

        tid = (n == 0 and 'p' or n == 1 and 'f' or n == 2 and 'e' or 's') + 't%s_%s' % (cid + 1, tid + 1)
        name = t.id().split('.')[-1]
        doc = t.shortDescription() or ""
        desc = doc and ('%s: %s' % (name, doc)) or name
        # tmpl = has_output and self.REPORT_TEST_WITH_OUTPUT_TMPL or self.REPORT_TEST_NO_OUTPUT_TMPL
        tmpl = self.REPORT_TEST_WITH_OUTPUT_TMPL
        uo1 = ""
        # o and e should be byte string because they are collected from stdout and stderr?

        if isinstance(o, bytes):
            o = str(o, 'utf-8')

        if isinstance(o, str):
            uo = o
        else:
            uo = e

        if isinstance(e, str):
            # TODO: some problem with 'string_escape': it escape \n and mess up formating
            # ue = unicode(e.encode('string_escape'))
            ue = e
        else:
            ue = o
        output = saxutils.escape(str(uo) + str(ue))
        if output == '':
            output = "this Case not OutPut Code!"
        script = self.REPORT_TEST_OUTPUT_TMPL % dict(
            output=output
        )

        if "shot_picture_name" in str(saxutils.escape(str(ue))):
            hidde_status = ''
            pattern = re.compile(r'AssertionError:.*?shot_picture_name=(.*)', re.S)
            shot_name = re.search(pattern, str(saxutils.escape(str(e))))
            try:
                image_url = "http://192.168.99.105/contractreport/screenshot/" + time.strftime("%Y-%m-%d",
                                                                                               time.localtime(
                                                                                                   time.time())) + "/" + shot_name.group(
                    1) + ".png"
            except Exception:
                image_url = "http://192.168.99.105/contractreport/screenshot/" + time.strftime("%Y-%m-%d",
                                                                                               time.localtime(
                                                                                                   time.time()))
        # style= n == 2 and 'errorCase' or (n == 1 and 'failCase') or (n == 3 and 'skipCase' or 'none')
        else:
            hidde_status = '''hidden="hidden"'''
            image_url = ''
            # Class=(n == 0 and 'hiddenRow' or 'none'),
        row = tmpl % dict(
            tid=tid,
            Class='hiddenRow',
            style=(n == 0 and 'passCase' or n == 1 and 'failCase' or n == 2 and 'errorCase' or 'skipCase'),
            desc=desc,
            script=script,
            hidde=hidde_status,
            image=image_url,
            status=self.STATUS[n],
        )

        rows.append(row)
        if not has_output:
            return

    def _generate_ending(self):
        return self.ENDING_TMPL

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值