Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1]
Print
Author Topic: Testing practices for Pure MVC  (Read 12140 times)
DEfusion
Courseware Beta
Jr. Member
***
Posts: 16


View Profile Email
« on: February 28, 2008, 06:02:01 »

I just wondered if anyone had any best practices for unit testing/functional testing your Pure MVC application (mine is in Flex).

I was thinking you could test the views & your models/business objects pretty easily, but it would be nice to test that all the command/proxies/mediators etc. are setup and working as expected.

Any thoughts?
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: April 29, 2008, 11:00:43 »

Sorry I've missed this post.

Unit Testing Flex is a thorny problem. If you want to be thorough in testing the client you have to be able to automate view testing. This means buying Mercury Interactive’s Quick Test Pro. (I think this has been sold to HP, now, so it may have their name on it.

For testing everything else, you have to be able to isolate it from the framework and just test the methods. The PureMVC framework unit tests themselves are a good place to start. You must limit your tests to the functionality in a method, and not on the cascade of actions that take place in a notification process.

On these forums, searching for ‘unit test’, you’ll find a little more conversation on the topic. Here are a few relevant posts:

http://forums.puremvc.org/index.php?topic=419.0
http://forums.puremvc.org/index.php?topic=213.0

-=Cliff>
Logged
notjones
Jr. Member
**
Posts: 10


View Profile Email
« Reply #2 on: May 09, 2008, 08:10:35 »

One approach that is working for us is to create unit tests using FlexUnit and use them to test all methods and classes that do not directly alter view components. Commands and proxies for the most part can be tested and some code in mediators.

To pull this off, I created a special extension of Facade that stores notifications in an ArrayCollection instead of immediately sending them. Then I added additional methods to check to see if a notification had been sent (added to the internal array collection), actually send the notification, and retrieve the notification. Using this version of facade, I'm able to create test data for the body of a notification that will normally trigger a command. Send that notification and verify that the facade has it, then really send the notification. The command as it processes sends additional notifications. The command sent notifications are stored in the facade and not immediately sent. Code in my unit test checks whether the correct notifications were sent and if the body of those notifications is as expected. Once they have been checked, I can tell the special facade to really send them and again check to see if the correct follow on notifications are sent.

This approach is working well checking the flow of notifications and command executions. Overriding sendNotification to save the notification is easy--just store the notification in an array collection. Checking for stored notifications requires that you loop through all entries in the array collection checking for the notification name. Really sending a perviously stored notification just requires doing a super.SendNotificaiton call.

Give this approach a try and see if it will work for you.
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #3 on: May 13, 2008, 11:55:11 »

Brilliant approach, notjones.

I call this pattern the 'intercepting facade' as it intervines in the standard 'firemans carry' of notification traffic. I actually thought of including something like it in the framework to begin with but nixxed the idea as too complex for the core.

You can also use this intercepting facade concept to do logging of notification traffic for instance to analyze the way an application is being used by looking at how the users invoke the use cases.

Thanks for sharing your experiences with this approach to testing!

-=Cliff> 
Logged
ohappyle
Newbie
*
Posts: 3


View Profile Email
« Reply #4 on: September 15, 2008, 05:14:31 »

....Give this approach a try and see if it will work for you.

Thanks, it works. Cool!
Logged
ohappyle
Newbie
*
Posts: 3


View Profile Email
« Reply #5 on: September 16, 2008, 07:39:06 »

... Really sending a perviously stored notification just requires doing a super.SendNotificaiton call...
Thanks for the idea, here is a simple example of notjones concept:
--Facade--

      public var incommingNotificationAray:ArrayCollection = new ArrayCollection();
      public var sentNotificationArray:ArrayCollection = new ArrayCollection();
      
      override public  function sendNotification(notificationName:String, body:Object = null, type:String = null):void
      {
         var aNotification:Notification = new Notification(notificationName, body, type);
         incommingNotificationAray.addItem(aNotification);
      }
      
      
      public function sendNote(notification:Notification):void {         
         incommingNotificationAray.removeItemAt(incommingNotificationAray.getItemIndex(notification));
         sentNotificationArray.addItem(notification);
         super.sendNotification(notification.getName(), notification.getBody(), notification.getType());
      }
      
      
      public function wasReceived(notificationName:String ):Notification {
         var i:int;
         var arr:Array = incommingNotificationAray.source;
         while(i < arr.length) {
              if(Notification(arr).getName()  == notificationName) {
                  return arr as Notification;
              }
              i++;
         }
         return null;
      }

--TestCase--
      public function testSaveHistory():void {
         var historyProxy:HistoryProxy = registerProxy();
         facade.sendNotification(ApplicationFacade.SAVE_USER_ACTION, new HistoryVO());
         var receivedNote:Notification = facade.wasReceived(ApplicationFacade.SAVE_USER_ACTION);
         if(receivedNote) {
            facade.sendNote(receivedNote);
         }         
         assertTrue("there is 1 item in the history list", historyProxy.historyArray.length == 1);
      }
Logged
Pages: [1]
Print