run.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. function run( kiss, runnext ) {
  2. window.document.title = kiss;
  3. var wb = window.brtest = window.brtest || {};
  4. wb.timeout = wb.timeout || 100000;
  5. wb.breakOnError = /breakonerror=true/gi.test( location.search )
  6. || $( 'input#id_control_breakonerror' ).attr( 'checked' );
  7. wb.runnext = /batchrun=true/gi.test( location.search ) || runnext
  8. || $( 'input#id_control_runnext' ).attr( 'checked' );
  9. wb.kiss = kiss;
  10. var cid = 'id_case_' + kiss.split( '.' ).join( '_' );
  11. /* 只有参数有showsrconly的时候才显示div */
  12. if ( /showsrconly=true/gi.test( location.search ) ) {
  13. var div = document.getElementById( 'id_showSrcOnly' );
  14. div.style.display = 'block';
  15. }
  16. /* id中由于嵌入用例名称,可能存在导致通过id直接$无法正确获取元素的情况 */
  17. wb.kissnode = $( document.getElementById( cid ) );
  18. wb.kisses = wb.kisses || {};
  19. // 把没有用例的情况加入到报告中
  20. if ( !wb.kisslost ) {
  21. $( 'div#id_showSrcOnly a' ).each( function () {
  22. wb.kisses[this.title] = '0;0;_;0;0';
  23. } );
  24. wb.kisslost = true;
  25. }
  26. wb.kisscov = wb.kisscov || {};
  27. var wbkiss = wb.kisses[wb.kiss] = wb.kisses[wb.kiss] || '';
  28. /**
  29. * 超时处理
  30. */
  31. var toh = setTimeout( function () {
  32. if ( !window.brtest.breakOnError )
  33. $( wb ).trigger( 'done', [ new Date().getTime(), {
  34. failed:1,
  35. passed:1
  36. }, frames[0].$_jscoverage, 'timeout' ] );
  37. }, wb.timeout );
  38. /**
  39. * 为当前用例绑定一个一次性事件
  40. */
  41. $( wb ).one( 'done', function ( event, time, result, covinfo ) {
  42. clearTimeout( toh );
  43. var wb = window.brtest, errornum = result.failed, allnum = result.failed + result.passed;
  44. wb.kissend = new Date().getTime();
  45. if ( covinfo !== null )// 如果支持覆盖率
  46. {
  47. wb.kisscov[wb.kiss] = covinfo;
  48. }
  49. wb.kissnode.removeClass( 'running_case' );
  50. /*
  51. * ext_qunit.js的_d方法会触发done事件
  52. * top.$(wbkiss).trigger('done', [ new Date().getTime(), args ]); new Date().getTime()指向a参数,args指向b参数
  53. */
  54. wb.kisses[wb.kiss] = errornum + ';' + allnum + ';_;' + wb.kissstart + ';' + wb.kissend;
  55. // var html = '<strong><span style="color: red">'+kiss + '</span></strong>:失败/所有:<strong><span style="color: red">'+errornum + '</span></strong>/' + allnum + ',开始:' + wb.kissstart + ',结束:' + wb.kissend +'耗时:'+(wb.kissend-wb.kissstart) +'\n';
  56. var args = kiss + ': 失败/所有:' + errornum + '/' + allnum + ',耗时:' + (wb.kissend - wb.kissstart);
  57. var html = upath + '../br/log.php?loginfo=' + args;
  58. html += '&detail='+result.detail;
  59. if ( errornum > 0 )
  60. html += '&fail=true';
  61. if ( errornum > 0 ) {
  62. wb.kissnode.addClass( 'fail_case' );
  63. // wb.kisses[kiss + '_error'] =
  64. // window.frames[0].innerHTML;
  65. } else
  66. wb.kissnode.addClass( 'pass_case' );
  67. if ( wb.runnext && (!wb.breakOnError || parseInt( wb.kisses[wb.kiss].split( ',' )[0] ) == 0) ) {
  68. var nextA = wb.kissnode.next()[0];
  69. if ( nextA.tagName == 'A' ) {
  70. if ( wb.kisses[nextA.title] === undefined ) {
  71. run( nextA.title, wb.runnext );
  72. }
  73. html += "&next=" + nextA.title;
  74. } else {
  75. /* 隐藏执行区 */
  76. // $('div#id_runningarea').toggle();
  77. /* ending 提交数据到后台 */
  78. html += '&next=@_@end';
  79. wb.kisses['config'] = location.search.substring( 1 );
  80. // var url = /mail=true/.test( location.search ) ? 'record.php' : 'report.php';
  81. var url = 'report.php';
  82. covcalc();
  83. /**
  84. * 启动时间,结束时间,校验点失败数,校验点总数
  85. */
  86. $.ajax( {
  87. url:url,
  88. type:'post',
  89. data:wb.kisses,
  90. success:function ( msg ) {
  91. // $('#id_testlist').hide();
  92. /* 展示报告区 */
  93. $( '#id_reportarea' ).show().html( msg );
  94. },
  95. error:function ( xhr, msg ) {
  96. alert( 'fail' + msg );
  97. }
  98. } );
  99. }
  100. }
  101. te.log( html );
  102. } );
  103. /**
  104. * 初始化执行区并通过嵌入iframe启动用例执行
  105. */
  106. var url = 'run.php?case=' + kiss + '&time=' + new Date().getTime() + "&"
  107. + location.search.substring( 1 );
  108. // + (location.search.length > 0 ? '&' + location.search.substring(1)
  109. // : '');
  110. var fdiv = 'id_div_frame_' + kiss.split( '.' ).join( '_' );
  111. var fid = 'id_frame_' + kiss.split( '.' ).join( '_' );
  112. wb.kissnode.addClass( 'running_case' );
  113. if ( $( 'input#id_control_hidelist' ).attr( 'checked' ) )
  114. $( 'div#id_testlist' ).css( 'display', 'none' );
  115. /* 隐藏报告区 */
  116. $( 'div#id_reportarea' ).empty().hide();
  117. /* 展示执行区 */
  118. // if(ua.browser.ie){//释放iframe里面占用的内存
  119. // if($( 'div#id_runningarea' )[0].getElementsByTagName('iframe').length){
  120. // var iframe_old = $( 'div#id_runningarea' )[0].getElementsByTagName('iframe')[0];
  121. // iframe_old.src = "javascript:false";
  122. // iframe_old.contentWindow.document.write('');
  123. // iframe_old.contentWindow.close();
  124. // CollectGarbage();
  125. // iframe_old.parentNode.removeChild(iframe_old);
  126. // }
  127. //
  128. // }
  129. var iframe =document.createElement('iframe');
  130. iframe.src= url;
  131. iframe.id= fid;
  132. iframe.className= "runningframe";
  133. $( 'div#id_runningarea' ).empty().css( 'display', 'block' ).append( iframe);
  134. wb.kissstart = new Date().getTime();
  135. };
  136. function match(fileName, matcher )
  137. {
  138. if ( matcher == '*' )
  139. return true;
  140. var len = matcher.length;
  141. /**
  142. * 处理多选分支,有一个成功则成功,filter后面参数使用|切割
  143. * @var unknown_type
  144. */
  145. var ms = matcher.split( ',');
  146. if ( ms.length > 1 ) {
  147. //这里把或的逻辑改成与
  148. for ( var matcher1 in ms ) {
  149. if ( !match(fileName, ms[matcher1] ) )
  150. return false;
  151. }
  152. return true;
  153. }
  154. /**
  155. * 处理反向选择分支
  156. */
  157. if ( matcher.substr( 0 , 1 ) == '!' ) {
  158. var m = matcher.substr( 1 );
  159. if ( fileName.substr( 0 , m.length ) == m )
  160. return false;
  161. return true;
  162. }
  163. if ( len > fileName.length ) {
  164. return false;
  165. }
  166. return fileName.substr( 0 , len ) == matcher;
  167. }
  168. // 需要根据一次批量执行整合所有文件的覆盖率情况
  169. function covcalc() {
  170. function covmerge( cc, covinfo ) {
  171. for ( var key in covinfo ) {//key :每个文件
  172. for ( var idx in covinfo[key] ) {
  173. if ( idx != 'source' ) {
  174. cc[key] = cc[key] || [];
  175. cc[key][idx] = (cc[key][idx] || 0) + covinfo[key][idx];
  176. }
  177. }
  178. }
  179. return cc;
  180. }
  181. var cc = {};
  182. var brkisses = window.brtest.kisses;
  183. for ( var key in window.brtest.kisscov ){
  184. covmerge( cc, window.brtest.kisscov[key] );//key:每个用例
  185. // brkisses[kiss]= brkisses[kiss] + ',' + key;
  186. }
  187. var file;
  188. var files = [];
  189. var filter = '';
  190. var ls = location.search.split('&');
  191. for( var i = 0; i < ls.length; i++){
  192. if(ls[i].indexOf('filter')!=-1&&ls[i].indexOf('filterRun')==-1){
  193. filter = ls[i].split('=')[1];
  194. }
  195. }
  196. for ( file in cc ) {
  197. if ( !cc.hasOwnProperty( file ) ) {
  198. continue;
  199. }
  200. if(match(file,filter))
  201. files.push( file );
  202. }
  203. files.sort();
  204. for ( var f = 0; f < files.length; f++ ) {
  205. file = files[f];
  206. var lineNumber;
  207. var num_statements = 0;
  208. var num_executed = 0;
  209. var missing = [];
  210. var fileCC = cc[file];
  211. var length = fileCC.length;
  212. var currentConditionalEnd = 0;
  213. var conditionals = null;
  214. if ( fileCC.conditionals ) {
  215. conditionals = fileCC.conditionals;
  216. }
  217. var recordCovForBrowser = null;//
  218. for ( lineNumber = 0; lineNumber < length; lineNumber++ ) {
  219. var n = fileCC[lineNumber];
  220. if ( lineNumber === currentConditionalEnd ) {
  221. currentConditionalEnd = 0;
  222. } else if ( currentConditionalEnd === 0 && conditionals
  223. && conditionals[lineNumber] ) {
  224. currentConditionalEnd = conditionals[lineNumber];
  225. }
  226. if ( currentConditionalEnd !== 0 ) {
  227. (recordCovForBrowser==null)?(recordCovForBrowser='2'):(recordCovForBrowser +=',2');
  228. continue;
  229. }
  230. if ( n === undefined || n === null ) {
  231. (recordCovForBrowser==null)?(recordCovForBrowser='2'):(recordCovForBrowser +=',2');
  232. continue;
  233. }
  234. if ( n === 0 ) {
  235. (recordCovForBrowser==null)?(recordCovForBrowser='0'):(recordCovForBrowser +=',0');
  236. missing.push( lineNumber );
  237. } else {
  238. (recordCovForBrowser==null)?(recordCovForBrowser='1'):(recordCovForBrowser +=',1');
  239. num_executed++;
  240. }
  241. num_statements++;
  242. }
  243. var percentage = (num_statements === 0 ? 0 : ( 100* num_executed / num_statements ).toFixed(1));
  244. var kiss = file.replace( '.js', '' );
  245. // 统计所有用例的覆盖率信息和测试结果
  246. if ( brkisses[kiss] == undefined )
  247. brkisses[kiss] = '0;0;_;0;0';
  248. var info = brkisses[kiss].split( ';_;' );// 覆盖率的处理在最后环节加入到用例的测试结果中
  249. brkisses[kiss] = info[0] + ';' + percentage + ';' + info[1]+';'+recordCovForBrowser;
  250. }
  251. }
  252. /**
  253. * 为批量运行提供入口,参数携带batchrun=true
  254. */
  255. $( document ).ready(
  256. function () {
  257. if ( location.href.search( "[?&,]batchrun=true" ) > 0
  258. || $( 'input#id_control_runnext' ).attr( 'checked' ) ) {
  259. run( $( 'div#id_testlist a' ).attr( 'title' ), true );
  260. }
  261. } );