28
www.cfunited.com Unit and Functional Testing Your Flex Applications Mike Nimer Dir. Of Engineering nomee.com

Presentation - CFUnited 2010: A ColdFusion, Flex

Embed Size (px)

Citation preview

Page 1: Presentation - CFUnited 2010: A ColdFusion, Flex

www.cfunited.com

Unit and Functional Testing Your Flex Applications

Unit and Functional Testing Your Flex Applications

Mike Nimer

Dir. Of Engineering

nomee.com

Page 2: Presentation - CFUnited 2010: A ColdFusion, Flex

2www.cfunited.com

Isolate each part of the program and show that the individual parts are correct.

Provide a strict, written contract that the piece of code must satisfy.

Find problems early in the development cycle.

Unit testing allows the programmer to re-factor code at a later date, and make sure the module still works correctly

--wikipedia

The goal(s) of testing

Page 3: Presentation - CFUnited 2010: A ColdFusion, Flex

3www.cfunited.com

Types of TestingTypes of TestingTypes of TestingTypes of Testing

Manual

• Humans create test scripts.

• Step by Step instructions (word doc).

• Humans execute those tests.

• Low cost to begin. High cost over the life of a project

• Testing generally happens less often

Automated

• Humans create test methods. Machines execute those tests.

• Higher cost to develop. Much lower cost over the life of a project

• Testing can happen continually

• On every check-in

Page 4: Presentation - CFUnited 2010: A ColdFusion, Flex

4www.cfunited.com

Automated TestingAutomated TestingAutomated TestingAutomated Testing

Testing as part of Development

• As developers create code, they create tests

• Test Driven Development – tests first, code 2nd

• Tests are continually executed by developer to ensure new code does not break existing features

Automated build/test environments

• Part of “Continuous Integration”

• Code checked out and built automatically

• Code continually tested with your tests and reports generated

• Automated QA ensuring a last minute check in does not break a release

Page 5: Presentation - CFUnited 2010: A ColdFusion, Flex

5www.cfunited.com

Types of Automated TestingTypes of Automated TestingTypes of Automated TestingTypes of Automated TestingUnit

• Tests the smallest unit of code that is possible

• Usually tests a single method or function

• Multiple tests for every path through a method

• Usually created by Developer

Integration / functional

• Tests a combination of units

• Can be used to test UI Components

• Confirms that individual pieces of code work together

• Created by Developer or QA

Page 6: Presentation - CFUnited 2010: A ColdFusion, Flex

6www.cfunited.com

Tools for Unit TestingTools for Unit TestingTools for Unit TestingTools for Unit TestingUnit Testing

• (before)

• FlexUnit - The original Flex/ActionScript 3.0 unit testing framework.

• Fluint –Written for better asynchronous support and support for testing UI components.

• (today)

• FlexUnit 4 – A merge of FlexUnit 3 and Fluint. Providing better asyncronous testing support, support for UIComponent testing and IDE integration.

Page 7: Presentation - CFUnited 2010: A ColdFusion, Flex

7www.cfunited.com

Tools for Automated TestingTools for Automated TestingTools for Automated TestingTools for Automated TestingThese products all use the Flex Automation API, to monitor, manipulate, and control the Flex application.

• FlexMonkey

• TestComplete

• Selenium (with SeleniumFlex project)

• Mercury QuickTest Pro 9.1 (QTP)

• Borland SilkTest

• IBM Rational Functional Tester

Page 8: Presentation - CFUnited 2010: A ColdFusion, Flex

8www.cfunited.com

Testing TerminologyTesting TerminologyTesting TerminologyTesting Terminology

Test Method - A test method is the smallest unit of the testing process. A test method executes code and checks the outcome.

At the end of the test method the developer generally makes an “assertion”, stating the expected outcome of this executed code.

Test Case - A test case is a collection of test methods that share a common test environment, also referred to as a test fixture.

Test Suite - A test suite is a collection of test cases.

Test Runner - A test runner is an application that executes the test methods in your suites and cases.

Page 9: Presentation - CFUnited 2010: A ColdFusion, Flex

9www.cfunited.com

Understanding AssertionsUnderstanding AssertionsUnderstanding AssertionsUnderstanding Assertions

assertEquals()—Accepts two parameters and is a valid assertion if the two values are equal (==).

assertStrictlyEquals()—Accepts two parameters and is a valid assertion if the two values are strictly equal (===).

assertTrue()—Accepts a single parameter and is a valid assertion if the value is true.

assertFalse()—Accepts a single parameter and is a valid assertion if the value is false.

assertNull()—Accepts a single parameter and is a valid assertion if the value is null.

assertNotNull()—Accepts a single parameter and is a valid assertion if the value is not null.

fail()— Marks the test failed.

Page 10: Presentation - CFUnited 2010: A ColdFusion, Flex

10www.cfunited.com

Whats new in FlexUnit 4Whats new in FlexUnit 4Whats new in FlexUnit 4Whats new in FlexUnit 4• Support for all Junit 4 features• Support for UI testing• Metadata driven• Exception handling

• New attribute of [Test] Metadata allows you to define expected exceptions (instead of using try/catch)

• [Test(expects=“TypeError”)]

• Async test support• Support for multiple Runners• Hamcrest support

• Uses the Hamecrest AS3 project for a richer set of Asserts.

• Theories and Assumptions• IDE Support• Beta 1 now available.

Page 11: Presentation - CFUnited 2010: A ColdFusion, Flex

11www.cfunited.com

Understanding MetadataUnderstanding MetadataUnderstanding MetadataUnderstanding Metadata

FlexUnit 4 can be driven off of specific flexmetadata (similar to java annotations). This allows you to define tests as you see fit, with your own naming conventions or in existing code.

Before metadata you had to name your test methods a certain way, and your tests had to extend specific classes.

• [Test]• [Suite]• [Before]• [After]• [BeforeClass]• [AfterClass]• [Ignore]• [DataPoints]• [Theory]• [RunWith]

Page 12: Presentation - CFUnited 2010: A ColdFusion, Flex

12www.cfunited.com

Creating A Basic Unit TestCreating A Basic Unit TestCreating A Basic Unit TestCreating A Basic Unit Test

package simpleTest.tests{

import org.flexunit.Assert;

public class SimpleTestCase{

[Test]

public function testMath():void {

var x:int = 5 + 3;

Assert.assertEquals( 8, x )

}

}

}

Page 13: Presentation - CFUnited 2010: A ColdFusion, Flex

13www.cfunited.com

Creating A Basic Test SuiteCreating A Basic Test SuiteCreating A Basic Test SuiteCreating A Basic Test Suite

package simpleTest

{

import flexunit.framework.TestSuite;

import simpleTest.tests.SimpleTestCase;

[Suite]

[RunWith("org.flexunit.runners.Suite")]

public class SimpleTestSuite

{

// define a var for each test case.

public var simpleTestCase:SimpleTestCase;

}

}

Page 14: Presentation - CFUnited 2010: A ColdFusion, Flex

14www.cfunited.com

Creating A Test RunnerCreating A Test RunnerCreating A Test RunnerCreating A Test Runner<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"

creationComplete="runMe()"

xmlns:flexUnitUIRunner="http://www.adobe.com/2009/flexUnitUIRunner" >

<mx:Script><![CDATA[

import simpleTest.SimpleTestSuite;

import org.flexunit.listeners.UIListener;

import org.flexunit.runner.FlexUnitCore;

private var core:FlexUnitCore;

public function runMe():void {

core = new FlexUnitCore();

//Listener for the UI, optional

core.addListener( new UIListener( uiListener ));

core.run( SimpleTestSuite );

}

]]></mx:Script>

<flexUnitUIRunner:TestRunnerBase

id="uiListener"

width="100%" height="100%" />

</mx:Application>

Page 15: Presentation - CFUnited 2010: A ColdFusion, Flex

15www.cfunited.com

Asynchronous TestingAsynchronous TestingAsynchronous TestingAsynchronous Testing

Asynchronous Tests examples• Server calls• Timers• AIR Sqlite• AIR File Access

Page 16: Presentation - CFUnited 2010: A ColdFusion, Flex

16www.cfunited.com

Creating an Asynchronous Unit Test – Creating an Asynchronous Unit Test – Setup/TeardownSetup/TeardownCreating an Asynchronous Unit Test – Creating an Asynchronous Unit Test – Setup/TeardownSetup/Teardown

[Before(async)]public function setUp():void{

timer = new Timer( 500, 3 );}

[After(async)]public function tearDown():void {

if ( timer ) {timer.stop();

}

timer = null;}

Page 17: Presentation - CFUnited 2010: A ColdFusion, Flex

17www.cfunited.com

Creating an Asynchronous Test – Test MethodCreating an Asynchronous Test – Test MethodCreating an Asynchronous Test – Test MethodCreating an Asynchronous Test – Test Method

[Test(async)]public function testInTimePass() : void {

var obj:Object= {expected:3}

timer.delay = 100;timer.addEventListener(TimerEvent.TIMER_COMPLETE, Async.asyncHandler( this, completehandler, 500, obj, null) , false, 0, true ); timer.start();

}

protected function completehandler( event:Event, data_:Object):void{ if( event.type == "timerComplete” && ){

Assert.assertEquals(Timer(event.target).currentCount, data_.expected ); }else{

Assert.fail("wrong event type"); }}

Page 18: Presentation - CFUnited 2010: A ColdFusion, Flex

18www.cfunited.com

Integration TestingIntegration TestingIntegration TestingIntegration Testing

UIComponents• A common goal when developing Flex

applications is to test UIComponents in a repeatable way

• UIComponents are internally asynchronous

Page 19: Presentation - CFUnited 2010: A ColdFusion, Flex

19www.cfunited.com

Integration Testing (FlexUnit)Integration Testing (FlexUnit)Integration Testing (FlexUnit)Integration Testing (FlexUnit)

FlexUnit Sequences• Sometimes a test of a UIComponent can require

many steps to setup.

• For example, you may need to create a Login Form, populate it and then click a button before you can decide if everything worked

• Sequences are a shorthand to simplify that work into a readable set of steps

Page 20: Presentation - CFUnited 2010: A ColdFusion, Flex

20www.cfunited.com

Testing UIComponents – setupTesting UIComponents – setupTesting UIComponents – setupTesting UIComponents – setup

public var form:LoginForm;

[Before(async,ui)]public function setUp():void {

form = new LoginForm();Async.proceedOnEvent( this, form, FlexEvent.CREATION_COMPLETE,

200 );UIImpersonator.addChild( form );

}

[After(async,ui)]public function tearDown():void {

UIImpersonator.removeChild( form );form = null;

}

Page 21: Presentation - CFUnited 2010: A ColdFusion, Flex

21www.cfunited.com

Testing UIComponents – test methodTesting UIComponents – test methodTesting UIComponents – test methodTesting UIComponents – test method

[Test(async,ui)]public function testLogin():void {

var passThroughData:Object = new Object();passThroughData.username = 'myuser1';passThroughData.password = 'somepsswd';

var sequence:SequenceRunner = new SequenceRunner( this );sequence.addStep( new SequenceSetter( form.usernameTI, {text:passThroughData.username} ) );sequence.addStep( new SequenceWaiter( form.usernameTI, FlexEvent.VALUE_COMMIT, 100 ) );

sequence.addStep( new SequenceSetter( form.passwordTI, {text:passThroughData.password} ) );sequence.addStep( new SequenceWaiter( form.passwordTI, FlexEvent.VALUE_COMMIT, 100 ) );

sequence.addStep( new SequenceEventDispatcher( form.loginBtn, new MouseEvent( 'click', true, false ) ) );sequence.addStep( new SequenceWaiter( form, 'loginRequested', 100 ) );

sequence.addAssertHandler( handleLoginEvent, passThroughData );sequence.run();}

protected function handleLoginEvent( event:TextEvent, passThroughData:Object ):void {Assert.assertEquals( passThroughData.password, event.text );

}

Page 22: Presentation - CFUnited 2010: A ColdFusion, Flex

22www.cfunited.com

Testing UIComponents – test methodTesting UIComponents – test methodTesting UIComponents – test methodTesting UIComponents – test method

var sequence:SequenceRunner = new SequenceRunner( this );sequence.addStep( new SequenceSetter( form.usernameTI, {text:passThroughData.username} ) );sequence.addStep( new SequenceWaiter( form.usernameTI, FlexEvent.VALUE_COMMIT, 100 ) );

sequence.addStep( new SequenceSetter( form.passwordTI, {text:passThroughData.password} ) );sequence.addStep( new SequenceWaiter( form.passwordTI, FlexEvent.VALUE_COMMIT, 100 ) );

1. Create a new Sequence

2. Set a property on a UIComponent

3. Wait for the “valueCommit” event to fire, so you know the property was set correctly.

Page 23: Presentation - CFUnited 2010: A ColdFusion, Flex

23www.cfunited.com

Testing UIComponents – test methodTesting UIComponents – test methodTesting UIComponents – test methodTesting UIComponents – test methodsequence.addStep(

new SequenceEventDispatcher( form.loginBtn, new MouseEvent( 'click', true, false ) ) );sequence.addStep( new SequenceWaiter( form, 'loginRequested', 100 ) );

sequence.addAssertHandler( handleLoginEvent, passThroughData );sequence.run();

1. Add a new step that simulates a user clicking on the “login” button.

2. Wait for the “loginRequested” event.

3. Add an “assertHandler” to check the login when it is completed.

4. Run the test.

Page 24: Presentation - CFUnited 2010: A ColdFusion, Flex

24www.cfunited.com

Testing UIComponents – test methodTesting UIComponents – test methodTesting UIComponents – test methodTesting UIComponents – test method//sequence.addAssertHandler( handleLoginEvent, passThroughData );

protected function handleLoginEvent( event:TextEvent, passThroughData:Object ):void {

Assert.assertEquals( passThroughData.password, event.text );}

1. Use the assertHandler method to test the results of the login action (server call)

2. If the right data exists, success.

Page 25: Presentation - CFUnited 2010: A ColdFusion, Flex

25www.cfunited.com

Integration Testing (FlexMonkey)Integration Testing (FlexMonkey)Integration Testing (FlexMonkey)Integration Testing (FlexMonkey)

• Recording Scripts• Replaying Scripts

Page 26: Presentation - CFUnited 2010: A ColdFusion, Flex

26www.cfunited.com

TipsTipsTipsTips

• All Software projects should be thoroughly tested!!• Automated testing saves you money by preventing

bugs form returning again and again.

• A getting started rule of thumb for writing a new test case• Write one test that passes the “usual” case• Write one test that passes by testing the extremes• Write one test that is supposed to fail

• Continue building your test cases, by writing a test case for every bug that is submitted – before you close the bug as fixed.

• Tests cases should “clean up” after themselves• Any developer should be able to run the tests without custom

setup – if possible.

Page 27: Presentation - CFUnited 2010: A ColdFusion, Flex

27www.cfunited.com

Questions

?

Page 28: Presentation - CFUnited 2010: A ColdFusion, Flex

28www.cfunited.com

FlexUnit 4http://opensource.adobe.com/wiki/display/flexunit/FlexUnit

Flex Monkeyhttp://code.google.com/p/flexmonkey/

More on Continuous Integrationhttp://www.martinfowler.com/articles/continuousIntegration.html