ColdFusion Unit Testing Frameworks

April 19, 2008

I am starting from scratch, putting in a unit testing framework, and working within the existing organization’s culture to introduce enough of the tool’s benefits without burdening the organization with too many of the downsides. Everything has a downside, a cost, or whatever you wish to call it. There is no free lunch.
The first steps were to gage the organization’s desire for the possible benefits of a unit testing framework, and their willingness to commit to moving forward, and accepting the cost. Having been in an “extreme” programming environment, which was only “extreme” in the sense that projects were “extremely” haphazard and “extremely” mismanaged, making sure that people are clear on what can be expected from implementing some test automation for unit testing and regression testing. Automated does not mean that you do nothing, and the machine does everything. It is difficult to know what people have been sold by the trade journals, and blogs, and common terms are often misappropriated.
The current environment is Flex/Actionscript and HTML, with a ColdFusion backend, with a ColdSpring framework. The goals are:
1) Automated testing with Ant, with performance metrics logged in a database, and pass/fail results e-mailed nightly to interested parties. (Thorough regression testing and reporting is key).
2) Eclipse Integration or reasonably nice Unit Runner, with easy ability to select individual tests, or test suites. (Easy sell to the engineers is key)
3) Mock Objects, automated test generation, anything to minimize the time impact on engineering, while maximizing the benefit, and keeping the program moving.

Sean Corfield had mentioned MXUnit fairly recently, so it seemed worth a look. Given the higher volume of activity on MXUnit, when compared to CFCUnit and CFUnit, it seemed like a reasonable way to go, for the best of all worlds for future itegrated add-ons. The first downside I will mention is that *MXUnit‘s Eclipse Integration is Not Flex Builder 2.01 Compatible, or rather, not compatible with the version of Eclipse (3.11) that ships with Flex Builder 2.01*  This wasn’t super clear from the  MXUnit website, so it’s possible for an engineer to go through the installation instructions, and end up with a failing plug in.  This might not be a problem for some organizations, but may be for others.  Most of the team has not yet upgraded to FB 3, so it could be an issue at the moment.

  MXUnit’s Eclipse integration isn’t quite finished, or at least that’s how it felt for me.  It “worked”, but was lacking a few things that I thought were important.  An html or Flex based unit runner will do the trick though, so it’s not a huge problem.  The things which make the integrated unit runner a little less than usable, for me, are: 1) It seems to have no memory of past tests, so I would have to go through the selection process for the unit test every time; some way to save the available test cases/test suites would be desireable/required, 2) The test case selection process was awkward; I found myself unable to select a Test Case which I knew was present on more than one occasion;  This could be forgiven more easily, if it would remember the test cases I had selected in the past, but I was required to select/find the test case with each restart of Eclipse, or any time I wanted to switch tests

On the plus side, the ant unit runner does a great job, and it is clear how to modify the ant task.  The availability of the different test result formats, allows me to feed the results into a variety of destinations with ease.  The key item was logging test results and performance metrics, and not just logging into a text file, but logging into a database table, so it could be consulted for history.  I was able to hack this item in really easily using the cfquery output format for the testResults.

I should at least mention that CFUnit and CFCUnit are both seemingly capable frameworks.  I was able to set up integrated Eclipse (with Flex Builder 2.01!) unit tests, and test suites.  But the availability of the test Result Formats, and the volume of project activity, were enough to convince me.  That does not mean that I am right, nor does it mean it is the best choice for everyone.  But the software selection is but one small piece of the puzzlement.

ColdFusion Unit Testing Frameworks, and related info:

Next steps, automating test generation, designing effective unit tests, and Flex Unit testing frameworks.  I’ll post if anything interesting comes up.

 

Advertisements

Degrafa – Flex Framework for Visual Elements

July 23, 2007

  When Flex was first introduced, there was, most prevalent, Cairngorm and Arp as support frameworks (Flex *is* a framework, don’t forget).  Both emphasized the data connection element, which was the biggest problem with Flash Remoting, so it makes a lot of sense.  Today, however, we are seeing a real need for the extension of some of that kind of methodology for the designer/graphics side of things.

  The Degrapha framework (http://www.degrafa.com/) promises to help ease some of the pain, or close the divide between the designer and the developer.  Called a “Declarative Graphics Framework” by its designers, Jason Hawryluk and Juan Sanchez, it provides support for re-use and extensibility on the graphics and visual side of the Flex development milieu.

  I took a moment this week to catch up on the Gausax framework developments (http://ablesa.wordpress.com/), and Angel Blesa has done quite a bit of good work there.  Check out the comparison of implementations of the Flex Store using no framework, Cairngorm, and then Gausax.  This treatment helps to easily see the difference.  The simplification of frameworks is what developers want, in order to remain Agile. 

  None of these is a case of replacing one thing with another.  There are benefits and strengths shown by each.  It is always a case of matching the solution with the problem, taking into account the complete context of the project at hand, customer requirements and the available resources. 


Value Object Bustifiers

July 2, 2007

  I’ve been fashioning Brian Renaldi’s the <a href=”https://howardscholz.wordpress.com/wp-admin/code.google.com/p/cfcgenerator/&#8221; target=”_blank”>Illudium PU-36 Code Generator</a>  package to produce scaffolding for the Cairngorm framework.

People tend to have opinions about code generation, scaffolding being a euphemism for a specific portion of code generation.  I really like the dynamic scaffolding employed by Groovy/Grails and Ruby/Rails, wherin the functionality of the scaffolding is generated, but the code is not.  That seems pretty cool.  It would be Uber Cool to generate the entire application that way, and have no code except for that very special case stuff.  But even generated scaffolding serves its purpose, and helps a group development effort have some consistency.
Typically, what I do in my VO’s is have them accept a parameter that is of type object, and let the constructor act as a sort of copy constructor, if it is fed an object, otherwise leaving the default values.
A further item that is handy in scaffolding, is making the assignment case insensitive.  Coldfusion is case insenstive, and Actionscript, is case sensitive.  So those assignments can be troublespots sometimes.  Also, sometimes there may be a mismatch between the VO properties and the properties returned from the persistent store, so any mismatches are observed and traced to the console output.

To handle these items, I’ve added the following:

/**
* Default constructor.
*/
public function CategoryVO(data : Object = null) : void {
if (data == null) return;
var dataDesc:Object = ObjectUtil.getClassInfo(data);
var myDesc:Object = ObjectUtil.getClassInfo(this);
var props:Array = dataDesc.properties;
var myProps:Array = myDesc.properties;
var found:Boolean = false;
for each (var name:String in props) {
found = false;
for each (var myName:String in myProps) {
if (!found &amp;&amp; myName.toUpperCase() == name.toUpperCase() ) {
this[myName.toUpperCase()] = data[name.toUpperCase()];
found = true;
break;
}
}
if (!found)
trace("CategoryVO - Input Object has extra property " + name);
}

The business delegate layer I’ve seen done in a pretty boilerplate manner, where it acts as kind of a pass through layer to the Commands.  More correctly, any data conversion that may be platform specific, like Coldfusion or PHP related Object constructs, should be handled in the business delegate layer, isolating the platform details from the remainder of the Actionscript code.  That makes this layer a little more interesting for matters of code generation.


Handling Results in Flex from RemoteObject calls in ColdFusion

July 2, 2007

I’m putting together a music library for a client, and I thought I’d take the opportunity to measure the return results from ColdFusion in various forms, and see how they appear in Flex:

1) Calling the songService.cfc to get a list of songs as and ArrayCollection of SongVO So, in the ModelLocator.as, the songList is declared as:

[ArrayElementType("SongVO")]public var songList:ArrayCollection = new ArrayCollection();

The SongVO is tied to the cfc with a meta tag like this:

package com.musiclib.fx.vo
  {
      import flash.events.EventDispatcher;
      [RemoteClass(alias="com.musiclib.db.Song")]
	  [Bindable]         
         public class SongVO extends EventDispatcher         
         {         
         public var song_id:Number = 0;         
         public var owner_id:Number = 0;         
         public var category_id:Number = 0;         
        <snip>        

Finally, the value is returned from the cfc as the ColdFusion equivalent of the AS class. In this case, I am calling getSongList(). In order to type all of the rows, each query result row must be cast into the coldfusion component type. So, when we receive the result, we get:

Charles network capture of result In the debugger, we see the modelLocator songList as null or Empty. Time to reach into the bag of tricks

debugger view of cfc call result

A quick look in the Flex manual tells me:

“Handling service resultsAfter an RPC component calls a service, the data that the service returns is placed in a lastResult object. By default, the resultFormat property value of HTTPService components and WebService component operations is object, and the data that is returned is represented as a simple tree of ActionScript objects. Flex interprets the XML data that a web service or HTTP service returns to appropriately represent base types, such as String, Number, Boolean, and Date. To work with strongly typed objects, you must populate those objects using the object tree that Flex creates.WebService and HTTPService components both return anonymous Objects and Arrays that are complex types. If makeObjectsBindable is true, which it is by default, Objects are wrapped in mx.utils.ObjectProxy instances and Arrays are wrapped in mx.collections.ArrayCollection instances.

NOTE Macromedia ColdFusion is case insensitive, so it internally uppercases all of its data. Keep this in mind when consuming a ColdFusion web service.

But, returning to a previous post, I pull this code, and plop it in:

 var result:Array = resultEvent.result as Array; 

    for (var i:String in result) 

    { 

result[i] = new ObjectProxy(result[i]); 

} 

    ModelLocator.getInstance().myArray = result as ArrayCollection; 

Well, that didn’t help one bit. I have the same results.

Now, if I return a query, directly from the cfc, and assign what comes back directly to the target arrayCollection songList, then everything works just fine.


MVC Framework for AS3

June 27, 2007

The Cairngorm framework has proven exception in providing a simple, lightweight methodology for Flex development, but its strength rested on application to database communications. Intense visual development was left without much support, or overuse of the Singleton ModelLocator, creation of ViewManagers and other constucts. PureMVC Diagram

I have been reading up on this framework, Pure MVC, which looks like it offers a complementary approach to Cairngorm for Flex/AS3 development. It’s possible elements of this could be adapted for use in Cairngorm framework implementations, and vice versa, but I’ll need to try it on its own first, and see. It’s definitely worth a look: http://www.puremvc.org


Object Proxy (cont)

June 8, 2007

I ran across the topic again, and again this week, and I haven’t even been working in Flex.  It’s been all Java this week.  I was cruising through the blogs of the European Union, and found this comment:

“Yep already… I fixed the annoying “Lazy Loading”-issue. I found a little hack and it goes something this:

  1. Store openDuration and closeDuration;
  2. Set openDuration and closeDuration to 0;
  3. Call open and close methods;
  4. Restore openDuration and closeDuration;
  5. TADA… lazy loading be gone….. “

http://labs.flexcoders.nl/?cat=3

Is it possible that the standard use of Delayed Instantiation of Objects, is emerging as an Anti-Pattern, as programmers worldwide come up with various solutions and workarounds to make the objects behave as procedural Objects would?

And at the same time, other programmers are adding additional Proxy wrappers, to achieve the effect they need.  Utilizing the Double Proxy Pattern, the first access to the object would release the inner proxy, and fire off a request to fill in the proxy with “real” data.  Hopefully, by the next time the object is accessed, it will be populated.  This is related to the re-wrapping with ObjectProxy which I have seen.

——

  Earler this week, a colleague was putting together a dashboard application view, and had a coldfusion remote service all wired up in ColdSpring, and was at the point of getting the data back in the ResultEvent of the Service Delegate, and was getting strange results.  The ResultEvent.result was an ObjectProxy, or nothing.  He was not getting a list of data for his view to bind to.  He was returning an array of some type, but the remote object declared it was returning type “any”.  Well, when we fired up Charles, and looked at the AMF result coming from the Coldfusion server, the type was a custom coldfusion recordset.  So, he changed the declaration of the return type to “Array”, and lo and behold, while observing in Charles, we saw that the  AMF return type was ArrayCollection.  And the rest of his code worked, and the dashboard element filled up, because the data was in a format that Flex recognized.  I don’t know exactly what this tells me, except that the return type declaration in Coldfusion is important.  As is the RemoteObject type meta tag in the Flex Value Object declaration.

  He did not try another test, wrapping the result in ObjectProxy to see if that would have taken care of the problem.  I don’t know that it would *solve* it, but it would probably yield different results.

  And then I am reminded of this post:

“Accessing proxied object

Under some circumstances Flex wraps object with special mx.utils.ObjectProxy wrapper class. Documentation describes special object_proxy “object” property containing reference to real object. But accessing this property at runtime always returns “null”, althought this property is visible in debuger watch window with “package” icon. Code below demonstrates the problem, and shows “Real object: null” message:

 import mx.utils.ObjectProxy;
 import mx.controls.Alert;
 …
 var o1:Object = { f1:”aaa”, f2:123 };
 var o2:Object = new ObjectProxy(o1);
 var o3:Object = ObjectProxy(o2).object;
 Alert.show(“Real object: “+o3);
Matt Chotin pointed me to the solution. It’s special namespaced property and need in special code handling. So updated example listed below:

 import mx.utils.ObjectProxy;
 import mx.utils.object_proxy;
 import mx.controls.Alert;
 …
 var o1:Object = { f1:”aaa”, f2:123 };
 var o2:Object = new ObjectProxy(o1);
 var o3:Object = ObjectProxy(o2).object_proxy::object;
 Alert.show(“Real object: “+o3);”

from http://www.docsultant.com/site2/articles/flex_internals.html

(to be continued)


When to Use ColdSpring: one example

June 4, 2007

  I have conversations with people I work with, regarding the pros and cons of employing a framework like Coldspring.  Well, ColdSpring in particular, actually.  While explanations of its benefits have been present, there has lacked a concrete example that I could share with with my coworkers and comrades.  The benefits realized from loose coupling of objects have been demonstrated, and ColdSpring is a way of moving toward that end, but that is fairly abstract.  Also, as trends in OOP have moved away from inheritance and have leaned toward composition, the process of decorating or injecting the objects in this model, is also worthy as part of a prevalent approach, but it remains too abstract.  The notion of logging, or security, or changing the DSN does not get people too excited about putting ColdSpring into place.  Instead, Coldspring could be the source of a whole new batch of problems without even giving any benefits in return.  And the notion that everyone is doing it, brings requests for a new glass of Kool-Aid. 

A ColdSpring Example Transaction  A real example that can be seen by our organization comes with the wave of demand for Dashboard enabled applications with analytics, and metrics that could never be satisfied.  (I will lay aside for this writing, my thoughts and concerns on Dashboards, and the dangers of their overuse).  So, in this perhaps hypothetical situation, we have a customer who uses our eCommerce application, and decides that he wants some real time metrics, of things which do not neatly fall into one table or another, and might require some data consolidation, or something, to pull what he wants to see.  Let’s say he wants to know what aisle of the store people spend the most time in (category), and of those, how many buy product.  For people that hang out in category A, how often are their carts abandoned.  Do people get lost in aisle A?  Questions like that bubble through the storeowner’s head, and he pictures a dashboard, with a realtime visualization as solving the problem.  Now, it could have been anything.  We don’t track which aisle people are in, only what they put in their basket.  And we don’t pair that with the cross sells.  How can we get the data that he wants without making huge changes?

   The important thing to note is this:  The huge changes that need to be made to facilitate this customer’s desires do *not* benefit the shopping workflow at all.  They are a separate concern.  A possible solution, with ColdSpring, would be to introduce an AfterAdvice, which would feed the desired data into a log, which would be fed to the dashboard, and so on.  So, this could be done without any major impact on the workflow code itself.  This is huge.  This could have made the shopping cart code just a little bit more complicated.  Instead, it has left it alone.

  In some ways, having programming in database scripts, Oracle PL/SQL procedures and triggers, this dependency injection is not so different.  It is just happening at a different layer in the process.  In fact, I had thought of using database triggers, at first.  It took a little while to realize that this would be a decent situation for using ColdSpring, and realizing some tangible benefit from it.

  Now, with a concrete example in front of me, I can think of another situation, which again, could have been dealt with using database triggers, that could benefit from this architecture.  Stepping back, I think that will continue to be the case.  The immediate solution that jumps out in response to the problems that ColdSpring addresses could often be taken care of with the application.cfc (security), or by the RDMS (logging).  Caching goes in the middle there somewhere, in certain situations, but even that for some situations, has solutions easily employed at different layers.  So, part of the difficulty is beyond the abstraction, and in the realm of problems which we have already solved in one way or another.  And while that may be so, as customer demands shift, we must at least be prepared to shift our strategies and solutions to problems.