unit test 與 AsUnit 3.0 - tutorial (2/3)

In engineering, flash, tutorials   November 15, 2005 - 11:02 am

目前 asUnit的最新版是 asUnit 3.0.1 alpha,據兩位負責人說這是多年以來最大的改版,完全使用 actionscirpt 3 語法,並且忠實的照者 JUnit 去刻出一樣的功能,因此對大部份熟悉 JUnit使用方式的工程師來說,只要記得把 type 改成放後面並加上 : 就可以直接開工了。

下面簡單說明一下 asUnit 3的用法。

假設你有一個叫做 Money的class,它的功能是用來加減運算金額的數目
(note:這個程式是從 as2unit裏面借來的,我將它改寫成AS3 語法並修掉一些錯誤以通過測試)

Actionscript:
  1. package{
  2.    
  3.     class Money {
  4.        
  5.         private var __pounds:Number;
  6.         private var __pence:Number
  7.        
  8.         public function Money( pounds:Number, pence:Number )
  9.         {
  10.             /*
  11.             if ( pounds == undefined || pence == undefined )
  12.                 throw new Error( "Invalid constructor arguments" );
  13.             */
  14.            
  15.             if ( pence> 100 )
  16.             {
  17.                pounds = pounds + Math.floor( pence / 100 );
  18.                 pence = pence % 100;
  19.             }
  20.             //it's using setters here, for updating __pounds indeed.
  21.             this.pounds = pounds;
  22.             this.pence = pence;
  23.         }
  24.    
  25.    
  26.     //------------------------------------------------------------------------------
  27.    
  28.         public function addMoney( money:Money ):Money
  29.         {
  30.             var pounds:Number = this.pounds;
  31.             var pence:Number = this.pence;
  32.    
  33.             pounds = pounds + money.pounds;
  34.             pence = pence + money.pence;
  35.    
  36.             return flatten( pounds, pence );
  37.         }
  38.       }
  39. }

在這個class裏目前只有一個method,叫做 addMoney。

以往我們要測試這個class會不會通過,可能會用類似下面的程式:

Actionscript:
  1. var m:Money = new Money(5,10);
  2. m.addMoney(new Money(2,10));
  3. trace(m)

然後看結果是不是如預期中的金額。

這很明顯的,這樣做非常沒有效率,而且當class結構越長越大時,就很難維護這些test code。

因此比較好的做法是寫一個獨立的 test class,像這樣:

Actionscript:
  1. package{
  2.  
  3.     /*
  4.     這裏是真正的 test class, 測試每一支 method
  5.     */
  6.    
  7.     import flash.util.*;
  8.     import Money;
  9.     import asunit.framework.TestCase;
  10.     import asunit.framework.TestSuite;
  11.    
  12.     public class TestMoney extends TestCase{
  13.        
  14.         private var money:Money;
  15.        
  16.         /**/
  17.         public function TestMoney( ... args:Array )
  18.         {
  19.             trace("abba:"+ args);
  20.             super( args[0] );
  21.         }
  22.        
  23.        
  24.     //------------------------------------------------------------------------------
  25.    
  26.         public function testAddMoney()
  27.         {
  28.             var pounds2:Number = 3;
  29.             var pence2:Number = 20;
  30.            
  31.             money = new Money( 3, 50 );
  32.            
  33.            
  34.             var money2:Money = new Money( pounds2, pence2 );
  35.            
  36.             var money3:Money = money.addMoney( money2 )
  37.             /*
  38.             //assertNotNull( "money was null", money3 );
  39.             //assertNotUndefined( "money was undefined", money3 );
  40.             */
  41.             assertEquals( "Pounds should be 6", 6, money3.pounds );
  42.             assertEquals( "Pence should be 70", 70, money3.pence );
  43.            
  44.         }
  45.      }
  46. }

在這個class裏可以看到許多 assertEquals(), assertNotNull()之類的method, 這些就是 asUnit提供的測試功能,以 testAddMoney()為例,我們用一個新數字加上原本的數字後,透過
assertEquals( "Pounds should be 6", 6, money3.pounds ); 來檢查加總的結果是否為 6,也就是將 money3.pounds 當做參數傳入,然後看看程式跑完後跳出來的數字是否為6,如果兩者相等,那這個測試就通過,如果不是,那就要開始debug囉~

由上面兩個例子可以類推,如果未來 Money class裏又增加了下列功能:

subtractMoney()
greaterThan()
lessThan()
equals()

勢必每個method都可以透過一個 testXXXX()來進行測試,透過這樣系統化的撰寫test code,不但可以確保程式如預期般的運作,更重要的是未來不論要修改,或是人事交替必需由新進工程師接手維護程式碼,都可以透過這組 test code來確保程式功能完整無誤。

asUnit另一個更棒的功能就是 test suite (唸做 sweet),可以將一堆test class集合起來一次執行,請看範例:

Actionscript:
  1. package{
  2.     import asunit.framework.TestSuite;
  3.  
  4.     import TestMoney, TestCar, TestObject;
  5.     import flash.util.*;
  6.    
  7.     /*
  8.     aggregates all test classes here to run at once
  9.     */
  10.     public  class MyTestSuite extends TestSuite{
  11.        
  12.         public function MyTestSuite(){
  13.             addTest(new TestMoney());
  14.                         addTest(new TestCar());
  15.                         addTest(new TestObject());
  16.         }
  17.     }
  18. }

這裏我們建了一個 MyTestSuite,並且將三個要測試的class (別別是 TestMoney, TestCar, TestObject) 都丟進去,將來只要執行這個 MyTestSuite就可以一次測試完三個class裏所有的method。

測試語法如下:

Actionscript:
  1. mt:MyTestSuite = new MyTestSuite();
  2. mt.run();

不過這樣做有個小缺點,就是除非執行過程中有發生錯誤,才會在eclipse的console中顯示錯誤訊息,但如果全部通過的話就完全不會顯示任何資訊。

為此asUnit很貼心的提供了兩種選擇,第一個是用 flex 畫出來的測試介面,使用方法如下:

Actionscript:
  1. package {
  2.     import asunit.textui.TestRunner;
  3.     import TestMoney;
  4.  
  5.     public class AsUnit extends TestRunner {
  6.  
  7.         public function AsUnit() {
  8.             start(MyTestSuite)//this is for multiple test sets
  9.             //start(TestMoney);  //this is for single test set
  10.         }
  11.     }
  12. }

只要把MyTestSuite傳進去,它就會自動執行並開啟一個小swf視窗,最後把結果顯示在裏面,如下圖:

從圖中可以看出只花了0.025秒就完成了12項測試並且全部通過。

另一個方法則是用xul ui。xul是一個可以在 firefox裏執行的 GUI app,使用方式也差不多,只是他得在browser裏面執行,但由於我不需要這種玩意所以抓回來後從來沒執行過。

by admin

留言回應

hidden

您的留言會先經過站長認証後才刊登在網站上。
your comments will be approved by Administrator before appearing on the page.

Trackback this post  |  Subscribe to the comments via RSS Feed

mobile phone