function handleEvent( event:Event ):void { trace("Handling Event"); } var blah:HTTPService(); blah.addEventListener( ResultEvent.RESULT, handleEvent ); blah.send(); trace("End of code block");이 코드가 동작했을때, "End of code block" 라는 trace 구문이 콘솔에 보여진다. 그런 다음, 향후 어떤 시점에 “Handling Event” 메서드가 발생한다.
function handleEvent( event:Event ):void { trace("Handling Event"); } var blah:TextInput = new TextInput(); addChild( blah ); blah.addEventListener( FlexEvent.VALUE_COMMIT, handleEvent ); blah.text = "Mike"; trace("End of code block");이번 예제에서는, “Handling Event”라는 trace 구문이 “End of code block” 구문 이전에 발생할 것이다. 왜냐하면 향후 어떤 시점에서가 아니라 텍스트가 변경되자 마자 텍스트 입력 필드에서 valueCommit 이벤트가 전달되기 때문이다. 이 예는 이벤트 기반이긴 하지만 동기(synchronous) 방식이다.
import flash.events.TimerEvent; import flash.utils.Timer;6) Timer 타입의 timer라는 변수를 protected로 정의한다.
protected var timer:Timer;7) 그 클래스 안에 setUp() 메서드를 오버라이드(override)하는 protected 메서드를 생성한다. super.setUp() 가 호출된 다음 timer의 새로운 객체를 인스턴스화 하는데, 이것은 1000ms를 대기했다 한번씩 실행할 것이다. timer 객체는 생성될 때 초기화 변수를 필요로 한다. 하지만 이것은 나중에 수정될 것이다.
override protected function setUp():void { super.setUp(); timer = new Timer( 1000, 1 ); }8) tearDown() 메서드를 오버라이드하는 protected로 되어 있는 또 다른 메서드를 생성한다. super.tearDown()가 호출된 후, timer를 멈추고 timer 값을 null 로 셋팅한다.
override protected function tearDown():void { super.tearDown(); if ( timer ) { timer.stop(); } timer = null; }9) null을 반환하는 testTimerSingle()라는 또 다른 public 메서드를 생성한다. 일반적으로 test 메서드는 코드를 실행하고 assertion을 책임지고 있다. 만일 assertion이 참이 아니면, 그 테스트 메서드는 실패한다. 네거티브한 관점에서 말하자면, test 메서드가 참이 아닌 assertion을 만들면, 그것은 성공이다. 비동기(asynchronous) test 경우 이것은 심각한 문제를 내포하고 있다. 왜냐하면 그 test는 즉각적으로 성공 또는 실패를 나타내기 보다 어떤 일이 일어날 결과를 기다려야하기 때문이다.
var handler:Function = asyncHandler( handleSingleResult, 2000, null, handleShouldNotFail );asyncHandler() 메서드는 인자로 네개의 값을 받는다. 첫번째는 의도한 이벤트가 어떤 시간적인 방식으로 발생할지를 알려주기 위한 방식이다. 두번째는 이 test가 끝났다고 선언하기 전 그 이벤트를 얼마 동안 기다릴 것인지를 알려준다. 세번째는 test와 함께 전달될 임의의 데이타이다. 마지막으로, 네번째는 시간이 완료되기 전에 그 의도된 결과를 받을지 말지를 알려주기 위한 방식이다.
timer.addEventListener(TimerEvent.TIMER_COMPLETE, handler,false, 0, true );13) timer의 start() 메서드를 호출한다. 최종적으로 test 메서드는 아래와 같다.
public function testTimerSingle() : void { var handler:Function = asyncHandler( handleSingleResult, 2000, null, handleShouldNotFail ); timer.delay = 1000; timer.addEventListener(TimerEvent.TIMER_COMPLETE, handler, false, 0, true ); timer.start(); }14) 두개의 값을 받아들이는 handleSingleResult()라는 새로운 메서드를 생성한다. 첫번째는 event라는 Event 타입이다. 두번째는 passThroughData라는 Object타입이다. 이 메서드는 시간이 다 되기전 timer 이벤트가 발생하면 호출될 것이다.
protected function handleSingleResult( event:Event, passThroughData:Object ):void { }이 경우 이벤트 객체는 timer 이벤트이다. passThroughData는 asyncHandler() 메서드를 통해 전달될 세번째 값으로 어떤 데이터도 가질 수 있다. 여기서, 이것은 null값이다.
protected function handleShouldNotFail( passThroughData:Object ):void { }16) handleShouldNotFail() 메서드 안에서, fail() 메서드를 호출한다. fail() 메서드는 테스트 결과로 표시될 메시지를 받는다.
protected function handleSingleResult( event:Event, passThroughData:Object ):void { fail("Timeout Reached"); }17) 이전에 만든 asyncSuite 디렉토리 안에 net.digitalprimates.fluint.tests.TestSuite를 슈퍼클래스로 하는 AsyncSuite라는 새로운 ActionScript 클래스를 생성한다.
import asyncSuite.tests.TestTimer;19) AsyncSuite 클래스의 생성자 안에 TestTimer 클래스의 새로운 인스턴스를 추가하기 위해 TestSuite 슈퍼클래스의 addTestCase() 메서드를 사용한다.
public function AsyncSuite() { addTestCase( new TestTimer() ); }AsyncSuite는 현재 하나의 test case를 포함하고 있는데, 이것은 하나씩의 메서드를 가지고 있다. 하지만 실제 테스트 환경에서는 여러분의 suite들은 수십 혹은 수백개의 메서드를 가진 각각의 case를 수백개씩 가질 수도 있다.
protected function startTestProcess( event:Event ) : void { var suiteArray:Array = new Array(); suiteArray.push( new MathSuite() ); suiteArray.push( new AsyncSuite() ); testRunner.startTests( suiteArray ); }만일 이 지점에서 FlexTestRunner.mxml 파일이 실행하면, 세개의 test가 실행되고, 그 세개가 통과된 것을 볼 수 있다. 즉, MathSuite로 부터 두개, 그리고 AsyncSuite로 부터 한개이다.
public function testTimerMultiple() : void { var obj:Object = new Object(); obj.repeatCount = 4; var handler:Function = asyncHandler( handleMultipleResult, 2000, obj, handleShouldNotFail ); }5) 다음으로 타이머의 delay 속성을 50ms으로 지정한다.
public function testTimerMultiple() : void { var obj:Object = new Object(); obj.repeatCount = 4; var handler:Function = asyncHandler( handleMultipleResult, 2000, obj, handleShouldNotFail ); timer.delay = 50; timer.repeatCount = obj.repeatCount;; timer.addEventListener(TimerEvent.TIMER_COMPLETE, handler, false, 0, true ); timer.start(); }9) 다음으로, event객체와 passThroughData를 인자값으로 받는 handleMultipleResult()라는 새로운 메서드를 생성한다.
protected function handleMultipleResult( event:Event, passThroughData:Object ):void { }10) 마지막으로, assertEquals() 메서드를 호출한다. 이 메서드는 timer의 currentCount 속성에 passThroughData의 repeatCount과 같은지를 확인하는 assertion을 만들기 위함이다. 다시 말해, 여러분이 지정한 만큼 그 타이머가 동작했는가를 확인한다.
protected function handleMultipleResult( event:Event, passThroughData:Object ):void { assertEquals( timer.currentCount, passThroughData.repeatCount ); }만일 여러분이 이 시점에 테스트 실행기(test runner)를 실행하면 네개의 test들이 실행되고, 네개가 성공했다는 결과를 보게 될 것이다. 여러분이 원한다면, 각각의 timer가 실행하는데 걸릴 횟수와 각각의 test가 대기할 시간을 다양하게 해보라. 이것은 실패하게 되는 상황들을 모의로 설정하고, 테스트 실행기(test runner)가 어떻게 반응하는지를 볼 수 있도록 해줄 것이다.
이전 글 : 다섯 RESTful 친구들
최신 콘텐츠