Results 1 to 6 of 6

Thread: Module Testing FB4

  1. #1
    Join Date
    Oct 2007
    Posts
    17

    Default Module Testing FB4

    Ok, I have spent enough time reading all the past posts about modules, context and testing. Let me explain from start to finish what i am doing and someone can judge if my issues warrant a reply.

    I have the following design (click here) I am attempting to create using Test Driven Development (TDD) in a practical sense (meaning that the process we come up with will serve the entire development team). To give you some background, one of the encompassing issues we all hear about from developers is that it's too hard. I am attempting to come up with a process that deals with both of the viewpoints contained within this opinion. The first being that you must do some domain translation to a unit test, and the second being the difficulty of testing frameworks you have at your disposal. As for myself, I am having issues with the latter.

    Here are the test Scenarios:

    1. Test that FlashVar Location is populated with Application context filename, path and the service module path
    testFlashVarLocationPassedResult()

    2. Load Application Context File
    testLoadApplicationContextPassed()

    3. Load Service Module

    Here is where i am running into real issues. Up to now, I relied on making changes to the FlexUnitApplication.mxml via an imported script that contained all the needed code for accessing the flashvars through that application. Since this mxml file is generated every time new methods are added and tests are run, I came up with this cut and paste methodology. I knew it wasn't the best answer, and when ran into issues when trying to obtain the Application Context within the Module Event, I began looking at the Spring Test Framework in earnest, trying to figure out how to use it.

    Here is the code where i try to access the context...

    Code:
    		public function appContextCompleteHandler(event:Event, passThroughData:Object):void
    		{
    			_applicationContext.removeEventListener(Event.COMPLETE, Async.asyncHandler);
    			//Assert.assertTrue(_applicationContext is FlexXMLApplicationContext);
    			var info:IModuleInfo = ModuleManager.getModule(application.serviceModulePath);
    			_moduleInfoList[info] = true;
    			info.addEventListener(ModuleEvent.READY, Async.asyncHandler(this, handleModuleReady, 15000, null, handleTimeout));
    			info.addEventListener(ModuleEvent.ERROR, Async.asyncHandler(this, handleModuleError, 15000, null, handleTimeout));
    			info.load(new ApplicationDomain(ApplicationDomain.currentDomain));
    		}
    
    		protected function handleModuleReady(event:ModuleEvent, passThroughData:Object):void
    		{
    			var info:IModuleInfo = event.module;
    			delete _moduleInfoList[info];
    			info.removeEventListener(ModuleEvent.READY, handleModuleReady);
    			info.removeEventListener(ModuleEvent.ERROR, handleModuleError);
    			var module:ISASModule = info.factory.create() as ISASModule;
    			module.applicationContext = _applicationContext;
    			(module as Module).data = info;
    		}
    The event is populated correctly and contains the event.module object. the local variable "info" is created just fine but the factory method does not produce an ISASModule, in fact it produces a null.

    This section of code runs just fine within the actual application, and is taken from the example on modules (I learn through examples). I have looked at the event objects in debug to compare and there is no noticeable difference. The only difference seems to be not running within an application object and requesting an object via a factory method from the Spring Container.

    What would really get me going is an example of loading a module within the Spring ActionScript Framework using Flexunit4 utilizing the classes discussed in Chapter 7. I'm sure they all have testing that has been proven to work.

    An opinion...

    I'll be frank here folks. I am a proponent of Spring ActionScript, and my client is heavy on the Java version. I have training and rate myself medium in various areas of Java Spring. I am also am well versed in ActionScript and FLEX. Achieving a high adoption rate for enterprise shops means that there has to be a ready amount of examples and test cases to learn quickly from. The last thing I want to do is spend weeks trying to understand how to use a TDD framework that is guaranteed to save weeks of development time. And if all we can use is a rudimentary approach to testing with Spring ActionScript because to build a complete testing system requires an experts understanding (we want to use this for a large team) and weeks of ongoing effort, then it will never last and people will point to it as: "yeah, we tried that once, it didn't work". Rod Johnson started out creating Spring because every other way was convoluted. To people like yourself, Roland and Christophe, this stuff comes to you as you dream. But for people like me, it keeps me awake at night!

    Thank you for your attention to this long plea. Please accept my apologies ahead of time if it seems i am frustrated or impatient in my remarks. I really want to achieve mastery of this quickly, and right now, it seems so far away...

    Curtis Fisher

  2. #2
    Join Date
    Dec 2008
    Location
    Brussels
    Posts
    407

    Default

    Hey Curtis,

    your issue is very strange indeed. If the Module.READY event is fired it means that the module is indeed *loaded* succesfully.
    Yet if this:

    Code:
    var module:ISASModule = info.factory.create() as ISASModule;
    yields null, then my first reaction would be that the module you're loading isn't implementing the ISASModule interface.
    Now, just as a sanity check, can you try this:
    Code:
    var module:* = info.factory.create();
    and check if the 'module' is still null? And if it's not, check in your debugger what exactly the module type is that was created.

    Your setup seems pretty elaborate, I'd like to respond in more detail to what you've posted but, unfortunately, right now I am swamped by my daily work. So it might not be until the weekend that I'll be able to get round to it, I'm sorry.

    cheers,

    Roland

  3. #3
    Join Date
    Oct 2007
    Posts
    17

    Default

    Tried your suggestion and still null.


    Here is the copied object from Debug...

    Code:
    module	ModuleInfoProxy	ModuleInfoProxy (@38ab5b9)	ModuleInfoProxy	
    	[inherited]	flash.events.EventDispatcher	
    	data	null	
    	_data	null	
    	error	Boolean	false	Boolean	
    	factory	com_srcp_module_application_services_ApplicationServicesModule_mx_core_FlexModuleFactory	     com_srcp_module_application_services_ApplicationServicesModule_mx_core_FlexModuleFactory (@4869ec1)	com_srcp_module_application_services_ApplicationServicesModule_mx_core_FlexModuleFactory	
    	info	ModuleInfo	ModuleInfo (@4a611a1)	ModuleInfo	
    	loaded	Boolean	true	Boolean	
    	ready	Boolean	true	Boolean	
    	referenced	Boolean	true	Boolean	
    	setup	Boolean	true	Boolean	
    	url	String	"com/srcp/module/application/services/ApplicationServicesModule.swf"	String
    The URL is correct and by all appearances it is in memory. Using the * for casting didn't seem to make any difference. Let me explain in detail what I am doing and perhaps you can suggest of spot something that didn't leap out in my last post.

    I begin by placing 2 flashvars in my index.template.html file...

    Code:
                var flashvars = {};
                flashvars.contextURL = "context/files/application-context.xml";
                flashvars.serviceModulePath = "com/srcp/module/application/services/ApplicationServicesModule.swf";
    Note that the FB4 template uses a different means of passing variables than the Spring ActionScript docs, but I would throw some Adobe links at the audience instead of trying to keep up.

    Why did I do this? Because any Application created for running the test will have those variables, thus FlexUnitApplication.mxml (generated each time I add or subtract a test method) will act as my proxy application for testing flashvars. I have to use an imported script each time the file is regenerated because I have to use the preinitialize event to populate the flashvars into member variables. I tried all other means of doing this that I could think of, and in the end, I needed that html file and to catch the true preinitialize event.

    Can you think of any other way to emulate this behavior?

    Here is the Imported Script...

    Code:
    // ActionScript file
    // copy and paste the line below into FlexUnitApplcation s:Application Tag
    // preinitialize="application1_preinitializeHandler(event)"
    
    // Place the following lines in the FlexUnitApplication.mxml Script block
    // include "test/as3/applicationscriptimport/ApplicationTestRunnerImports.as"
    
    import mx.events.FlexEvent;
    
    [Bindable] public var contextURL:String = "";
    
    [Bindable] public var serviceModulePath:String = "";
    
    protected function application1_preinitializeHandler(event:FlexEvent):void
    {
    	this.contextURL = parameters['contextURL'];
    	this.serviceModulePath = parameters['serviceModulePath'];
    }
    The test looks like this...

    Code:
    /**
     * Some of these variables must be tied into the Test Runner Application as this is the only context
     * available.  There are import Scripts located in the test.as3.applicationscriptimport package. to help
     * with setup as the FlexUnitApplication is a generated application and you will either have to save it
     * off under another name, or connect the code blocks in at testing.
     *
     **/
    
    package test.as3.unit
    {
    	import com.srcp.view.main.Main;
    
    	import flash.events.Event;
    	import flash.system.ApplicationDomain;
    	import flash.utils.Dictionary;
    
    	import flexunit.framework.Assert;
    
    	import mx.core.FlexGlobals;
    	import mx.events.FlexEvent;
    	import mx.events.ModuleEvent;
    	import mx.modules.IModuleInfo;
    	import mx.modules.Module;
    	import mx.modules.ModuleManager;
    
    	import org.flexunit.asserts.assertEquals;
    	import org.flexunit.async.Async;
    	import org.springextensions.actionscript.context.support.FlexXMLApplicationContext;
    	import org.springextensions.actionscript.module.ISASModule;
    
    	import org.springextensions.actionscript.test.context.flexunit4.SpringFlexUnit4ClassRunner;
    
    	import spark.components.Application;
    
    	[RunWith("org.springextensions.actionscript.test.context.flexunit4.SpringFlexUnit4ClassRunner")]
    	[ContextConfiguration(locations="context/files/application-context.xml")]
    	public class ApplicationInitialization
    	{
    
    		private var application:Object = null;
    
    		private var _applicationContext:FlexXMLApplicationContext;
    
    		private var flashVarLocationPassed:String = "context/files/application-context.xml";
    
    		private var flashVarLocationFailed:String = "context/files/application-context";
    
    		private var _moduleInfoList:Dictionary = new Dictionary();
    
    		private var dummy:SpringFlexUnit4ClassRunner;
    
    		private var info:IModuleInfo = null;
    
    
    		public function ApplicationInitialization()
    		{
    			super();
    		}
    
    		[Before]
    		public function setUp():void
    		{
    			application = FlexGlobals.topLevelApplication;
    		}
    
    		[After]
    		public function tearDown():void
    		{
    		}
    
    		[BeforeClass]
    		public static function setUpBeforeClass():void
    		{
    		}
    
    		[AfterClass]
    		public static function tearDownAfterClass():void
    		{
    		}
    
    		/**
    		 * Creation Complete Event
    		 * Test that FlashVar Location is populated with Application context filename and path
    		 *
    		 * Test for proper string
    		 *
    		 **/
    
    		[Test]
    		public function testFlashVarLocationFailedResult():void
    		{
    			trace("In the flashVarLocationFailedResult");
    			var contextURL:String = application.contextURL;
    			Assert.assertEquals(flashVarLocationFailed, contextURL);
    		}
    
    		[Test]
    		public function testFlashVarLocationPassedResult():void
    		{
    			trace("In the flashVarLocationPassedResult");
    			var contextURL:String = application.contextURL;
    			Assert.assertEquals(flashVarLocationPassed, contextURL);
    		}
    
    		protected function handleTimeout(passThroughData:Object):void
    		{
    			Assert.fail("Timeout occured");
    		}
    
    		/**
    		 * Test 2:  Load Application Context File
    		 *
    		 * Test for I/O Error
    		 *
    		 * Register Listener for Load Complete and test for successful and unsuccessful Load Complete
    		 *
    		 **/
    		[Test(async, timeout="500")]
    		public function testLoadApplicationContextPassed():void
    		{
    			_applicationContext = new FlexXMLApplicationContext(application.contextURL);
    			_applicationContext.addEventListener(Event.COMPLETE, Async.asyncHandler(this, appContextCompleteHandler, 500, null, handleTimeout));
    			_applicationContext.load();
    		}
    
    
    		public function appContextCompleteHandler(event:Event, passThroughData:Object):void
    		{
    			_applicationContext.removeEventListener(Event.COMPLETE, Async.asyncHandler);
    			Assert.assertTrue(_applicationContext is FlexXMLApplicationContext);
    		/*			var info:IModuleInfo = ModuleManager.getModule(application.serviceModulePath);
    					_moduleInfoList[info] = true;
    					info.addEventListener(ModuleEvent.READY, Async.asyncHandler(this, handleModuleReady, 15000, null, handleTimeout));
    					info.addEventListener(ModuleEvent.ERROR, Async.asyncHandler(this, handleModuleError, 15000, null, handleTimeout));
    					info.load(new ApplicationDomain(ApplicationDomain.currentDomain));*/
    		}
    
    
    
    		/*		protected function handleModuleReady(event:ModuleEvent, passThroughData:Object):void
    				{
    					var info:IModuleInfo = event.module;
    					delete _moduleInfoList[info];
    					info.removeEventListener(ModuleEvent.READY, handleModuleReady);
    					info.removeEventListener(ModuleEvent.ERROR, handleModuleError);
    					var module:ISASModule = info.factory.create() as ISASModule;
    					module.applicationContext = _applicationContext;
    					(module as Module).data = info;
    				}*/
    
    		/**
    		 * Test 3:  Load Service Module
    		 *
    		 * Test for I/O Error
    		 *
    		 * Register Listener for Load Complete and test for successful and unsuccessful Load Complete
    		 *
    		 **/
    		[Test(async, timeout="500")]
    		public function testLoadServicesModulePassed():void
    		{
    			info = ModuleManager.getModule(application.serviceModulePath);
    			_moduleInfoList[info] = true;
    			info.addEventListener(ModuleEvent.READY, Async.asyncHandler(this, handleModuleReady, 500, null, handleTimeout));
    			info.addEventListener(ModuleEvent.ERROR, Async.asyncHandler(this, handleModuleError, 500, null, handleTimeout));
    			info.load(new ApplicationDomain(ApplicationDomain.currentDomain));
    		}
    
    
    		protected function handleModuleReady(event:ModuleEvent, passThroughData:Object):void
    		{
    			info = event.module;
    			//cleanupInfo(info);
    			//var module:ISASModule = info.factory.create() as ISASModule;
    
    			var module:* = info.factory.create(); //------------------------------------------- Problem code returns a null
    			//set the applicationContext property, inside the BasicSASModule this
    			//will automatically be set as the moduleApplicationContext's parent
    			module.applicationContext = _applicationContext;
    			(module as Module).data = info;
    		}
    
    		protected function handleModuleError(event:ModuleEvent, passThroughData:Object):void
    		{
    			Assert.fail("Module loading error");
    		}
    
    
    	/**
    	 * Test 4:  Load Default Framework Parameters
    	 *
    	 * Test for Collections existing
    	 *
    	 * Register Listener for Load Complete and test for successful and unsuccessful Load Complete
    	 *
    	 **/
    
    	}
    }


    Curtis
    Last edited by cdfisher; Dec 8th, 2010 at 10:44 PM.

  4. #4
    Join Date
    Oct 2007
    Posts
    17

    Default Module Code

    The tests all run and work, except where noted above. The module code is below...
    Code:
    package com.srcp.module.application.services
    {
    	import org.springextensions.actionscript.module.BasicSASModule;
    	import com.srcp.module.application.services.ApplicationServicesModule
    
    	/**
    	 * The application services module supplies six services related to the framework...
    	 *
    	 * 1. Application Initialization - Basic initialization parameters as specific name:value
    	 * pairs of properties used for initialization.
    	 *
    	 * 2. Logging System - To collect data for the Framework initialization and sets listeners
    	 * for Modules being Loaded to receive new logging target instructions.
    	 *
    	 * 3. Framework Manager - To setup an Error Supervisor or Listener so that Errors can be
    	 * caught, routed to the proper Locale Translation.  Load Name:Value Pairs & Resources
    	 * and populate the versioning object and begin the Operation of Loading Modules.
    	 *
    	 * 4. Module Management - Modules are loaded/unloaded with default Logging applied.
    	 * Memory/resources are passed to Logging as modules consume resources.  Module versioning
    	 * can load specific Modules according to the Business relationship defined by the UserID.
    	 *
    	 * 5. Security Services - The user is Authorized and Authenticated and can only load and interact
    	 * with modules they have access to, and perform Actions according to their role.
    	 *
    	 * 6. Personalization Services - User Modules are arranged and resized as a default layout
    	 * and they have the Burger King option to for the layout.
    	 *
    	 *
    	 **/
    
    	public final class ApplicationServicesModule extends BasicSASModule
    	{
    		public function ApplicationServicesModule()
    		{
    			super();
    		}
    
    	}
    }

  5. #5
    Join Date
    Dec 2008
    Location
    Brussels
    Posts
    407

    Default still weird

    Hey Curtis,

    juding from your stack trace, the fact that 'module' is of type ModuleInfoProxy still seems to indicate that the module hasn't been fully loaded yet.
    Is it possible for you to post a demo application of some sorts that demonstrates the problem? That way I'm sure I'll be able to track down what's going wrong.
    Your project seems pretty elaborate and the way you're trying to set things up seems to me like the right way to go. Therefore I'd really like to help you get on track here, if you're able to provide me with some source code I'll do my best to help you out.

    cheers,

    Roland

  6. #6
    Join Date
    Oct 2007
    Posts
    17

    Default Thanks for your generous offer of assistance

    I can send you a link to download the project. I need to send you email directly about this.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •