Test Driven Development (TDD) Preso 360|Flex 2010

52
Test Driven Development (TDD) San Jose 360|Flex @EladElrom

description

Test Driven Development (TDD) Preso 360|Flex 2010

Transcript of Test Driven Development (TDD) Preso 360|Flex 2010

Page 1: Test Driven Development (TDD) Preso 360|Flex 2010

Test Driven Development (TDD)

San Jose 360|Flex

@EladElrom

Page 2: Test Driven Development (TDD) Preso 360|Flex 2010

@EladElrom• Associate Dev Director @ Sigma Group• Senior Flash Engineer & Lead• Technical Writer• FlashAndTheCity Organizer• Adobe Community Professional

Page 3: Test Driven Development (TDD) Preso 360|Flex 2010

TOCUSING FLEXUNIT 4 WITH TEST DRIVEN DEVELOPMENT• Test Driven Development quick overview• Defining Application’s Objective• User Stories

GETTING STARTED• Creating the application• Creating the class to be tested• Creating your first Test Suite• Add your first test case class

IMPLEMENTING YOUR USER STORIES• Retrieve Tweets User Story• Retrieve tweets every few seconds User Story

Page 4: Test Driven Development (TDD) Preso 360|Flex 2010

Show & tell

• How many of you have used TDD?• How have of you have tried to use TDD and

gave up?• How many always wanted wanted to use TDD

but never did?

Page 5: Test Driven Development (TDD) Preso 360|Flex 2010

In Software Engineer, What’s your

development techniques

options?

Page 6: Test Driven Development (TDD) Preso 360|Flex 2010

• Any team where the biggest jerk makes all the big decisions is asshole driven development. All wisdom, logic or process goes out the window when Mr. Asshole is in the room, doing whatever idiotic, selfish thing he thinks is best. There may rules and processes, but Mr. A breaks them and people follow anyway.

Scott Berkun

Asshole Driven Development (ADD)

Page 7: Test Driven Development (TDD) Preso 360|Flex 2010

• The driving force behind most individual efforts is to make sure than when the shit hits the fan, they are not to blame.

Scott Berkun

Cover Your Ass Engineering (CYAE)

Page 8: Test Driven Development (TDD) Preso 360|Flex 2010

• Get it out the door as quickly as possible, cut-n-paste from anything that you find that works on Google, if it works it’s ready

Duct-tape Driven Design (DDD)

Page 9: Test Driven Development (TDD) Preso 360|Flex 2010

Now Seriously...

Page 10: Test Driven Development (TDD) Preso 360|Flex 2010
Page 11: Test Driven Development (TDD) Preso 360|Flex 2010

WaterfallSoftware Development

Process

Page 12: Test Driven Development (TDD) Preso 360|Flex 2010

Disadvantages of Waterfall Process• Creating tasks based on developer’s opinion rather than

project’s needs.• Spending time on technical design documents such as UML

diagrams.• May create code that is not used in the app and increase

development time.• One programmer code may break another programmer code.• Many time methods do more than one task and code is hard

to maintain.• Changing requirements may require re-engineering parts of

the app.

Page 13: Test Driven Development (TDD) Preso 360|Flex 2010

What’s the alternative?

Page 14: Test Driven Development (TDD) Preso 360|Flex 2010

What’s TDD?

• The concept is pretty simple. You write your tests before you write your code. It’s that simple and worth repeating: write tests before code!

• Test Driven Development is a software development technique in which programmers are writing a failed test that will define the functionality before writing the actual code.

Page 15: Test Driven Development (TDD) Preso 360|Flex 2010

Process overview

Page 16: Test Driven Development (TDD) Preso 360|Flex 2010

Developers are lazy!

• Software developers our job is to be lazy. Lazy = Efficient.. Really?

• We automate repetitive tasks. Yet we most of our time testing and debugging our code manually (80% as some studies suggest).

• Why would you choose to do this repetitive and annoying task when you automate all of the others?

Page 17: Test Driven Development (TDD) Preso 360|Flex 2010

Automate testing

• Let humans do the work they do best while letting computers do the work they do best and ending up with code that is more stable and more maintainable!

Page 18: Test Driven Development (TDD) Preso 360|Flex 2010

Furthermore• The concept of TDD is based on Extreme Programming (XP) development paradigm,

which talks about teams that work on the development of dynamic projects with changing requirements and a development cycle that includes TDD for writing the test before the code itself. TDD is not the complete development cycle; it is only part of the Extreme Programming (XP) development paradigm. Preparing the tests before writing the code helps a development team to demonstrate their work in small steps, rather than making the customer or other stakeholders wait for the complete result.

• Moving in small increments also makes it easier to accommodate changing requirements and helps ensure that your code does what it needs to do, and nothing more. It is important to mention that the focus of the TDD technique is to produce code and not to create a testing platform. The ability to test is an added benefit.

• TDD is based on the idea that anything you build should be tested and if you are unable to test it, you should think twice about whether you really want to build it.

Page 19: Test Driven Development (TDD) Preso 360|Flex 2010

“The single most important effect of practicing TDD is that it forces you as the developer to be the first consumer of your own API.”

Brian Button

Page 20: Test Driven Development (TDD) Preso 360|Flex 2010

TDD Rules

• You are not allowed to write any production code unless it is to make a failing unit test pass.

• You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.

Via butunclebob.com

Page 21: Test Driven Development (TDD) Preso 360|Flex 2010

What most programmers think about TDD when they are first introduced to the

technique?

Page 22: Test Driven Development (TDD) Preso 360|Flex 2010

Via butunclebob.com

• "This is stupid!" • "It's going to slow me down”• “It's a waste of time and effort”• “It will keep me from thinking”• “It will keep me from designing”• “It will just break my flow”

Programmers respond:

Page 23: Test Driven Development (TDD) Preso 360|Flex 2010

Defining Application’s ObjectiveUnderstanding the application objectives is asimportant as coding your application. Here’s aLessons we can learn from a Master Carpenter:

Measure Twice, Cut Once!

Page 24: Test Driven Development (TDD) Preso 360|Flex 2010

Defining Application’s ObjectiveYou need to understand what you are

developingbefore you get started. In our case, we are

building an application that will do the following:

• Allow attendees to communicate with

each other through twitter API. • The class will keep a list of tweets with

#FlashAndTheCity hashtag• The class will check for updates of tweets

often

Page 25: Test Driven Development (TDD) Preso 360|Flex 2010

User StoriesA good approach to take to ensure the tasks are defined well is to follow Agilesoftware development mythology. The Agile mythologies talks about creatingone or more informal sentences in an everyday or business language, this typeof approach is known as a User Story. The User Story should be limited incharacters and should fit a small paper note card. The user stories are usuallywritten by the client in order to give direction to build the software. Think ofthis list as your todo list.

• In our case here are the User Stories:• Retrieve tweets with #FlashAndTheCity HashTag from Twitter API.• Have a service call to twitter and retrieve tweets every few seconds.• Login into user's twitter account and retrieve personal information.• Store user's information so user wouldn’t have to login again every time. • Post a tweet on twitter from a user • Add #FlashAndTheCity Hashtag to a tweet so user wont have to type it every time

and the application will be able to retrieve all tweets related to the conference.• Keep a list of tweets with the ability to add a tweet & remove a tweet.

Page 26: Test Driven Development (TDD) Preso 360|Flex 2010

Creating the application• With the knowledge of what we need to develop we

are ready to get started. The first step is to create the application open Eclipse or Flash Builder 4 Beta and create a new project name Companion (see instructions below).

• Select File > New > Flex Project to create the project. • For the Project Name, type Companion, ensure you set

the project as Desktop application type.• Click Finish.

Page 27: Test Driven Development (TDD) Preso 360|Flex 2010

Creating your first Test Suite• A test suite is a composite of tests. It runs a

collection of test cases. During development you can create a collection of tests packaged into test suite and once you are done, you can run the test suite to ensure your code is still working correctly after changes have been made.

• To create a test suite, choose File > New > Test Suite class.

Page 28: Test Driven Development (TDD) Preso 360|Flex 2010

Continue• After you select New Test Suite Class a wizard

window opens up. Fill in the following information:

• In the New Test Suite Class dialog box, name the class CompanionTestSuite.

• Select New FlexUnit 4 Test. • Click Finish.

Page 29: Test Driven Development (TDD) Preso 360|Flex 2010

Look at your Test Suite• Flash Builder 4 added the following class under the flexUnitTests folder:

package flexUnitTests{

[Suite][RunWith("org.flexunit.runners.Suite")]public class CompanionTestSuite{}

} • The Suite metadata tag indicates that the class is a suite. The RunWith tag instructs the

test runner to execute the tests that follow it using a specific class. FlexUnit 4 is a collection of runners that will run a complete set of tests. You can define each runner to implement a specific interface. You can, for example, specify a different class to run the tests instead of the default runner built into FlexUnit 4.

Page 30: Test Driven Development (TDD) Preso 360|Flex 2010

FlexUnit 4 Metadata• The FlexUnit 4 framework is based on metadata tags. So far

you've seen [Suite], [Test], and [RunWith]. Here are some other common metadata tags:

• [Ignore] - Causes the method to be ignored. You can use this tag instead of commenting out a method.

• [Before] - Replaces the setup() method in FlexUnit 1 and supports multiple methods.

• [After] - Replaces the teardown() method in FlexUnit 1 and supports multiple methods.

• [BeforeClass] - Allows you to run methods before a test class. • [AfterClass] - Allows you to run methods after a test class.

Page 31: Test Driven Development (TDD) Preso 360|Flex 2010

Add your first test case class• Next, you need to create a test case. A test case

comprises the conditions you want to assert to verify a business requirement or a User Story. Each test case in FlexUnit 4 must be connected to a class.

Create the Test Case class: • Choose File > New > Test Case Class.• Select New FlexUnit 4 Test.• Type flexUnitTests as the package.• Type TwitterHelperTester as the name.

Page 32: Test Driven Development (TDD) Preso 360|Flex 2010

Add a Reference • Important: Ensure that there is a reference in

CompanionTestSuite.as to TwitterHelperTester: package flexUnitTests{

[Suite][RunWith("org.flexunit.runners.Suite")]public class CompanionTestSuite{

public var twitterHelperTester:TwitterHelperTester;}

}

Page 33: Test Driven Development (TDD) Preso 360|Flex 2010

Implementing your User Stories• Retrieve Tweets User StoryWe can start with the first User Story, Retrievetweets with #FlashAndTheCity HashTag fromTwitter API.

Page 34: Test Driven Development (TDD) Preso 360|Flex 2010

Understand your goal• In our case we are testing that the service is working

correctly. • We are using a public API that is maintained by Twitter

and creating a Mashup application. • Using a well maintain API helps us creating our

application quickly, however it also store a disadvantage that in any time Twitter may change their API and our application will stop working.

• We are testing that the fail and success events are dispatching correctly and ensuring that the API is working, see the code below:

Page 35: Test Driven Development (TDD) Preso 360|Flex 2010

testRetrieveTweetsBasedOnHashTag [Test(async,timeout="500")]public function testRetrieveTweetsBasedOnHashTag():void {

classToTestRef = new TwitterHelper();var EVENT_TYPE:String = "retrieveTweets";

classToTestRef.addEventListener(EVENT_TYPE, Async.asyncHandler( this, handleAsyncEvnet, 500 ), false, 0, true );

classToTestRef.retrieveTweetsBasedOnHashTag("FlashAndTheCity”); }

private function handleAsyncEvnet(event:Event, passThroughData:Object):void

{Assert.assertEquals( event.type, "retrieveTweets" );

}

Page 36: Test Driven Development (TDD) Preso 360|Flex 2010

Assertion methods

Page 37: Test Driven Development (TDD) Preso 360|Flex 2010
Page 38: Test Driven Development (TDD) Preso 360|Flex 2010

Working on the compilation errors• Save the file and now you see a compile time

error:• Call to a possibly undefined method

retrieveTweetsBasedOnHashTag through a reference with static type utils:TwitterHelper.

• This is actually a good. The compiler is telling you what you need to do next. We can now create the method in TwitterHelper in order to get rid of the compiler error.

Page 39: Test Driven Development (TDD) Preso 360|Flex 2010

Create TwitterHelper – write min code package utils{ import flash.events.EventDispatcher; import flash.events.IEventDispatcher; public class TwitterHelper extends EventDispatcher { public function TwitterHelper(target:IEventDispatcher=null) { super(target); }

/** * Method to send a request to retrieve all the tweet with a HashTag * @param hashTag defined hashtag to search * */ public function retrieveTweetsBasedOnHashTag(hashTag:String):void {

// implement }

}}

Page 40: Test Driven Development (TDD) Preso 360|Flex 2010

Run FlexUnit Tests • Compile the project and we don’t have any

compile time errors and you can run the tests. Select the Run icon carrot and in the drop menu select FlexUnit Tests.

Page 41: Test Driven Development (TDD) Preso 360|Flex 2010

Review the Results• Flash Builder opens a new window where the

tests are run and shows the results of your test, see below:

• 1 total test was run • 0 were successful • 1 was a failure • 0 were errors• 0 were ignored

Page 42: Test Driven Development (TDD) Preso 360|Flex 2010

Results view

Page 43: Test Driven Development (TDD) Preso 360|Flex 2010

Change the Test from Fail to Pass• In order to pass the test you now need to

write the actual code. At this point we wrote the test and once we write the code the test will succeed. I have implemented the code to call Twitter and retrieve results that includes #FlashAndTheCity hashtag

• Write the code on TwitterHelper; retrieveTweetsBasedOnHashTag & onResults methods

Page 44: Test Driven Development (TDD) Preso 360|Flex 2010

Write code package utils{

import com.adobe.serialization.json.JSON;

import flash.events.EventDispatcher;

import mx.rpc.events.FaultEvent;import mx.rpc.events.ResultEvent;import mx.rpc.http.HTTPService;

public class TwitterHelper extends EventDispatcher{

/** * Holds the service class */private var service:HTTPService; //--------------------------------------------------------------------------//// Default Constructor////--------------------------------------------------------------------------public function TwitterHelper() {

// implement}

/** * Method to send a request to retrieve all the tweet with a HashTag * @param hashTag defined hashtag to search * @url the twitter API url * */ public function retrieveTweetsBasedOnHashTag(hashTag:String, url:String):void {

service = new HTTPService(); service.url = url; service.resultFormat = "text"; service.addEventListener(ResultEvent.RESULT, onResults); var object:Object = new Object(); object.q = hashTag; service.send( object );

Page 45: Test Driven Development (TDD) Preso 360|Flex 2010

Write code #2 }

//-------------------------------------------------------------------------- // // Event handlers // //--------------------------------------------------------------------------

/** * Method to handle the result of a request to retrieve all the list * @param event * */ private function onResults(event:ResultEvent):void {

service.removeEventListener(ResultEvent.RESULT, onResults); service.removeEventListener(FaultEvent.FAULT, onFault); var rawData:String = String( event.result ); var object:Object = JSON.decode( rawData ); var results:Array = object.results as Array; var collection:Vector.<TweetVO> = new Vector.<TweetVO>; results.forEach( function callback(item:*, index:int, array:Array):void {

var tweet:TweetVO = new TweetVO( item.from_user, item.from_user_id, item.geo, item.id, item.profile_image_url, item.source, item.text, item.to_user, item.to_user_id );

collection.push( tweet );

}); // dispatch an event that holds the results this.dispatchEvent( new TwitterHelperSuccessEvent( collection ) );

}}

}

Page 46: Test Driven Development (TDD) Preso 360|Flex 2010

Run your test again• Run the test again and observe the results.• A test that does not fail succeeds • Click the Run Completed Button • Observe the Green Bar that indicates success

Page 47: Test Driven Development (TDD) Preso 360|Flex 2010

Refactor• At this point, we can do a small refactoring to

the test case and include the static method from the custom event instead of having the string attached, which will ensure our tests still pass in case we refactor the event type string, see code below:

classToTestRef = new TwitterHelper();var EVENT_TYPE:String =

TwitterHelperSuccessEvent.RETRIEVE_TWEETS;

Page 48: Test Driven Development (TDD) Preso 360|Flex 2010

Refactor tests - tests have duplication that can become painful to maintain• In our case, we need to instantiating TwitterHelper in each test.• Granted, there are just two, but this will grow• We can solve this problem by using additional metadata provided by FlexUnit 4

called [Before] and [After]• [Before] can be applied to any method that you wish called before each test.• [After] will be called after each test

• For good measure, let’s add a method name tearMeDown() and mark it with the [After] metadata.

• The [After] method gives you a place to clean up from your test case.• In this case just set classToTestRef equal to null so the instance is available for

garbage collection• In more complicated tests it is often crucial to remove listeners, etc. in this way.

In our case TwitterHelper is already removing the listeners so we don’t need to do that, but many other times you will.

Page 49: Test Driven Development (TDD) Preso 360|Flex 2010

Refactor the actual code • We focus on passing the test and didn’t care that much

about the code, however you may find out that the code is too complex and can be simplify by implementing a design pattern, or just adding some small modification.

• For instance, I can add metadata so when you instantiate the class and add event listeners in MXML component you will get the event type available automatically. Add the code below to the TwitterHelper class.

Page 50: Test Driven Development (TDD) Preso 360|Flex 2010

My personal notes about TDD• Don’t use TDD for Micro-architecture User

Gestures.• Usually avoid using TDD for testing GUI.• Use TDD for building APIs, frameworks,

utilities and helpers.• Use TDD for testing services.• Use TDD for code that will be used on more

than one application.

Page 52: Test Driven Development (TDD) Preso 360|Flex 2010

Q&A

@EladElrom