所以我仿照 flex unit 作了一個自己的測試類別 BasicUnitTestCase
只要繼承這個類別
就可以仿照 flex unit 4 的方式來建構 test case
並且簡單的測試!
不需要使用 premium 版本的 IDE
也不需要特定的 IDE 等等的部分!
當然也有一些別人寫好的這種類別
例如 asUnit, asUnit Git URL
因為某些原因所以 asunit 對我來說不是很適用,
所以才產出了這個類別 !
來講一下我寫這個 測試類別的基本需求
1. 可以直接和 flex unit 交互使用(test case, Assert ).
2. 提供簡易報表 和 詳細報表
3. 簡單的使用和測試.
因為需求 1,
所以有了 metadata 的分析
和 flex unit 一樣直接取 Test tag 的 test case
也和 flex unit 一樣的基本斷言函式 assertEquals
為了測試正確 所以暫時不使用 flex unit 的 Before 和 After 這兩個 metadata,
強迫使用者複寫 startUp 和 shutdown 這兩個函數
確保一定會做到這兩個動作!
因為需求 2.
整個測試完畢會使用 showLog 將基本的報告印出.
也可以使用 Detail 來取的比較完整的報告
最後需求3.
只需要 BasicUnitTestCase 就可以進行測試,
雖然目前功能還是相對簡單!
所以對目前的幾個 IDE 介面都可以使用.
綜合以上 有了下面的類別
package com.tenchiwang.unitTest
{
import flash.events.ErrorEvent;
import flash.utils.describeType;
public class BasicUnitTestCase
{
private var _testCaseList:Vector.<TestCaseVo>;
private var _detail:String = '';
private var _ErrorCount:int;
private var _PassCount :int;
private var _isPass:Boolean = false;
private var _callback:Function;
// 基本的測試類別!
public function BasicUnitTestCase(callBack:Function = null)
{
_callback = callBack;
_testCaseList = new Vector.<TestCaseVo>();
saveDetail('Analyze Unit Test....');
var accessorsList:XMLList = describeType(this).method;
var fun:Function;
var vo:TestCaseVo;
var acces:XML;
var metadataName:String;
for(var i:int = 0;i<accessorsList.length();i++)
{
acces = accessorsList[i];
metadataName = acces.metadata[0].@name;
metadataName = metadataName.toLocaleLowerCase();
switch(metadataName)
{
case 'test':
fun = this[acces['@name']] as Function;
if(fun != null)
{
vo = new TestCaseVo();
vo.name = acces['@name'];
vo.fun = fun;
_testCaseList.push(vo);
}
break;
default:
}
}
saveDetail('Analyze Unit Test End. Get ' + _testCaseList.length + ' tests');
//
runTest();
//
if(_callback != null)
_callback.apply();
}
final public function assertEquals(a:*, b:*):void
{
if( a === b)
{
_PassCount++;
_isPass = true;
}
}
private function runTest():void
{
showLog('Unit Test Start.');
saveDetail('Unit Test Start ....');
saveDetail('=======================');
var len:int = _testCaseList.length;
var vo:TestCaseVo;
for(var i:int = 0; i < len ;i++)
{
vo = _testCaseList[i];
saveDetail( vo.name + ' Start.' );
_isPass = false;
startUp();
try
{
vo.fun.call();
}
catch(error:Error)
{
showLog('Test Case ' + vo.name + ' Error.');
saveDetail('Test Case ' + vo.name + ' Error.');
_ErrorCount++;
}
catch(evt:ErrorEvent)
{
showLog('Test Case ' + vo.name + ' Error.');
saveDetail('Test Case ' + vo.name + ' Error.');
_ErrorCount++;
}
shutdown();
saveDetail(vo.name + ' End. ' );
}
showLog('Unit Test End.');
showLog('Test Case ' + len);
showLog('Pass Case ' + _PassCount );
showLog('Error Case ' + _ErrorCount);
//
saveDetail('=======================');
saveDetail('Unit Test End.');
saveDetail('Test Case ' + len);
saveDetail('Pass Case ' + _PassCount );
saveDetail('Error Case ' + _ErrorCount);
}
private function saveDetail(msg:String):void
{
_detail += getDate() + msg + '\n';
}
private function getDate():String
{
var date:Date = new Date();
var dateStr:String = '[' + date.getUTCHours() + ' : ' + date.getUTCMinutes() + ' : ' +
date.getUTCSeconds() + ' ' + date.getUTCMilliseconds() +'] ' ;
return dateStr;
}
/**
* 每次 unit test 前須要做的事
*/
protected function startUp():void
{
throw new Error('Plz override startUp.');
}
/**
* 每次 unit test 後須要做的事
*/
protected function shutdown():void
{
throw new Error('Plz override shutdown.');
}
/**
* 預設的顯示 Log 的通用函數
* @param msg
*
*/
protected function showLog(msg:String):void
{
trace(getDate() + msg);
}
/**
* 顯示詳細的測試資料.
*/
public function get Detail():String
{
return _detail;
}
}
}
internal class TestCaseVo
{
public var name:String;
public var fun:Function;
}
沒有留言 :
張貼留言