C:\Python27\Lib中修改unittest内容

unittest 在init中添加Myskip代码:

__all__ = ['TestResult', 'TestCase', 'TestSuite','TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main','defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless','expectedFailure', 'TextTestResult', 'installHandler','registerResult', 'removeResult', 'removeHandler','Myskip']from .case import (TestCase, FunctionTestCase, SkipTest, skip, skipIf, Myskip,skipUnless, expectedFailure)

unittest在case.py中增加如下代码:

def _id(obj):
  return obj

def Myskip(func):def RebackTest(self):if self._resultForDoCleanups.failures or self._resultForDoCleanups.errors:raise SkipTest("{} do not excute because {} is failed".format(func.__name__,self._resultForDoCleanups.failures[0][0]._testMethodName))func(self)return  RebackTest

C:\Python27\Lib修改HTMLReport文件(Python2)

  1 #coding=utf-8
  2 """
  3 A TestRunner for use with the Python unit testing framework. It
  4 generates a HTML report to show the result at a glance.
  5
  6 The simplest way to use this is to invoke its main method. E.g.
  7
  8     import unittest
  9     import HTMLTestRunner
 10
 11     ... define your tests ...
 12
 13     if __name__ == '__main__':
 14         HTMLTestRunner.main()
 15
 16
 17 For more customization options, instantiates a HTMLTestRunner object.
 18 HTMLTestRunner is a counterpart to unittest's TextTestRunner. E.g.
 19
 20     # output to a file
 21     fp = file('my_report.html', 'wb')
 22     runner = HTMLTestRunner.HTMLTestRunner(
 23                 stream=fp,
 24                 title='My unit test',
 25                 description='This demonstrates the report output by HTMLTestRunner.'
 26                 )
 27
 28     # Use an external stylesheet.
 29     # See the Template_mixin class for more customizable options
 30     runner.STYLESHEET_TMPL = '<link rel="stylesheet" href="my_stylesheet.css" type="text/css">'
 31
 32     # run the test
 33     runner.run(my_test_suite)
 34
 35
 36 ------------------------------------------------------------------------
 37 Copyright (c) 2004-2007, Wai Yip Tung
 38 All rights reserved.
 39
 40 Redistribution and use in source and binary forms, with or without
 41 modification, are permitted provided that the following conditions are
 42 met:
 43
 44 * Redistributions of source code must retain the above copyright notice,
 45   this list of conditions and the following disclaimer.
 46 * Redistributions in binary form must reproduce the above copyright
 47   notice, this list of conditions and the following disclaimer in the
 48   documentation and/or other materials provided with the distribution.
 49 * Neither the name Wai Yip Tung nor the names of its contributors may be
 50   used to endorse or promote products derived from this software without
 51   specific prior written permission.
 52
 53 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 54 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 55 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 56 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 57 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 58 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 59 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 60 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 61 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 62 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 63 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 64 """
 65
 66 # URL: http://tungwaiyip.info/software/HTMLTestRunner.html
 67
 68 __author__ = "Wai Yip Tung"
 69 __version__ = "0.8.2"
 70
 71
 72 """
 73 Change History
 74
 75 Version 0.8.2
 76 * Show output inline instead of popup window (Viorel Lupu).
 77
 78 Version in 0.8.1
 79 * Validated XHTML (Wolfgang Borgert).
 80 * Added description of test classes and test cases.
 81
 82 Version in 0.8.0
 83 * Define Template_mixin class for customization.
 84 * Workaround a IE 6 bug that it does not treat <script> block as CDATA.
 85
 86 Version in 0.7.1
 87 * Back port to Python 2.3 (Frank Horowitz).
 88 * Fix missing scroll bars in detail log (Podi).
 89 """
 90
 91 # TODO: color stderr
 92 # TODO: simplify javascript using ,ore than 1 class in the class attribute?
 93 #coding=utf-8
 94 import datetime
 95 import io
 96 import sys
 97 reload(sys)
 98 sys.setdefaultencoding('utf8')
 99 import time
100 import unittest
101 import re
102 from xml.sax import saxutils
103
104
105 # ------------------------------------------------------------------------
106 # The redirectors below are used to capture output during testing. Output
107 # sent to sys.stdout and sys.stderr are automatically captured. However
108 # in some cases sys.stdout is already cached before HTMLTestRunner is
109 # invoked (e.g. calling logging.basicConfig). In order to capture those
110 # output, use the redirectors for the cached stream.
111 #
112 # e.g.
113 #   >>> logging.basicConfig(stream=HTMLTestRunner.stdout_redirector)
114 #   >>>
115
116 class OutputRedirector(object):
117     """ Wrapper to redirect stdout or stderr """
118     def __init__(self, fp):
119         self.fp = fp
120
121     def write(self, s):
122         self.fp.write(s)
123
124     def writelines(self, lines):
125         self.fp.writelines(lines)
126
127     def flush(self):
128         self.fp.flush()
129
130 stdout_redirector = OutputRedirector(sys.stdout)
131 stderr_redirector = OutputRedirector(sys.stderr)
132
133
134
135 # ----------------------------------------------------------------------
136 # Template
137
138 class Template_mixin(object):
139     """
140     Define a HTML template for report customerization and generation.
141
142     Overall structure of an HTML report
143
144     HTML
145     +------------------------+
146     |<html>                  |
147     |  <head>                |
148     |                        |
149     |   STYLESHEET           |
150     |   +----------------+   |
151     |   |                |   |
152     |   +----------------+   |
153     |                        |
154     |  </head>               |
155     |                        |
156     |  <body>                |
157     |                        |
158     |   HEADING              |
159     |   +----------------+   |
160     |   |                |   |
161     |   +----------------+   |
162     |                        |
163     |   REPORT               |
164     |   +----------------+   |
165     |   |                |   |
166     |   +----------------+   |
167     |                        |
168     |   ENDING               |
169     |   +----------------+   |
170     |   |                |   |
171     |   +----------------+   |
172     |                        |
173     |  </body>               |
174     |</html>                 |
175     +------------------------+
176     """
177
178     STATUS = {
179     0: 'pass',
180     1: 'fail',
181     2: 'error',
182     3:'skip'
183     }
184
185     DEFAULT_TITLE = 'Unit Test Report'
186     DEFAULT_DESCRIPTION = ''
187
188     # ------------------------------------------------------------------------
189     # HTML Template
190
191     HTML_TMPL = r"""<?xml version="1.0" encoding="UTF-8"?>
192 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
193 <html xmlns="http://www.w3.org/1999/xhtml">
194 <head>
195     <title>%(title)s</title>
196     <meta name="generator" content="%(generator)s"/>
197     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
198     %(stylesheet)s
199 </head>
200 <body>
201 <script language="javascript" type="text/javascript"><!--
202 output_list = Array();
203
204 /* level - 0:Summary; 1:Failed; 2:All */
205 function showCase(level) {
206     trs = document.getElementsByTagName("tr");
207     for (var i = 0; i < trs.length; i++) {
208         tr = trs[i];
209         id = tr.id;
210         if (id.substr(0,2) == 'ft') {
211             if (level < 1) {
212                 tr.className = 'hiddenRow';
213             }
214             else {
215                 tr.className = '';
216             }
217         }
218         if (id.substr(0,2) == 'pt') {
219             if (level > 1) {
220                 tr.className = '';
221             }
222             else {
223                 tr.className = 'hiddenRow';
224             }        }        if (id.substr(0,2) == 'st') {           if (level > 1) {               tr.className = '';            }           else {               tr.className = 'hiddenRow';           }
225         }
226     }
227 }
228
229 function showClassDetail(cid, count) {
230     var id_list = Array(count);
231     var toHide = 1;
232     for (var i = 0; i < count; i++) {
233         tid0 = 't' + cid.substr(1) + '.' + (i+1);
234         tid = 'f' + tid0;
235         tr = document.getElementById(tid);
236         if (!tr) {
237             tid = 'p' + tid0;
238             tr = document.getElementById(tid);
239         }
240          if (!tr) {
241             tid = 's' + tid0;
242             tr = document.getElementById(tid);
243         }
244         id_list[i] = tid;
245         if (tr.className) {
246             toHide = 0;
247         }
248
249     }
250     for (var i = 0; i < count; i++) {
251         tid = id_list[i];
252         if (toHide) {
253             document.getElementById('div_'+tid).style.display = 'none'
254             document.getElementById(tid).className = 'hiddenRow';
255         }
256         else {
257             document.getElementById(tid).className = '';
258         }
259     }
260 }
261
262
263 function showTestDetail(div_id){
264     var details_div = document.getElementById(div_id)
265     var displayState = details_div.style.display
266     // alert(displayState)
267     if (displayState != 'block' ) {
268         displayState = 'block'
269         details_div.style.display = 'block'
270     }
271     else {
272         details_div.style.display = 'none'
273     }
274 }
275
276
277 function html_escape(s) {
278     s = s.replace(/&/g,'&');
279     s = s.replace(/</g,'<');
280     s = s.replace(/>/g,'>');
281     return s;
282 }
283
284 /* obsoleted by detail in <div>
285 function showOutput(id, name) {
286     var w = window.open("", //url
287                     name,
288                     "resizable,scrollbars,status,width=800,height=450");
289     d = w.document;
290     d.write("<pre>");
291     d.write(html_escape(output_list[id]));
292     d.write("\n");
293     d.write("<a href='javascript:window.close()'>close</a>\n");
294     d.write("</pre>\n");
295     d.close();
296 }
297 */
298 --></script>
299
300 %(heading)s
301 %(report)s
302 %(ending)s
303
304 </body>
305 </html>
306 """
307     # variables: (title, generator, stylesheet, heading, report, ending)
308
309
310     # ------------------------------------------------------------------------
311     # Stylesheet
312     #
313     # alternatively use a <link> for external style sheet, e.g.
314     #   <link rel="stylesheet" href="$url" type="text/css">
315
316     STYLESHEET_TMPL = """
317 <style type="text/css" media="screen">
318 body        { font-family: verdana, arial, helvetica, sans-serif; font-size: 80%; }
319 table       { font-size: 100%; }
320 pre         { word-wrap:break-word;word-break:break-all;overflow:auto;}
321
322 /* -- heading ---------------------------------------------------------------------- */
323 h1 {
324     font-size: 16pt;
325     color: gray;
326 }
327 .heading {
328     margin-top: 0ex;
329     margin-bottom: 1ex;
330 }
331
332 .heading .attribute {
333     margin-top: 1ex;
334     margin-bottom: 0;
335 }
336
337 .heading .description {
338     margin-top: 4ex;
339     margin-bottom: 6ex;
340 }
341
342 /* -- css div popup ------------------------------------------------------------------------ */
343 a.popup_link {
344 }
345
346 a.popup_link:hover {
347     color: red;
348 }
349
350 .popup_window {
351     display: none;
352     position: relative;
353     left: 0px;
354     top: 0px;
355     /*border: solid #627173 1px; */
356     padding: 10px;
357     background-color: 00;
358     font-family: "Lucida Console", "Courier New", Courier, monospace;
359     text-align: left;
360     font-size: 8pt;
361     width: 600px;
362 }
363
364 }
365 /* -- report ------------------------------------------------------------------------ */
366 #show_detail_line {
367     margin-top: 3ex;
368     margin-bottom: 1ex;
369 }
370 #result_table {
371     width: 80%;
372     border-collapse: collapse;
373     border: 1px solid #777;
374 }
375 #header_row {
376     font-weight: bold;
377     color: white;
378     background-color: #777;
379 }
380 #result_table td {
381     border: 1px solid #777;
382     padding: 2px;
383 }
384 #total_row  { font-weight: bold; }
385 .passClass  { background-color: #6c6; }
386 .failClass  { background-color: #c60; }
387 .errorClass { background-color: #c00; }
388 .passCase   { color: #6c6; }
389 .failCase   { color: #c60; font-weight: bold; }
390 .errorCase  { color: #c00; font-weight: bold; }
391 .hiddenRow  { display: none; }
392 .testcase   { margin-left: 2em; }
393
394
395 /* -- ending ---------------------------------------------------------------------- */
396 #ending {
397 }
398
399 </style>
400 """
401
402
403
404     # ------------------------------------------------------------------------
405     # Heading
406     #
407
408     HEADING_TMPL = """<div class='heading'>
409 <h1>%(title)s</h1>
410 %(parameters)s
411 <p class='description'>%(description)s</p>
412 </div>
413
414 """ # variables: (title, parameters, description)
415
416     HEADING_ATTRIBUTE_TMPL = """<p class='attribute'><strong>%(name)s:</strong> %(value)s</p>
417 """ # variables: (name, value)
418
419
420
421     # ------------------------------------------------------------------------
422     # Report
423     #
424
425     REPORT_TMPL = """
426 <p id='show_detail_line'>Show
427 <a href='javascript:showCase(0)'>Summary</a>
428 <a href='javascript:showCase(1)'>Failed</a>
429 <a href='javascript:showCase(2)'>All</a>
430 </p>
431 <table id='result_table'>
432 <colgroup>
433 <col align='left' />
434 <col align='right' />
435 <col align='right' />
436 <col align='right' />
437 <col align='right' />
438 <col align='right' />
439 </colgroup>
440 <tr id='header_row'>
441     <td>Test Group/Test case</td>
442     <td>Count</td>
443     <td>Pass</td>
444     <td>Fail</td>
445     <td>Error</td>
446     <td>Skip</td>
447     <td>View</td>
448     <td>Screenshot</td>
449 </tr>
450 %(test_list)s
451 <tr id='total_row'>
452     <td>Total</td>
453     <td>%(count)s</td>
454     <td>%(Pass)s</td>
455     <td>%(fail)s</td>
456     <td>%(error)s</td>
457     <td>%(skip)s</td>
458     <td> </td>
459     <td> </td>
460
461 </tr>
462 </table>
463 """ # variables: (test_list, count, Pass, fail, error)
464
465     REPORT_CLASS_TMPL = r"""
466 <tr class='%(style)s'>
467     <td>%(desc)s</td>
468     <td>%(count)s</td>
469     <td>%(Pass)s</td>
470     <td>%(fail)s</td>
471     <td>%(error)s</td>
472     <td>%(skip)s</td>
473     <td><a href="javascript:showClassDetail('%(cid)s',%(count)s)">Detail</a></td>
474     <td> </td>
475 </tr>
476 """ # variables: (style, desc, count, Pass, fail,skip, error, cid)
477
478
479     REPORT_TEST_WITH_OUTPUT_TMPL = r"""
480 <tr id='%(tid)s' class='%(Class)s'>
481     <td class='%(style)s'><div class='testcase'>%(desc)s</div></td>
482     <td colspan='6' align='center'>
483     <!--css div popup start-->
484     <a class="popup_link" οnfοcus='this.blur();' href="javascript:showTestDetail('div_%(tid)s')" >
485         %(status)s</a>
486
487     <div id='div_%(tid)s' class="popup_window" >
488         <div style='text-align: right; color:red;cursor:pointer'>
489         <a οnfοcus='this.blur();' οnclick="document.getElementById('div_%(tid)s').style.display = 'none' " >
490            [x]</a>
491         </div>
492         <pre>
493         %(script)s
494         </pre>
495     </div>
496     <!--css div popup end-->
497     </td>
498     <td align='center'>
499     <a  %(hidde)s  href="%(image)s">picture_shot</a>
500     </td>
501 </tr>
502 """ # variables: (tid, Class, style, desc, status)
503     REPORT_TEST_NO_OUTPUT_TMPL = r"""
504 <tr id='%(tid)s' class='%(Class)s'>
505     <td class='%(style)s'><div class='testcase'>%(desc)s</div></td>
506     <td colspan='6' align='center'>%(status)s</td>
507     <td align='center'>
508     <a  %(hidde)s  href="%(image)s">picture_shot</a>
509     </td>
510 </tr>
511 """ # variables: (tid, Class, style, desc, status)
512
513
514     REPORT_TEST_OUTPUT_TMPL = r"""
515 %(id)s: %(output)s
516 """
517
518     # variables: (id, output)
519
520
521
522     # ------------------------------------------------------------------------
523     # ENDING
524     #
525
526     ENDING_TMPL = """<div id='ending'> </div>"""
527
528 # -------------------- The end of the Template class -------------------
529
530
531 TestResult = unittest.TestResult
532
533 class _TestResult(TestResult):
534     # note: _TestResult is a pure representation of results.
535     # It lacks the output and reporting ability compares to unittest._TextTestResult.
536
537     def __init__(self, verbosity=1):
538         TestResult.__init__(self)
539         self.stdout0 = None
540         self.stderr0 = None
541         self.success_count = 0
542         self.skipped_count=0#add skipped_count
543         self.failure_count = 0
544         self.error_count = 0
545         self.verbosity = verbosity
546
547         # result is a list of result in 4 tuple
548         # (
549         #   result code (0: success; 1: fail; 2: error),
550         #   TestCase object,
551         #   Test output (byte string),
552         #   stack trace,
553         # )
554         self.result = []
555
556
557     def startTest(self, test):
558         TestResult.startTest(self, test)
559         # just one buffer for both stdout and stderr
560         self.outputBuffer = io.BytesIO()
561         stdout_redirector.fp = self.outputBuffer
562         stderr_redirector.fp = self.outputBuffer
563         self.stdout0 = sys.stdout
564         self.stderr0 = sys.stderr
565         sys.stdout = stdout_redirector
566         sys.stderr = stderr_redirector
567
568
569     def complete_output(self):
570         """
571         Disconnect output redirection and return buffer.
572         Safe to call multiple times.
573         """
574         if self.stdout0:
575             sys.stdout = self.stdout0
576             sys.stderr = self.stderr0
577             self.stdout0 = None
578             self.stderr0 = None
579         return self.outputBuffer.getvalue()
580
581
582     def stopTest(self, test):
583         # Usually one of addSuccess, addError or addFailure would have been called.
584         # But there are some path in unittest that would bypass this.
585         # We must disconnect stdout in stopTest(), which is guaranteed to be called.
586         self.complete_output()
587
588
589     def addSuccess(self, test):
590         self.success_count += 1
591         TestResult.addSuccess(self, test)
592         output = self.complete_output()
593         self.result.append((0, test, output, ''))
594         if self.verbosity > 1:
595             sys.stderr.write('ok ')
596             sys.stderr.write(str(test))
597             sys.stderr.write('\n')
598         else:
599             sys.stderr.write('.')
600
601     def addSkip(self, test, reason):
602         self.skipped_count+= 1
603         TestResult.addSkip(self, test,reason)
604         output = self.complete_output()
605         self.result.append((3, test,'',reason))
606         if self.verbosity > 1:
607             sys.stderr.write('skip ')
608             sys.stderr.write(str(test))
609             sys.stderr.write('\n')
610         else:
611             sys.stderr.write('s')
612     def addError(self, test, err):
613         self.error_count += 1
614         TestResult.addError(self, test, err)
615         _, _exc_str = self.errors[-1]
616         output = self.complete_output()
617         self.result.append((2, test, output, _exc_str))
618         if self.verbosity > 1:
619             sys.stderr.write('E  ')
620             sys.stderr.write(str(test))
621             sys.stderr.write('\n')
622         else:
623             sys.stderr.write('E')
624
625     def addFailure(self, test, err):
626         self.failure_count += 1
627         TestResult.addFailure(self, test, err)
628         _, _exc_str = self.failures[-1]
629         output = self.complete_output()
630         self.result.append((1, test, output, _exc_str))
631         if self.verbosity > 1:
632             sys.stderr.write('F  ')
633             sys.stderr.write(str(test))
634             sys.stderr.write('\n')
635         else:
636             sys.stderr.write('F')
637
638
639 class HTMLTestRunner(Template_mixin):
640     """
641     """
642     def __init__(self, stream=sys.stdout, verbosity=1, title=None, description=None,name=None):
643         self.stream = stream
644         self.verbosity = verbosity
645         if title is None:
646             self.title = self.DEFAULT_TITLE
647         else:
648             self.title = title
649         if name is None:
650             self.name =''
651         else:
652             self.name = name
653         if description is None:
654             self.description = self.DEFAULT_DESCRIPTION
655         else:
656             self.description = description
657
658         self.startTime = datetime.datetime.now()
659
660
661     def run(self, test):
662         "Run the given test case or test suite."
663         result = _TestResult(self.verbosity)
664         test(result)
665         self.stopTime = datetime.datetime.now()
666         self.generateReport(test, result)
667         # print (sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime))
668         return result
669
670
671     def sortResult(self, result_list):
672         # unittest does not seems to run in any particular order.
673         # Here at least we want to group them together by class.
674         rmap = {}
675         classes = []
676         for n,t,o,e in result_list:
677             cls = t.__class__
678             if not cls in rmap:
679                 rmap[cls] = []
680                 classes.append(cls)
681             rmap[cls].append((n,t,o,e))
682         r = [(cls, rmap[cls]) for cls in classes]
683         return r
684
685
686     def getReportAttributes(self, result):
687         """
688         Return report attributes as a list of (name, value).
689         Override this to add custom attributes.
690         """
691         startTime = str(self.startTime)[:19]
692         duration = str(self.stopTime - self.startTime)
693         status = []
694         if result.success_count: status.append('Pass %s'    % result.success_count)
695         if result.failure_count: status.append('Failure %s' % result.failure_count)
696         if result.skipped_count: status.append('Skip %s' % result.skipped_count)
697         if result.error_count:   status.append('Error %s'   % result.error_count  )
698         if status:
699             status = ' '.join(status)
700         else:
701             status = 'none'
702         return [
703             ('Start Time', startTime),
704             ('Duration', duration),
705             ('Status', status),
706         ]
707
708
709     def generateReport(self, test, result):
710         report_attrs = self.getReportAttributes(result)#报告的头部
711         generator = 'HTMLTestRunner %s' % __version__
712         stylesheet = self._generate_stylesheet()#拿到css文件
713         heading = self._generate_heading(report_attrs)
714         report = self._generate_report(result)
715         ending = self._generate_ending()
716         output = self.HTML_TMPL % dict(
717             title = saxutils.escape(self.title),
718             generator = generator,
719             stylesheet = stylesheet,
720             heading = heading,
721             report = report,
722             ending = ending,
723         )
724         self.stream.write(output.encode('utf8'))
725
726
727     def _generate_stylesheet(self):
728         return self.STYLESHEET_TMPL
729
730
731     def _generate_heading(self, report_attrs):
732         a_lines = []
733         for name, value in report_attrs:
734             line = self.HEADING_ATTRIBUTE_TMPL % dict(
735                     name = saxutils.escape(name),
736                     value = saxutils.escape(value),
737                 )
738             a_lines.append(line)
739         heading = self.HEADING_TMPL % dict(
740             title = saxutils.escape(self.title),
741             parameters = ''.join(a_lines),
742             description = saxutils.escape(self.description),
743         )
744         return heading
745 #根据result收集报告
746     def _generate_report(self, result):
747         rows = []
748         sortedResult = self.sortResult(result.result)
749         i = 0
750         for cid, (cls, cls_results) in enumerate(sortedResult):
751             # subtotal for a class
752             np = nf =ns=ne = 0#np代表pass个数,nf代表fail,ns代表skip,ne,代表error
753             for n,t,o,e in cls_results:
754                 if n == 0: np += 1
755                 elif n == 1: nf += 1
756                 elif n==3:ns+=1
757                 else: ne += 1
758
759             # format class description
760             # if cls.__module__ == "__main__":
761             #     name = cls.__name__
762             # else:
763             #     name = "%s.%s" % (cls.__module__, cls.__name__)
764             name = cls.__name__
765             try:
766                 core_name=self.name[i]
767             except Exception,e:
768                 core_name =''
769             # doc = (cls.__doc__)+core_name and (cls.__doc__+core_name).split("\n")[0] or ""
770             doc = (cls.__doc__)  and cls.__doc__ .split("\n")[0] or ""
771             desc = doc and '%s: %s' % (name, doc) or name
772             i=i+1            #生成每个TestCase类的汇总数据,对于报告中的
773             row = self.REPORT_CLASS_TMPL % dict(
774                 style = ne > 0 and 'errorClass' or nf > 0 and 'failClass' or 'passClass',
775                 desc = desc,
776                 count = np+nf+ne+ns,
777                 Pass = np,
778                 fail = nf,
779                 error = ne,
780                 skip=ns,
781                 cid = 'c%s' % (cid+1),
782             )
783             rows.append(row)
784             #生成每个TestCase类中所有方法的测试结果
785             for tid, (n,t,o,e) in enumerate(cls_results):
786                 self._generate_report_test(rows, cid, tid, n, t, o, e)
787
788         report = self.REPORT_TMPL % dict(
789             test_list = ''.join(rows),
790             count = str(result.success_count+result.failure_count+result.error_count+result.skipped_count),
791             Pass = str(result.success_count),
792             fail = str(result.failure_count),
793             error = str(result.error_count),
794             skip=str(result.skipped_count)
795         )
796         return report
797
798
799     def _generate_report_test(self, rows, cid, tid, n, t, o, e):
800         # e.g. 'pt1.1', 'ft1.1', etc
801         has_output = bool(o or e)
802         tid = (n == 0 and 'p' or n==3 and 's' or 'f') + 't%s.%s' % (cid+1,tid+1)
803         name = t.id().split('.')[-1]
804         doc = t.shortDescription() or ""
805         desc = doc and ('%s: %s' % (name, doc)) or name
806         tmpl = has_output and self.REPORT_TEST_WITH_OUTPUT_TMPL or self.REPORT_TEST_NO_OUTPUT_TMPL
807         uo1=""
808         # o and e should be byte string because they are collected from stdout and stderr?
809         if isinstance(o,str):
810             uo = str(o)
811         else:
812             uo = e
813         if isinstance(e,str):
814             # TODO: some problem with 'string_escape': it escape \n and mess up formating
815             # ue = unicode(e.encode('string_escape'))
816             ue = e
817         else:
818             ue = o
819         script = self.REPORT_TEST_OUTPUT_TMPL % dict(
820             id = tid,
821             output = saxutils.escape(str(uo) + str(ue))
822         )
823
824         if "shot_picture_name" in str(saxutils.escape(str(ue))):
825             hidde_status=''
826             pattern = re.compile(r'AssertionError:.*?shot_picture_name=(.*)',re.S)
827             shot_name =re.search(pattern,str(saxutils.escape(str(e))))
828             try:
829                 image_url="http://192.168.99.105/contractreport/screenshot/"+time.strftime("%Y-%m-%d", time.localtime(time.time()))+"/"+shot_name.group(1)+".png"
830             except Exception,e:
831                 image_url = "http://192.168.99.105/contractreport/screenshot/" + time.strftime("%Y-%m-%d",time.localtime(time.time()))
832
833         else:
834             hidde_status = '''hidden="hidden"'''
835             image_url=''
836         row = tmpl % dict(
837             tid = tid,
838             Class = (n == 0 and 'hiddenRow' or 'none'),
839             style=n == 2 and 'errorCase' or (n == 1 and 'failCase') or (n == 3 and 'skipCase' or 'none'),
840             desc = desc,
841             script = script,
842             hidde=hidde_status,
843         image=image_url,
844             status = self.STATUS[n],
845         )
846
847         rows.append(row)
848         if not has_output:
849             return
850
851     def _generate_ending(self):
852         return self.ENDING_TMPL
853
854
855 ##############################################################################
856 # Facilities for running tests from the command line
857 ##############################################################################
858
859 # Note: Reuse unittest.TestProgram to launch test. In the future we may
860 # build our own launcher to support more specific command line
861 # parameters like test title, CSS, etc.
862 # class TestProgram(unittest.TestProgram):
863 #     """
864 #     A variation of the unittest.TestProgram. Please refer to the base
865 #     class for command line parameters.
866 #     """
867 #     def runTests(self):
868 #         # Pick HTMLTestRunner as the default test runner.
869 #         # base class's testRunner parameter is not useful because it means
870 #         # we have to instantiate HTMLTestRunner before we know self.verbosity.
871 #         if self.testRunner is None:
872 #             self.testRunner = HTMLTestRunner(verbosity=self.verbosity)
873 #         unittest.TestProgram.runTests(self)
874 #
875 # main = TestProgram
876
877 ##############################################################################
878 # Executing this module from the command line
879 ##############################################################################
880
881 if __name__ == "__main__":
882     main(module=None)

测试SKIP代码

 1 #coding=utf-8
 2 import unittest
 3 # import HTMLTestRunner
 4 import HTMLTestRunner_python2
 5 import time
 6 import sys,os
 7
 8 class Mydemo(unittest.TestCase):
 9     def test1(self):
10         print "excute test1"
11     @unittest.Myskip
12     def test2(self):
13         print "excute test2"
14
15     @unittest.Myskip
16     def test3(self):
17         print "excute test3"
18         raise AssertionError("test3 fail")
19     @unittest.Myskip
20     def test4(self):
21         print "excute test4"
22
23
24 def suite():
25     #添加测试用例
26     suiteTest=unittest.TestSuite()
27     # suiteTest.addTest(Mydemo("test1"))
28     # suiteTest.addTest(Mydemo("test2"))
29     # suiteTest.addTest(Mydemo("test3"))
30     # suiteTest.addTest(Mydemo("test4"))
31     suiteTest.addTests(map(Mydemo,["test1","test2","test3","test4"]))
32     return suiteTest
33
34 if __name__=='__main__':
35     # unittest.main()
36     now = time.strftime("%Y-%m-%d-%H_%M_%S", time.localtime(time.time()))
37     filepath = r'D:\Python\report\{0}result.html'.format(now)
38     print(filepath)
39     fp = file(filepath, 'wb')
40
41     # 定义测试报告的标题与描述
42     runner = HTMLTestRunner_python2.HTMLTestRunner(stream=fp, title=u'单元测试用例', description=u'测试执行情况')
43     #执行测试用例
44     runner.run(suite())
45     fp.close()

测试结果如图所示:

转载于:https://www.cnblogs.com/yye2010/p/8579686.html

Python的unittest拓展和HTMLReport SKIP报表扩展相关推荐

  1. python+selenium+unittest+ddt参数化实现自动化运行和脚本并生成报告

    test fixture:初始化和清理测试环境,比如创建临时的数据库,文件和目录等,其中 setUp() 和 setDown() 是最常用的方法. test case:单元测试用例,TestCase ...

  2. Python +selenium+unittest+ddt数据化实现自动化运行和脚本并生成报告

    一.unittest 框架解析 unittest 是 python 的单元测试框架.unittest 单元测试提供了创建测试用例,测试套件以及批量执行的方案, unittest 在安装 pyhton ...

  3. python unit test 访问开发代码,使用Python的unittest模块作为testrunner时,如何在测试前运行初始化代码?...

    How can a user of a library run his own initialization code (setting debug levels of loggers for exa ...

  4. selenium + python自动化测试unittest框架学习(二)

    1.unittest单元测试框架文件结构 unittest是python单元测试框架之一,unittest测试框架的主要文件结构: File >report >all_case.py &g ...

  5. python 参数拼接token_对python的unittest架构公共参数token提取方法详解

    额...每个请求都有token值的传入,但是token非常易变,一旦变化,所有的接口用例都得改一遍token,工作量太大了... 那么有没有一种方法能把token提取出来,作为一个全局变量,作为一个参 ...

  6. selenium + python自动化测试unittest框架学习(一)selenium原理及应用

    unittest框架的学习得益于虫师的<selenium+python自动化实践>这一书,该书讲得很详细,大家可以去看下,我也只学到一点点用于工作中,闲暇时记录下自己所学才能更加印象深刻. ...

  7. python的unittest测试类代码实例

    nittest单元测试框架不仅可以适用于单元测试,还可以适用WEB自动化测试用例的开发与执行,该测试框架可组织执行测试用例,并且提供了丰富的断言方法,判断测试用例是否通过,最终生成测试结果.今天笔者就 ...

  8. Excel、Python靠边站,这才是实现报表自动化最快的方法

    最近在跟隔壁部门闲聊的时候,我发现会有这样的情况.他们跟我吐槽说,每天需要花很多时间做报表,但我发现其实他们80%的报表都是机械.重复式的手工操作,最夸张的一张报表需要花两个小时才能更新完.作为报表老 ...

  9. 由浅入深----python+requests+unittest执行自动化接口测试

    由浅入深----python+requests+unittest执行自动化接口测试 一.安装requests.xlrd.json.unittest库 1.pip 命令安装: 2.pycharm里安装 ...

最新文章

  1. java applet 缺陷_Java Applet在最新JRE上的奇怪性能行为(7.55)
  2. BZOJ4280 : [ONTAK2015]Stumilowy sad
  3. 调用ajax_[WEB篇]-AJAX-02-AJAX应用案例
  4. Spring boot处理附件的一个坑
  5. 学习笔记:Windows 下Keras安装和配置指南
  6. php 数组 定义 遍历,php针对数组的定义、遍历及删除
  7. 基于asp.net + easyui框架,js实现上传图片之前判断图片格式,同时实现预览,兼容各种浏览器+下载...
  8. LED灯随机亮起几个灯
  9. 启用zhparser插件时一直报Permission denied
  10. tl-wn821n无线网卡驱动 linux,tlwn821n 300m无线网卡驱动 官方最新版
  11. [记录]HAproxy负载均衡配置教程
  12. 简单制作登录注册页面
  13. python网易云收费_小白都能学会的Python爬虫网易云音乐
  14. 使用微软官方工具下载最新系统(win10为例)
  15. 微信小程序实现跳转到另外一个小程序的方法
  16. 如何获取QQ邮箱授权码——步骤详解
  17. Python用try-except的时候获取错误行信息和文件信息
  18. 计算机软件投资所得税减免,个人以计算机软件著作权增资可以享受延迟纳个税的优惠吗...
  19. 刘润年度演讲2022:进化的力量(演讲全文)
  20. [转帖]同事推荐的的aira2

热门文章

  1. idea windows快捷键
  2. Re: 征男友征男友(有女友者勿回) (转载)
  3. 我想团:聚划算的反向电子商务实践
  4. ABC243 ABCDE
  5. 鹰潭一中2021高考成绩查询,2021年鹰潭高考状元名单公布,鹰潭高考状元学校资料及最高分...
  6. 2014年网络犯罪与社会安全(中国)论坛
  7. Python_常用模块
  8. bootstrapt 表格自适应_BootStrap table表格插件自适应固定表头(超好用)
  9. First-Blood
  10. 完整教程:spring-boot-starter-data-elasticsearch整合elasticsearch 6.x