<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      JavaScript單元測試ABC

      前言

        當前,在軟件開發中單元測試越來越受到開發者的重視,它能提高軟件的開發效率,而且能保障開發的質量。以往,單元測試往往多見于服務端的開發中,但隨著Web編程領域的分工逐漸明細,在前端Javascript開發領域中,也可以進行相關的單元測試,以保障前端開發的質量。

        在服務器端的單元測試中,都有各種各樣的測試框架,在JavaScript中現在也有一些很優秀的框架,但在本文中,我們將自己動手一步步來實現一個簡單的單元測試框架。

        JS單元測試有很多方面,比較多的是對方法功能檢查,對瀏覽器兼容性檢查,本文主要談第一種。

        本文檢查的JS代碼是我以前寫的一個JS日期格式化的方法,原文在這里(javascript日期格式化函數,跟C#中的使用方法類似),代碼如下:

      Date.prototype.toString=function(format){
          var time={};
          time.Year=this.getFullYear();
          time.TYear=(""+time.Year).substr(2);
          time.Month=this.getMonth()+1;
          time.TMonth=time.Month<10?"0"+time.Month:time.Month;
          time.Day=this.getDate();
          time.TDay=time.Day<10?"0"+time.Day:time.Day;
          time.Hour=this.getHours();
          time.THour=time.Hour<10?"0"+time.Hour:time.Hour;
          time.hour=time.Hour<13?time.Hour:time.Hour-12;
          time.Thour=time.hour<10?"0"+time.hour:time.hour;
          time.Minute=this.getMinutes();
          time.TMinute=time.Minute<10?"0"+time.Minute:time.Minute;
          time.Second=this.getSeconds();
          time.TSecond=time.Second<10?"0"+time.Second:time.Second;
          time.Millisecond=this.getMilliseconds();
      
          var oNumber=time.Millisecond/1000;
      
          if(format!=undefined && format.replace(/\s/g,"").length>0){
              format=format
                  .replace(/yyyy/ig,time.Year)
                  .replace(/yyy/ig,time.Year)
                  .replace(/yy/ig,time.TYear)
                  .replace(/y/ig,time.TYear)
                  .replace(/MM/g,time.TMonth)
                  .replace(/M/g,time.Month)
                  .replace(/dd/ig,time.TDay)
                  .replace(/d/ig,time.Day)
                  .replace(/HH/g,time.THour)
                  .replace(/H/g,time.Hour)
                  .replace(/hh/g,time.Thour)
                  .replace(/h/g,time.hour)
                  .replace(/mm/g,time.TMinute)
                  .replace(/m/g,time.Minute)
                  .replace(/ss/ig,time.TSecond)
                  .replace(/s/ig,time.Second)
                  .replace(/fff/ig,time.Millisecond)
                  .replace(/ff/ig,oNumber.toFixed(2)*100)
                  .replace(/f/ig,oNumber.toFixed(1)*10);
          }
          else{
              format=time.Year+"-"+time.Month+"-"+time.Day+" "+time.Hour+":"+time.Minute+":"+time.Second;
          }
          return format;
      }

        這段代碼目前沒有發現比較嚴重的bug,本文為了測試,我們把 .replace(/MM/g,time.TMonth) 改為 .replace(/MM/g,time.Month),這個錯誤是當月份小于10時,沒有用兩位數表示月份。

        現在有這么一句話,好的設計都是重構出來的,在本文中也一樣,我們從最簡單的開始。

      第一版:用最原始的alert

        作為第一版,我們很偷懶的直接用alert來檢查,完整代碼如下:

      <!DOCTYPE html>
      <html>
      <head>
          <title>Demo</title>
          <meta charset="utf-8"/>
      </head>
      <body>
          <script type="text/javascript">
              Date.prototype.toString=function(format){
                  var time={};
                  time.Year=this.getFullYear();
                  time.TYear=(""+time.Year).substr(2);
                  time.Month=this.getMonth()+1;
                  time.TMonth=time.Month<10?"0"+time.Month:time.Month;
                  time.Day=this.getDate();
                  time.TDay=time.Day<10?"0"+time.Day:time.Day;
                  time.Hour=this.getHours();
                  time.THour=time.Hour<10?"0"+time.Hour:time.Hour;
                  time.hour=time.Hour<13?time.Hour:time.Hour-12;
                  time.Thour=time.hour<10?"0"+time.hour:time.hour;
                  time.Minute=this.getMinutes();
                  time.TMinute=time.Minute<10?"0"+time.Minute:time.Minute;
                  time.Second=this.getSeconds();
                  time.TSecond=time.Second<10?"0"+time.Second:time.Second;
                  time.Millisecond=this.getMilliseconds();
      
                  var oNumber=time.Millisecond/1000;
      
                  if(format!=undefined && format.replace(/\s/g,"").length>0){
                      format=format
                          .replace(/yyyy/ig,time.Year)
                          .replace(/yyy/ig,time.Year)
                          .replace(/yy/ig,time.TYear)
                          .replace(/y/ig,time.TYear)
                          .replace(/MM/g,time.Month)
                          .replace(/M/g,time.Month)
                          .replace(/dd/ig,time.TDay)
                          .replace(/d/ig,time.Day)
                          .replace(/HH/g,time.THour)
                          .replace(/H/g,time.Hour)
                          .replace(/hh/g,time.Thour)
                          .replace(/h/g,time.hour)
                          .replace(/mm/g,time.TMinute)
                          .replace(/m/g,time.Minute)
                          .replace(/ss/ig,time.TSecond)
                          .replace(/s/ig,time.Second)
                          .replace(/fff/ig,time.Millisecond)
                          .replace(/ff/ig,oNumber.toFixed(2)*100)
                          .replace(/f/ig,oNumber.toFixed(1)*10);
                  }
                  else{
                      format=time.Year+"-"+time.Month+"-"+time.Day+" "+time.Hour+":"+time.Minute+":"+time.Second;
                  }
                  return format;
              }
      
              var date=new Date(2012,3,9);
              alert(date.toString("yyyy"));
              alert(date.toString("MM"));
          </script>
      </body>
      </html>

        運行后會彈出 2012 和 4 ,觀察結果我們知道 date.toString("MM")方法是有問題的。

        這種方式很不方便,最大的問題是它只彈出了結果,并沒有給出正確或錯誤的信息,除非對代碼非常熟悉,否則很難知道彈出的結果是正是誤,下面,我們寫一個斷言(assert)方法來進行測試,明確給出是正是誤的信息。

      第二版:用assert進行檢查

        斷言是表達程序設計人員對于系統應該達到狀態的一種預期,比如有一個方法用于把兩個數字加起來,對于3+2,我們預期這個方法返回的結果是5,如果確實返回5那么就通過,否則給出錯誤提示。

        斷言是單元測試的核心,在各種單元測試的框架中都提供了斷言功能,這里我們寫一個簡單的斷言(assert)方法:

      function assert(message,result){
          if(!result){
              throw new Error(message);
          }
          return true;
      }

        這個方法接受兩個參數,第一個是錯誤后的提示信息,第二個是斷言結果

        用斷言測試代碼如下:

      var date=new Date(2012,3,9);
      try{
          assert("yyyy should return full year",date.toString("yyyy")==="2012");
      }catch(e){
          alert("Test failed:"+e.message);
      }
      
      try{
          assert("MM should return full month",date.toString("MM")==="04");
      }
      catch(e){
          alert("Test failed:"+e.message);
      }

        運行后會彈出如下窗口:

      第三版:進行批量測試

        在第二版中,assert方法可以給出明確的結果,但如果想進行一系列的測試,每個測試都要進行異常捕獲,還是不夠方便。另外,在一般的測試框架中都可以給出成功的個數,失敗的個數,及失敗的錯誤信息。

        為了可以方便在看到測試結果,這里我們把結果用有顏色的文字顯示的頁面上,所以這里要寫一個小的輸出方法PrintMessage:

      function PrintMessage(text,color){
          var div=document.createElement("div");
          div.innerHTML=text;
          div.style.color=color;
          document.body.appendChild(div);
          delete div;
      }

        下面,我們就寫一個類似jsTestDriver中的TestCase方法,來進行批量測試:

      function testCase(name,tests){
          var successCount=0;
          var testCount=0;
          for(var test in tests){
              testCount++;
              try{
                  tests[test]();
                  PrintMessage(test+" success","#080");
                  successCount++;
              }
              catch(e){
                  PrintMessage(test+" failed:"+e.message,"#800");
              }
          }
          PrintMessage("Test result: "+testCount+" tests,"+successCount+" success, "+ (testCount-successCount)+" failures","#800");
      }

        測試代碼:

      var date=new Date(2012,3,9);
      testCase("date toString test",{
          yyyy:function(){
              assert("yyyy should return 2012",date.toString("yyyy")==="2012");
          },
          MM:function(){
              assert("MM should return 04",date.toString("MM")==="04");
          },
          dd:function(){
              assert("dd should return 09",date.toString("dd")==="09");
          }
      });

        結果為:

        這樣我們一眼就可以看出哪個出錯了。但這樣是否就完美了呢,我們可以看到最后那個測試中 var date=new Date(2012,3,9)是放在testCase外面定義的,并且整個testCase的測試代碼中共用了date,這里因為各個方法中沒有對date的值進行修改,所以沒出問題,如果某個測試方法中對date的值修改了呢,測試的結果就是不準確的,所以在很多測試框架中都提供了setUp和tearDown方法,用來對統一提供和銷毀測試數據,下面我們就在我們的testCase中加上setUp和tearDown方法。

      第四版:統一提供測試數據的批量測試

        首先我們添加setUp和tearDown方法:

      testCase("date toString",{
          setUp:function(){
              this.date=new Date(2012,3,9);
          },
          tearDown:function(){
              delete this.date;
          },
          yyyy:function(){
              assert("yyyy should return 2012",this.date.toString("yyyy")==="2012");
          },
          MM:function(){
              assert("MM should return 04",this.date.toString("MM")==="04");
          },
          dd:function(){
              assert("dd should return 09",this.date.toString("dd")==="09");
          }
      });

        由于setUp和tearDown方法不參與測試,所以我們要修改testCase代碼:

      function testCase(name,tests){
          var successCount=0;
          var testCount=0;
          var hasSetUp=typeof tests.setUp == "function";
          var hasTearDown=typeof tests.tearDown == "function";
          for(var test in tests){
              if(test==="setUp"||test==="tearDown"){
                  continue;
              }
              testCount++;
              try{
                  if(hasSetUp){
                      tests.setUp();
                  }
                  tests[test]();
                  PrintMessage(test+" success","#080");
      
                  if(hasTearDown){
                      tests.tearDown();
                  }
      
                  successCount++;
              }
              catch(e){
                  PrintMessage(test+" failed:"+e.message,"#800");
              }
          }
          PrintMessage("Test result: "+testCount+" tests,"+successCount+" success, "+ (testCount-successCount)+" failures","#800");
      }

        運行后的結果跟第三版相同。

      小結及參考文章

        上面說了,好的設計是不斷重構的結果,上面的第四版是不是就完美了呢,遠遠沒有達到,這里只是一個示例。如果大家需要這方面的知識,我后面可以再寫寫各個測試框架的使用。

        本文只是JS單元測試入門級的示例,讓初學者對JS的單元測試有個初步概念,屬于拋磚引玉,歡迎各位高人拍磚補充。

        本文參考了《測試驅動的JavaScript開發》(個人覺得還不錯,推薦下)一書第一章,書中的測試用例也是一個時間函數,不過寫的比較復雜,初學者不太容易看懂。

      posted @ 2012-04-09 15:41  artwl  閱讀(1591)  評論(4)    收藏  舉報

      個人簡介

      var ME = {
      	"name": "土豆/Artwl",
      	"job": "coding",
      	"languages": [
      		"JS", "HTML",
                      "CSS", "jQuery"
      		"MVC",".NET",
      		"設計模式"
      	],
      	"hobby": [
      		"閱讀", "旅游",
      		"音樂", "電影"
      	]
      }
      
      TOP
      主站蜘蛛池模板: 久热伊人精品国产中文| 九九久久精品国产| 国产一区二区三区精品综合| 久久日产一线二线三线| 欧美人与禽2o2o性论交| 免费人成网站免费看视频| 伊人精品成人久久综合97| 亚洲欧美日韩久久一区二区 | 日本欧美大码aⅴ在线播放| 国产av无码专区亚洲aⅴ| 平昌县| 国产啪视频免费观看视频| 亚洲综合伊人久久大杳蕉| 激情综合色五月六月婷婷| 色猫咪av在线观看| 制服丝袜人妻有码无码中文字幕 | 国产精品国三级国产av| 久久九九久精品国产免费直播| 中国少妇嫖妓BBWBBW| 国内自拍小视频在线看| 少妇高潮水多太爽了动态图| 亚洲中文字幕一二区日韩| 国产精品一区二区日韩精品 | 中文字幕av日韩有码| 99久久国产综合精品女图图等你| 建始县| av色国产色拍| 国产精品日韩中文字幕熟女 | 真实单亲乱l仑对白视频| 国产对白老熟女正在播放| 99久久亚洲综合精品成人网| 欧美一本大道香蕉综合视频| 中文字幕日韩有码国产| 亚洲国产精品综合久久2007 | 亚洲综合日韩av在线| 日韩激情一区二区三区| 亚洲精品成人久久久| 九九热爱视频精品视频| 又大又黄又粗高潮免费| 少妇爽到呻吟的视频| 久久精品国产亚洲AV麻豆长发|