51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1191|回复: 5
打印 上一主题 下一主题

[原创] Day2-7测试积点任务

[复制链接]
  • TA的每日心情
    擦汗
    6 小时前
  • 签到天数: 527 天

    连续签到: 4 天

    [LV.9]测试副司令

    跳转到指定楼层
    1#
    发表于 2018-7-30 10:37:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    1测试积点
    问题:
    Python+Selenium 做 UI 自动化输出报告报错
    1. <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>
    复制代码
    1. # coding=utf-8
    2. import HTMLTestRunner
    3. import os
    4. import unittest
    5. import time

    6. # 设置报告文件保存路径
    7. report_path = os.path.dirname(os.path.abspath(".")) + '/test_reports/'

    8. # 获取系统当前时间
    9. now = time.strftime("%Y-%m-%d-%H_%M_%S", time.localtime(time.time()))

    10. # 设置报告名称格式
    11. html_file = report_path + now + "HTMLTemplate.html"
    12. fp = open(html_file, "wb")

    13. # 构建suite
    14. # suite = unittest.TestSuite()
    15. # suite.addTest(TestBaiduSearch('test_baidu_search'))
    16. # suite.addTest(TestGetPageTitle('test_get_page_title'))

    17. # # 通过makeSuite把整个class的测试case都加入套件中
    18. # suite = unittest.TestSuite(unittest.makeSuite(TestBaiduSearch))

    19. # 通过discover把整个package的所有测试case都加入套件中
    20. suite = unittest.TestLoader().discover("testsuites")

    21. if __name__ == '__main__':

    22.     # # 执行测试用例
    23.     # runner = unittest.TextTestRunner()

    24.     # 初始化一个HTMLTestRunner实例对象,用来生成报告
    25.     runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title=u"某某项目测试报告", description=u"用例测试情况")
    26.     # 开始执行套件
    27.     runner.run(suite)
    复制代码

    问题:当我运行这段程序的时候,提示报错:
    <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>
    Time Elapsed: 0:00:00.000047

    有没有人遇到类似的,我是Python3,下面附上我的HTMLTestRunner.py的代码:
    1. """
    2. A TestRunner for use with the Python unit testing framework. It
    3. generates a HTML report to show the result at a glance.

    4. The simplest way to use this is to invoke its main method. E.g.

    5.     import unittest
    6.     import HTMLTestRunner

    7.     ... define your tests ...

    8.     if __name__ == '__main__':
    9.         HTMLTestRunner.main()


    10. For more customization options, instantiates a HTMLTestRunner object.
    11. HTMLTestRunner is a counterpart to unittest's TextTestRunner. E.g.

    12.     # output to a file
    13.     fp = file('my_report.html', 'wb')
    14.     runner = HTMLTestRunner.HTMLTestRunner(
    15.                 stream=fp,
    16.                 title='My unit test',
    17.                 description='This demonstrates the report output by HTMLTestRunner.'
    18.                 )

    19.     # Use an external stylesheet.
    20.     # See the Template_mixin class for more customizable options
    21.     runner.STYLESHEET_TMPL = '<link rel="stylesheet" href="my_stylesheet.css" type="text/css">'

    22.     # run the test
    23.     runner.run(my_test_suite)


    24. ------------------------------------------------------------------------
    25. Copyright (c) 2004-2007, Wai Yip Tung
    26. All rights reserved.

    27. Redistribution and use in source and binary forms, with or without
    28. modification, are permitted provided that the following conditions are
    29. met:

    30. * Redistributions of source code must retain the above copyright notice,
    31.   this list of conditions and the following disclaimer.
    32. * Redistributions in binary form must reproduce the above copyright
    33.   notice, this list of conditions and the following disclaimer in the
    34.   documentation and/or other materials provided with the distribution.
    35. * Neither the name Wai Yip Tung nor the names of its contributors may be
    36.   used to endorse or promote products derived from this software without
    37.   specific prior written permission.

    38. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
    39. IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
    40. TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
    41. PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
    42. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    43. EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    44. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    45. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    46. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    47. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    48. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    49. """

    50. # URL: http://tungwaiyip.info/software/HTMLTestRunner.html

    51. __author__ = "Wai Yip Tung"
    52. __version__ = "0.8.2"


    53. """
    54. Change History

    55. Version 0.8.2
    56. * Show output inline instead of popup window (Viorel Lupu).

    57. Version in 0.8.1
    58. * Validated XHTML (Wolfgang Borgert).
    59. * Added description of test classes and test cases.

    60. Version in 0.8.0
    61. * Define Template_mixin class for customization.
    62. * Workaround a IE 6 bug that it does not treat <script> block as CDATA.

    63. Version in 0.7.1
    64. * Back port to Python 2.3 (Frank Horowitz).
    65. * Fix missing scroll bars in detail log (Podi).
    66. """

    67. # TODO: color stderr
    68. # TODO: simplify javascript using ,ore than 1 class in the class attribute?

    69. import datetime
    70. import io
    71. import sys
    72. import time
    73. import unittest
    74. from xml.sax import saxutils


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

    85. class OutputRedirector(object):
    86.     """ Wrapper to redirect stdout or stderr """
    87.     def __init__(self, fp):
    88.         self.fp = fp

    89.     def write(self, s):
    90.         self.fp.write(s)

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

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

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



    97. # ----------------------------------------------------------------------
    98. # Template

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

    102.     Overall structure of an HTML report

    103.     HTML
    104.     +------------------------+
    105.     |<html>                  |
    106.     |  <head>                |
    107.     |                        |
    108.     |   STYLESHEET           |
    109.     |   +----------------+   |
    110.     |   |                |   |
    111.     |   +----------------+   |
    112.     |                        |
    113.     |  </head>               |
    114.     |                        |
    115.     |  <body>                |
    116.     |                        |
    117.     |   HEADING              |
    118.     |   +----------------+   |
    119.     |   |                |   |
    120.     |   +----------------+   |
    121.     |                        |
    122.     |   REPORT               |
    123.     |   +----------------+   |
    124.     |   |                |   |
    125.     |   +----------------+   |
    126.     |                        |
    127.     |   ENDING               |
    128.     |   +----------------+   |
    129.     |   |                |   |
    130.     |   +----------------+   |
    131.     |                        |
    132.     |  </body>               |
    133.     |</html>                 |
    134.     +------------------------+
    135.     """

    136.     STATUS = {
    137.     0: 'pass',
    138.     1: 'fail',
    139.     2: 'error',
    140.     }

    141.     DEFAULT_TITLE = 'Unit Test Report'
    142.     DEFAULT_DESCRIPTION = ''

    143.     # ------------------------------------------------------------------------
    144.     # HTML Template

    145.     HTML_TMPL = r"""<?xml version="1.0" encoding="UTF-8"?>
    146. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    147. <html xmlns="http://www.w3.org/1999/xhtml">
    148. <head>
    149.     <title>%(title)s</title>
    150.     <meta name="generator" content="%(generator)s"/>
    151.     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    152.     %(stylesheet)s
    153. </head>
    154. <body>
    155. <script language="javascript" type="text/javascript"><!--
    156. output_list = Array();

    157. /* level - 0:Summary; 1:Failed; 2:All */
    158. function showCase(level) {
    159.     trs = document.getElementsByTagName("tr");
    160.     for (var i = 0; i < trs.length; i++) {
    161.         tr = trs[i];
    162.         id = tr.id;
    163.         if (id.substr(0,2) == 'ft') {
    164.             if (level < 1) {
    165.                 tr.className = 'hiddenRow';
    166.             }
    167.             else {
    168.                 tr.className = '';
    169.             }
    170.         }
    171.         if (id.substr(0,2) == 'pt') {
    172.             if (level > 1) {
    173.                 tr.className = '';
    174.             }
    175.             else {
    176.                 tr.className = 'hiddenRow';
    177.             }
    178.         }
    179.     }
    180. }


    181. function showClassDetail(cid, count) {
    182.     var id_list = Array(count);
    183.     var toHide = 1;
    184.     for (var i = 0; i < count; i++) {
    185.         tid0 = 't' + cid.substr(1) + '.' + (i+1);
    186.         tid = 'f' + tid0;
    187.         tr = document.getElementById(tid);
    188.         if (!tr) {
    189.             tid = 'p' + tid0;
    190.             tr = document.getElementById(tid);
    191.         }
    192.         id_list[i] = tid;
    193.         if (tr.className) {
    194.             toHide = 0;
    195.         }
    196.     }
    197.     for (var i = 0; i < count; i++) {
    198.         tid = id_list[i];
    199.         if (toHide) {
    200.             document.getElementById('div_'+tid).style.display = 'none'
    201.             document.getElementById(tid).className = 'hiddenRow';
    202.         }
    203.         else {
    204.             document.getElementById(tid).className = '';
    205.         }
    206.     }
    207. }


    208. function showTestDetail(div_id){
    209.     var details_div = document.getElementById(div_id)
    210.     var displayState = details_div.style.display
    211.     // alert(displayState)
    212.     if (displayState != 'block' ) {
    213.         displayState = 'block'
    214.         details_div.style.display = 'block'
    215.     }
    216.     else {
    217.         details_div.style.display = 'none'
    218.     }
    219. }


    220. function html_escape(s) {
    221.     s = s.replace(/&/g,'&');
    222.     s = s.replace(/</g,'<');
    223.     s = s.replace(/>/g,'>');
    224.     return s;
    225. }

    226. /* obsoleted by detail in <div>
    227. function showOutput(id, name) {
    228.     var w = window.open("", //url
    229.                     name,
    230.                     "resizable,scrollbars,status,width=800,height=450");
    231.     d = w.document;
    232.     d.write("<pre>");
    233.     d.write(html_escape(output_list[id]));
    234.     d.write("\n");
    235.     d.write("<a href='javascript:window.close()'>close</a>\n");
    236.     d.write("</pre>\n");
    237.     d.close();
    238. }
    239. */
    240. --></script>

    241. %(heading)s
    242. %(report)s
    243. %(ending)s

    244. </body>
    245. </html>
    246. """
    247.     # variables: (title, generator, stylesheet, heading, report, ending)


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

    253.     STYLESHEET_TMPL = """
    254. <style type="text/css" media="screen">
    255. body        { font-family: verdana, arial, helvetica, sans-serif; font-size: 80%; }
    256. table       { font-size: 100%; }
    257. pre         { }

    258. /* -- heading ---------------------------------------------------------------------- */
    259. h1 {
    260.     font-size: 16pt;
    261.     color: gray;
    262. }
    263. .heading {
    264.     margin-top: 0ex;
    265.     margin-bottom: 1ex;
    266. }

    267. .heading .attribute {
    268.     margin-top: 1ex;
    269.     margin-bottom: 0;
    270. }

    271. .heading .description {
    272.     margin-top: 4ex;
    273.     margin-bottom: 6ex;
    274. }

    275. /* -- css div popup ------------------------------------------------------------------------ */
    276. a.popup_link {
    277. }

    278. a.popup_link:hover {
    279.     color: red;
    280. }

    281. .popup_window {
    282.     display: none;
    283.     position: relative;
    284.     left: 0px;
    285.     top: 0px;
    286.     /*border: solid #627173 1px; */
    287.     padding: 10px;
    288.     background-color: #E6E6D6;
    289.     font-family: "Lucida Console", "Courier New", Courier, monospace;
    290.     text-align: left;
    291.     font-size: 8pt;
    292.     width: 500px;
    293. }

    294. }
    295. /* -- report ------------------------------------------------------------------------ */
    296. #show_detail_line {
    297.     margin-top: 3ex;
    298.     margin-bottom: 1ex;
    299. }
    300. #result_table {
    301.     width: 80%;
    302.     border-collapse: collapse;
    303.     border: 1px solid #777;
    304. }
    305. #header_row {
    306.     font-weight: bold;
    307.     color: white;
    308.     background-color: #777;
    309. }
    310. #result_table td {
    311.     border: 1px solid #777;
    312.     padding: 2px;
    313. }
    314. #total_row  { font-weight: bold; }
    315. .passClass  { background-color: #6c6; }
    316. .failClass  { background-color: #c60; }
    317. .errorClass { background-color: #c00; }
    318. .passCase   { color: #6c6; }
    319. .failCase   { color: #c60; font-weight: bold; }
    320. .errorCase  { color: #c00; font-weight: bold; }
    321. .hiddenRow  { display: none; }
    322. .testcase   { margin-left: 2em; }


    323. /* -- ending ---------------------------------------------------------------------- */
    324. #ending {
    325. }

    326. </style>
    327. """



    328.     # ------------------------------------------------------------------------
    329.     # Heading
    330.     #

    331.     HEADING_TMPL = """<div class='heading'>
    332. <h1>%(title)s</h1>
    333. %(parameters)s
    334. <p class='description'>%(description)s</p>
    335. </div>

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

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



    339.     # ------------------------------------------------------------------------
    340.     # Report
    341.     #

    342.     REPORT_TMPL = """
    343. <p id='show_detail_line'>Show
    344. <a href='javascript:showCase(0)'>Summary</a>
    345. <a href='javascript:showCase(1)'>Failed</a>
    346. <a href='javascript:showCase(2)'>All</a>
    347. </p>
    348. <table id='result_table'>
    349. <colgroup>
    350. <col align='left' />
    351. <col align='right' />
    352. <col align='right' />
    353. <col align='right' />
    354. <col align='right' />
    355. <col align='right' />
    356. </colgroup>
    357. <tr id='header_row'>
    358.     <td>Test Group/Test case</td>
    359.     <td>Count</td>
    360.     <td>Pass</td>
    361.     <td>Fail</td>
    362.     <td>Error</td>
    363.     <td>View</td>
    364. </tr>
    365. %(test_list)s
    366. <tr id='total_row'>
    367.     <td>Total</td>
    368.     <td>%(count)s</td>
    369.     <td>%(Pass)s</td>
    370.     <td>%(fail)s</td>
    371.     <td>%(error)s</td>
    372.     <td> </td>
    373. </tr>
    374. </table>
    375. """ # variables: (test_list, count, Pass, fail, error)

    376.     REPORT_CLASS_TMPL = r"""
    377. <tr class='%(style)s'>
    378.     <td>%(desc)s</td>
    379.     <td>%(count)s</td>
    380.     <td>%(Pass)s</td>
    381.     <td>%(fail)s</td>
    382.     <td>%(error)s</td>
    383.     <td><a href="javascript:showClassDetail('%(cid)s',%(count)s)">Detail</a></td>
    384. </tr>
    385. """ # variables: (style, desc, count, Pass, fail, error, cid)


    386.     REPORT_TEST_WITH_OUTPUT_TMPL = r"""
    387. <tr id='%(tid)s' class='%(Class)s'>
    388.     <td class='%(style)s'><div class='testcase'>%(desc)s</div></td>
    389.     <td colspan='5' align='center'>

    390.     <!--css div popup start-->
    391.     <a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_%(tid)s')" >
    392.         %(status)s</a>

    393.     <div id='div_%(tid)s' class="popup_window">
    394.         <div style='text-align: right; color:red;cursor:pointer'>
    395.         <a onfocus='this.blur();' onclick="document.getElementById('div_%(tid)s').style.display = 'none' " >
    396.            [x]</a>
    397.         </div>
    398.         <pre>
    399.         %(script)s
    400.         </pre>
    401.     </div>
    402.     <!--css div popup end-->

    403.     </td>
    404. </tr>
    405. """ # variables: (tid, Class, style, desc, status)


    406.     REPORT_TEST_NO_OUTPUT_TMPL = r"""
    407. <tr id='%(tid)s' class='%(Class)s'>
    408.     <td class='%(style)s'><div class='testcase'>%(desc)s</div></td>
    409.     <td colspan='5' align='center'>%(status)s</td>
    410. </tr>
    411. """ # variables: (tid, Class, style, desc, status)


    412.     REPORT_TEST_OUTPUT_TMPL = r"""
    413. %(id)s: %(output)s
    414. """ # variables: (id, output)



    415.     # ------------------------------------------------------------------------
    416.     # ENDING
    417.     #

    418.     ENDING_TMPL = """<div id='ending'> </div>"""

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


    420. TestResult = unittest.TestResult

    421. class _TestResult(TestResult):
    422.     # note: _TestResult is a pure representation of results.
    423.     # It lacks the output and reporting ability compares to unittest._TextTestResult.

    424.     def __init__(self, verbosity=1):
    425.         TestResult.__init__(self)
    426.         self.stdout0 = None
    427.         self.stderr0 = None
    428.         self.success_count = 0
    429.         self.failure_count = 0
    430.         self.error_count = 0
    431.         self.verbosity = verbosity

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


    440.     def startTest(self, test):
    441.         TestResult.startTest(self, test)
    442.         # just one buffer for both stdout and stderr
    443.         self.outputBuffer = io.StringIO()
    444.         stdout_redirector.fp = self.outputBuffer
    445.         stderr_redirector.fp = self.outputBuffer
    446.         self.stdout0 = sys.stdout
    447.         self.stderr0 = sys.stderr
    448.         sys.stdout = stdout_redirector
    449.         sys.stderr = stderr_redirector


    450.     def complete_output(self):
    451.         """
    452.         Disconnect output redirection and return buffer.
    453.         Safe to call multiple times.
    454.         """
    455.         if self.stdout0:
    456.             sys.stdout = self.stdout0
    457.             sys.stderr = self.stderr0
    458.             self.stdout0 = None
    459.             self.stderr0 = None
    460.         return self.outputBuffer.getvalue()


    461.     def stopTest(self, test):
    462.         # Usually one of addSuccess, addError or addFailure would have been called.
    463.         # But there are some path in unittest that would bypass this.
    464.         # We must disconnect stdout in stopTest(), which is guaranteed to be called.
    465.         self.complete_output()


    466.     def addSuccess(self, test):
    467.         self.success_count += 1
    468.         TestResult.addSuccess(self, test)
    469.         output = self.complete_output()
    470.         self.result.append((0, test, output, ''))
    471.         if self.verbosity > 1:
    472.             sys.stderr.write('ok ')
    473.             sys.stderr.write(str(test))
    474.             sys.stderr.write('\n')
    475.         else:
    476.             sys.stderr.write('.')

    477.     def addError(self, test, err):
    478.         self.error_count += 1
    479.         TestResult.addError(self, test, err)
    480.         _, _exc_str = self.errors[-1]
    481.         output = self.complete_output()
    482.         self.result.append((2, test, output, _exc_str))
    483.         if self.verbosity > 1:
    484.             sys.stderr.write('E  ')
    485.             sys.stderr.write(str(test))
    486.             sys.stderr.write('\n')
    487.         else:
    488.             sys.stderr.write('E')

    489.     def addFailure(self, test, err):
    490.         self.failure_count += 1
    491.         TestResult.addFailure(self, test, err)
    492.         _, _exc_str = self.failures[-1]
    493.         output = self.complete_output()
    494.         self.result.append((1, test, output, _exc_str))
    495.         if self.verbosity > 1:
    496.             sys.stderr.write('F  ')
    497.             sys.stderr.write(str(test))
    498.             sys.stderr.write('\n')
    499.         else:
    500.             sys.stderr.write('F')


    501. class HTMLTestRunner(Template_mixin):
    502.     """
    503.     """
    504.     def __init__(self, stream=sys.stdout, verbosity=1, title=None, description=None):
    505.         self.stream = stream
    506.         self.verbosity = verbosity
    507.         if title is None:
    508.             self.title = self.DEFAULT_TITLE
    509.         else:
    510.             self.title = title
    511.         if description is None:
    512.             self.description = self.DEFAULT_DESCRIPTION
    513.         else:
    514.             self.description = description

    515.         self.startTime = datetime.datetime.now()


    516.     def run(self, test):
    517.         "Run the given test case or test suite."
    518.         result = _TestResult(self.verbosity)
    519.         test(result)
    520.         self.stopTime = datetime.datetime.now()
    521.         self.generateReport(test, result)
    522.         # print >> sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime)
    523.         print(sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime))
    524.         return result


    525.     def sortResult(self, result_list):
    526.         # unittest does not seems to run in any particular order.
    527.         # Here at least we want to group them together by class.
    528.         rmap = {}
    529.         classes = []
    530.         for n,t,o,e in result_list:
    531.             cls = t.__class__
    532.             if not cls in rmap:
    533.                 rmap[cls] = []
    534.                 classes.append(cls)
    535.             rmap[cls].append((n,t,o,e))
    536.         r = [(cls, rmap[cls]) for cls in classes]
    537.         return r


    538.     def getReportAttributes(self, result):
    539.         """
    540.         Return report attributes as a list of (name, value).
    541.         Override this to add custom attributes.
    542.         """
    543.         startTime = str(self.startTime)[:19]
    544.         duration = str(self.stopTime - self.startTime)
    545.         status = []
    546.         if result.success_count: status.append('Pass %s'    % result.success_count)
    547.         if result.failure_count: status.append('Failure %s' % result.failure_count)
    548.         if result.error_count:   status.append('Error %s'   % result.error_count  )
    549.         if status:
    550.             status = ' '.join(status)
    551.         else:
    552.             status = 'none'
    553.         return [
    554.             ('Start Time', startTime),
    555.             ('Duration', duration),
    556.             ('Status', status),
    557.         ]


    558.     def generateReport(self, test, result):
    559.         report_attrs = self.getReportAttributes(result)
    560.         generator = 'HTMLTestRunner %s' % __version__
    561.         stylesheet = self._generate_stylesheet()
    562.         heading = self._generate_heading(report_attrs)
    563.         report = self._generate_report(result)
    564.         ending = self._generate_ending()
    565.         output = self.HTML_TMPL % dict(
    566.             title = saxutils.escape(self.title),
    567.             generator = generator,
    568.             stylesheet = stylesheet,
    569.             heading = heading,
    570.             report = report,
    571.             ending = ending,
    572.         )
    573.         self.stream.write(output.encode('utf-8'))


    574.     def _generate_stylesheet(self):
    575.         return self.STYLESHEET_TMPL


    576.     def _generate_heading(self, report_attrs):
    577.         a_lines = []
    578.         for name, value in report_attrs:
    579.             line = self.HEADING_ATTRIBUTE_TMPL % dict(
    580.                     name = saxutils.escape(name),
    581.                     value = saxutils.escape(value),
    582.                 )
    583.             a_lines.append(line)
    584.         heading = self.HEADING_TMPL % dict(
    585.             title = saxutils.escape(self.title),
    586.             parameters = ''.join(a_lines),
    587.             description = saxutils.escape(self.description),
    588.         )
    589.         return heading


    590.     def _generate_report(self, result):
    591.         rows = []
    592.         sortedResult = self.sortResult(result.result)
    593.         for cid, (cls, cls_results) in enumerate(sortedResult):
    594.             # subtotal for a class
    595.             np = nf = ne = 0
    596.             for n,t,o,e in cls_results:
    597.                 if n == 0: np += 1
    598.                 elif n == 1: nf += 1
    599.                 else: ne += 1

    600.             # format class description
    601.             if cls.__module__ == "__main__":
    602.                 name = cls.__name__
    603.             else:
    604.                 name = "%s.%s" % (cls.__module__, cls.__name__)
    605.             doc = cls.__doc__ and cls.__doc__.split("\n")[0] or ""
    606.             desc = doc and '%s: %s' % (name, doc) or name

    607.             row = self.REPORT_CLASS_TMPL % dict(
    608.                 style = ne > 0 and 'errorClass' or nf > 0 and 'failClass' or 'passClass',
    609.                 desc = desc,
    610.                 count = np+nf+ne,
    611.                 Pass = np,
    612.                 fail = nf,
    613.                 error = ne,
    614.                 cid = 'c%s' % (cid+1),
    615.             )
    616.             rows.append(row)

    617.             for tid, (n,t,o,e) in enumerate(cls_results):
    618.                 self._generate_report_test(rows, cid, tid, n, t, o, e)

    619.         report = self.REPORT_TMPL % dict(
    620.             test_list = ''.join(rows),
    621.             count = str(result.success_count+result.failure_count+result.error_count),
    622.             Pass = str(result.success_count),
    623.             fail = str(result.failure_count),
    624.             error = str(result.error_count),
    625.         )
    626.         return report


    627.     def _generate_report_test(self, rows, cid, tid, n, t, o, e):
    628.         # e.g. 'pt1.1', 'ft1.1', etc
    629.         has_output = bool(o or e)
    630.         tid = (n == 0 and 'p' or 'f') + 't%s.%s' % (cid+1,tid+1)
    631.         name = t.id().split('.')[-1]
    632.         doc = t.shortDescription() or ""
    633.         desc = doc and ('%s: %s' % (name, doc)) or name
    634.         tmpl = has_output and self.REPORT_TEST_WITH_OUTPUT_TMPL or self.REPORT_TEST_NO_OUTPUT_TMPL

    635.         # o and e should be byte string because they are collected from stdout and stderr?
    636.         if isinstance(o,str):
    637.             # TODO: some problem with 'string_escape': it escape \n and mess up formating
    638.             # uo = unicode(o.encode('string_escape'))
    639.             # uo = o.decode('latin-1')
    640.             uo = e
    641.         else:
    642.             uo = o
    643.         if isinstance(e,str):
    644.             # TODO: some problem with 'string_escape': it escape \n and mess up formating
    645.             # ue = unicode(e.encode('string_escape'))
    646.             # ue = e.decode('latin-1')
    647.             ue = e
    648.         else:
    649.             ue = e

    650.         script = self.REPORT_TEST_OUTPUT_TMPL % dict(
    651.             id = tid,
    652.             output = saxutils.escape(str(uo)+ue),
    653.         )

    654.         row = tmpl % dict(
    655.             tid = tid,
    656.             Class = (n == 0 and 'hiddenRow' or 'none'),
    657.             style = n == 2 and 'errorCase' or (n == 1 and 'failCase' or 'none'),
    658.             desc = desc,
    659.             script = script,
    660.             status = self.STATUS[n],
    661.         )
    662.         rows.append(row)
    663.         if not has_output:
    664.             return

    665.     def _generate_ending(self):
    666.         return self.ENDING_TMPL


    667. ##############################################################################
    668. # Facilities for running tests from the command line
    669. ##############################################################################

    670. # Note: Reuse unittest.TestProgram to launch test. In the future we may
    671. # build our own launcher to support more specific command line
    672. # parameters like test title, CSS, etc.
    673. class TestProgram(unittest.TestProgram):
    674.     """
    675.     A variation of the unittest.TestProgram. Please refer to the base
    676.     class for command line parameters.
    677.     """
    678.     def runTests(self):
    679.         # Pick HTMLTestRunner as the default test runner.
    680.         # base class's testRunner parameter is not useful because it means
    681.         # we have to instantiate HTMLTestRunner before we know self.verbosity.
    682.         if self.testRunner is None:
    683.             self.testRunner = HTMLTestRunner(verbosity=self.verbosity)
    684.         unittest.TestProgram.runTests(self)

    685. main = TestProgram

    686. ##############################################################################
    687. # Executing this module from the command line
    688. ##############################################################################

    689. if __name__ == "__main__":
    690.     main(module=None)
    复制代码




    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    4 小时前
  • 签到天数: 1516 天

    连续签到: 5 天

    [LV.Master]测试大本营

    2#
    发表于 2018-7-31 10:27:52 | 只看该作者
    检查下权限
    回复

    使用道具 举报

  • TA的每日心情
    开心
    7 天前
  • 签到天数: 473 天

    连续签到: 2 天

    [LV.9]测试副司令

    3#
    发表于 2018-7-31 11:06:36 | 只看该作者
    没有赋予权限
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    7 小时前
  • 签到天数: 2812 天

    连续签到: 5 天

    [LV.Master]测试大本营

    4#
    发表于 2018-7-31 13:14:51 | 只看该作者
    权限问题吧
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2022-7-23 11:23
  • 签到天数: 316 天

    连续签到: 1 天

    [LV.8]测试军长

    5#
    发表于 2018-7-31 13:40:16 | 只看该作者
    真心问题描述太长了,看不懂
    回复

    使用道具 举报

  • TA的每日心情

    2020-2-2 12:43
  • 签到天数: 630 天

    连续签到: 1 天

    [LV.9]测试副司令

    6#
    发表于 2018-7-31 15:39:32 | 只看该作者
    权限问题?
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-15 15:10 , Processed in 0.071202 second(s), 22 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表