Selenium3+python自动化011-unittest生成测试报告(HTMLTestRunner)
批量执行完用例后,生成的测试报告是文本形式的,不够直观,为了更好的展示测试报告,最好是生成HTML格式的。
unittest里面是不能生成html格式报告的,需要导入一个第三方的模块:HTMLTestRunner
一、导入HTMLTestRunner
1.这个模块下载不能通过pip安装了,只能下载后手动导入,下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html
2.Download下HTMLTestRunner.py文件就是我们需要下载的包。
3.下载后手动拖到python安装文件的Lib目录下
4.验证安装成功 执行 import HTMLTestRunner 没有报错证明配置成功。
报告路径
1 # encoding = utf - 8 2 import unittest 3 import sys 4 import HTMLTestRunner 5 import time 6 import os 7 8 #被测试类 9 class myclass(object): 10 """classmethod 修饰符对应的函数不需要实例化, 11 不需要 self 参数,但第一个参数需要是表示自身 12 类的 cls 参数,可以来调用类的属性,类的方法, 13 实例化对象等。""" 14 @classmethod 15 def sum(cls,a,b): 16 return a + b #将两个传入参数进行相加操作 17 @classmethod 18 def sub(cls, a, b): 19 return a - b #将两个传入参数进行相减操作 20 21 class mytest(unittest.TestCase): 22 # @classmethod 23 # def setUpClass(cls): 24 # """初始化类固件""" 25 # print("-----setUpClass") 26 27 # @classmethod 28 # def tearDownClass(cls): 29 # """重构类固件""" 30 # print("--tearDownClas") 31 32 #初始化工作 33 def setUp(self): 34 self.a = 3 35 self.b = 1 36 print("--setUp") 37 38 #退出清理工作 39 def tearDown(self): 40 print("--tearDown") 41 42 #具体的测试用例,一定要以test开头 43 def test1sum(self): 44 # res=3/0 抛出异常,执行结果为F 45 #断言两数之和的结果是否是4 46 res=myclass.sum(self.a,self.b) 47 self.assertEqual(res,4,'test sum fail') 48 print('testsum方法') 49 50 def testsub(self): 51 #断言两数之差的结果是否是2 52 self.assertEqual(myclass.sub(self.a,self.b),2,'test sub fail') 53 print('testsub方法') 54 55 56 class aa(unittest.TestCase): 57 # num=2 58 # @unittest.skip('skipping') 59 # @unittest.skipIf(num>1,'num已经大于1') 60 @unittest.skipUnless(sys.platform == "linux", "requires linux") 61 def testaa(self): 62 print('testaa') 63 64 65 if __name__ == '__main__': 66 testCase = unittest.TestLoader().loadTestsFromTestCase(mytest) 67 #将多个测试类加载到测试集合中 68 suite = unittest.TestSuite([testCase]) 69 # 创建时间 70 cur_time = time.strftime('%Y-%m-%d_%H_%M_%S') 71 # 文件路径 72 filename = os.path.dirname(os.path.abspath('.'))+'\\report\\'+cur_time+'.html' 73 print("===================================") 74 print("当前文件路径是:",os.path.abspath('.')) 75 print("===================================") 76 print("当前文件路径的上一级文件路径是:",os.path.dirname(os.path.abspath('.'))) 77 # 写入一个文件 78 f = open(filename,"wb") 79 # 报告详情 80 runner = HTMLTestRunner.HTMLTestRunner(stream=f,title="测试报告",description='测试报告描述') 81 runner.run(suite) 82 83 # 原始版本 84 # f = open("./report.html","wb") 85 # runner = HTMLTestRunner.HTMLTestRunner(stream=f,title="测试报告",description="测试报告描述") 86 # runner.run(suite)
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 3 <html xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <title>测试报告</title> 6 <meta name="generator" content="HTMLTestRunner 0.8.2"/> 7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> 8 9 <style type="text/css" media="screen"> 10 body { font-family: verdana, arial, helvetica, sans-serif; font-size: 80%; } 11 table { font-size: 100%; } 12 pre { } 13 14 /* -- heading ---------------------------------------------------------------------- */ 15 h1 { 16 font-size: 16pt; 17 color: gray; 18 } 19 .heading { 20 margin-top: 0ex; 21 margin-bottom: 1ex; 22 } 23 24 .heading .attribute { 25 margin-top: 1ex; 26 margin-bottom: 0; 27 } 28 29 .heading .description { 30 margin-top: 4ex; 31 margin-bottom: 6ex; 32 } 33 34 /* -- css div popup ------------------------------------------------------------------------ */ 35 a.popup_link { 36 } 37 38 a.popup_link:hover { 39 color: red; 40 } 41 42 .popup_window { 43 display: none; 44 position: relative; 45 left: 0px; 46 top: 0px; 47 /*border: solid #627173 1px; */ 48 padding: 10px; 49 background-color: #E6E6D6; 50 font-family: "Lucida Console", "Courier New", Courier, monospace; 51 text-align: left; 52 font-size: 8pt; 53 width: 500px; 54 } 55 56 } 57 /* -- report ------------------------------------------------------------------------ */ 58 #show_detail_line { 59 margin-top: 3ex; 60 margin-bottom: 1ex; 61 } 62 #result_table { 63 width: 80%; 64 border-collapse: collapse; 65 border: 1px solid #777; 66 } 67 #header_row { 68 font-weight: bold; 69 color: white; 70 background-color: #777; 71 } 72 #result_table td { 73 border: 1px solid #777; 74 padding: 2px; 75 } 76 #total_row { font-weight: bold; } 77 .passClass { background-color: #6c6; } 78 .failClass { background-color: #c60; } 79 .errorClass { background-color: #c00; } 80 .passCase { color: #6c6; } 81 .failCase { color: #c60; font-weight: bold; } 82 .errorCase { color: #c00; font-weight: bold; } 83 .hiddenRow { display: none; } 84 .testcase { margin-left: 2em; } 85 86 87 /* -- ending ---------------------------------------------------------------------- */ 88 #ending { 89 } 90 91 </style> 92 93 </head> 94 <body> 95 <script language="javascript" type="text/javascript"><!-- 96 output_list = Array(); 97 98 /* level - 0:Summary; 1:Failed; 2:All */ 99 function showCase(level) { 100 trs = document.getElementsByTagName("tr"); 101 for (var i = 0; i < trs.length; i++) { 102 tr = trs[i]; 103 id = tr.id; 104 if (id.substr(0,2) == 'ft') { 105 if (level < 1) { 106 tr.className = 'hiddenRow'; 107 } 108 else { 109 tr.className = ''; 110 } 111 } 112 if (id.substr(0,2) == 'pt') { 113 if (level > 1) { 114 tr.className = ''; 115 } 116 else { 117 tr.className = 'hiddenRow'; 118 } 119 } 120 } 121 } 122 123 124 function showClassDetail(cid, count) { 125 var id_list = Array(count); 126 var toHide = 1; 127 for (var i = 0; i < count; i++) { 128 tid0 = 't' + cid.substr(1) + '.' + (i+1); 129 tid = 'f' + tid0; 130 tr = document.getElementById(tid); 131 if (!tr) { 132 tid = 'p' + tid0; 133 tr = document.getElementById(tid); 134 } 135 id_list[i] = tid; 136 if (tr.className) { 137 toHide = 0; 138 } 139 } 140 for (var i = 0; i < count; i++) { 141 tid = id_list[i]; 142 if (toHide) { 143 document.getElementById('div_'+tid).style.display = 'none' 144 document.getElementById(tid).className = 'hiddenRow'; 145 } 146 else { 147 document.getElementById(tid).className = ''; 148 } 149 } 150 } 151 152 153 function showTestDetail(div_id){ 154 var details_div = document.getElementById(div_id) 155 var displayState = details_div.style.display 156 // alert(displayState) 157 if (displayState != 'block' ) { 158 displayState = 'block' 159 details_div.style.display = 'block' 160 } 161 else { 162 details_div.style.display = 'none' 163 } 164 } 165 166 167 function html_escape(s) { 168 s = s.replace(/&/g,'&'); 169 s = s.replace(/</g,'<'); 170 s = s.replace(/>/g,'>'); 171 return s; 172 } 173 174 /* obsoleted by detail in <div> 175 function showOutput(id, name) { 176 var w = window.open("", //url 177 name, 178 "resizable,scrollbars,status,width=800,height=450"); 179 d = w.document; 180 d.write("<pre>"); 181 d.write(html_escape(output_list[id])); 182 d.write("\n"); 183 d.write("<a href='javascript:window.close()'>close</a>\n"); 184 d.write("</pre>\n"); 185 d.close(); 186 } 187 */ 188 --></script> 189 190 <div class='heading'> 191 <h1>测试报告</h1> 192 <p class='attribute'><strong>Start Time:</strong> 2019-07-01 23:11:41</p> 193 <p class='attribute'><strong>Duration:</strong> 0:00:00.001000</p> 194 <p class='attribute'><strong>Status:</strong> Pass 2</p> 195 196 <p class='description'>测试报告描述</p> 197 </div> 198 199 200 201 <p id='show_detail_line'>Show 202 <a href='javascript:showCase(0)'>Summary</a> 203 <a href='javascript:showCase(1)'>Failed</a> 204 <a href='javascript:showCase(2)'>All</a> 205 </p> 206 <table id='result_table'> 207 <colgroup> 208 <col align='left' /> 209 <col align='right' /> 210 <col align='right' /> 211 <col align='right' /> 212 <col align='right' /> 213 <col align='right' /> 214 </colgroup> 215 <tr id='header_row'> 216 <td>Test Group/Test case</td> 217 <td>Count</td> 218 <td>Pass</td> 219 <td>Fail</td> 220 <td>Error</td> 221 <td>View</td> 222 </tr> 223 224 <tr class='passClass'> 225 <td>mytest</td> 226 <td>2</td> 227 <td>2</td> 228 <td>0</td> 229 <td>0</td> 230 <td><a href="javascript:showClassDetail('c1',2)">Detail</a></td> 231 </tr> 232 233 <tr id='pt1.1' class='hiddenRow'> 234 <td class='none'><div class='testcase'>test1sum</div></td> 235 <td colspan='5' align='center'> 236 237 <!--css div popup start--> 238 <a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_pt1.1')" > 239 pass</a> 240 241 <div id='div_pt1.1' class="popup_window"> 242 <div style='text-align: right; color:red;cursor:pointer'> 243 <a onfocus='this.blur();' onclick="document.getElementById('div_pt1.1').style.display = 'none' " > 244 [x]</a> 245 </div> 246 <pre> 247 248 pt1.1: 249 250 </pre> 251 </div> 252 <!--css div popup end--> 253 254 </td> 255 </tr> 256 257 <tr id='pt1.2' class='hiddenRow'> 258 <td class='none'><div class='testcase'>testsub</div></td> 259 <td colspan='5' align='center'> 260 261 <!--css div popup start--> 262 <a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_pt1.2')" > 263 pass</a> 264 265 <div id='div_pt1.2' class="popup_window"> 266 <div style='text-align: right; color:red;cursor:pointer'> 267 <a onfocus='this.blur();' onclick="document.getElementById('div_pt1.2').style.display = 'none' " > 268 [x]</a> 269 </div> 270 <pre> 271 272 pt1.2: 273 274 </pre> 275 </div> 276 <!--css div popup end--> 277 278 </td> 279 </tr> 280 281 <tr id='total_row'> 282 <td>Total</td> 283 <td>2</td> 284 <td>2</td> 285 <td>0</td> 286 <td>0</td> 287 <td> </td> 288 </tr> 289 </table> 290 291 <div id='ending'> </div> 292 293 </body> 294 </html>