Flex Developer’s Journal: Functional testing of Flex RIA with FlexMonkey 4

Posted in Stu Stern on May 25th, 2010 by Stu Stern

Stu Stern originally posted this on Big Gorilla - Stu Stern's Blog.

I was recently interviewed by Yakov Fain, editor of Flex Developer's Journal. You can check it out here.

Performance Improvements for DAO Testing in an ORM environment

Posted in Bob Hedlund on May 20th, 2010 by admin

admin originally posted this on Eldorado Software.

In any good size project using an ORM tool such as Hibernate, you are bound to have a good number of DAO classes that encapsulate persistent interactions. Running JUnit tests against your DAO's can take some time with ANT, as a new Session Factory is instantiated for each Unit Test. In a current project the time to run the tests in our DAO package was about three minutes. I found a solution that cut the time to run all the tests down to 40 seconds. The solution : Junit TestsSuite.

The TestSuite instantiates the SessionFactory once, and all the tests reuse the instance. The code:

public class DaoTestSuite extends TestCase{

public static Test suite(){
TestSuite suite = new TestSuite();
suite.addTestSuite(DaoTest1.class);
suite.addTestSuite(DaoTest2.class);

// and so on ... or you could do this reflectively

suite.addTestSuite(DaoTestN.class);


TestSetup wrapper = new TestSetup(suite){
protected DbUtil dbUtil = new DbUtil();

@Override
protected void setUp(){
//Before the suite, we configure the factory
dbUtil.beginConversationThread();
}


@Override
protected void tearDown(){
//After the suite, we ensure the factory is closed
dbUtil.rollbackTransaction();
}
};

return wrapper;
}



The DbUtil class is a standard ORM class that configures the SessionFactory, ensures that a session is open, transaction is active, and provides a means to rollback the transaction.

The Test classes that are added to the suite have the following before and after methods:

protected DbUtil _dbUtil = new DbUtil();


public void setUp() {
_dbUtil.beginConversationThread();
}


public void tearDown() {
_dbUtil.rollbackTransaction();
}


Where the beginConversationThread() call grabs an active session from the factory, or starts the factory if it is not yet configured and running. Since the TestSuite is run in one JVM, the SessionFactory is configured but once.

Metrics and the AIR Install Badge

Posted in FlexMonkey, Justin Shacklette on May 19th, 2010 by admin

admin originally posted this on Saturnboy.

The AIR Install Badge is a very handy little flash application for delivering AIR applications to your users via the web. The badge allows your users to download and install both your application and the Adobe AIR runtime. Additionally, the install badge will automatically prompt users to upgrade if a previously installed version is detected. At Gorilla Logic, we use the AIR Install Badge on the FlexMonkey download page (free registration required).

Alas, flash is opaque to analytics. We have no idea what our users are doing inside the AIR Install Badge application. Are they installing? Or upgrading? No problem, we just need to write some code…

The Code

Using flash’s ExternalInterface, we can manually push the data out of flash and into javascript. Once we have the data in javascript, we have total control. One option is to use google analytics to store our badge data. In the case of FlexMonkey, we send the badge data along with the user’s credentials to our CRM platform, SalesForce.com.

Step 1: First, open AIRInstallBadge.as and add this to the top:

import flash.external.ExternalInterface;

Step 2: Next, add the ExternalInterface call to the top of the handleActinClick() function in AIRInstallBadge.as:

protected function handleActionClick(evt:MouseEvent):void {
    if (action == 'install' || action == 'upgrade') {
        //send data to js
        ExternalInterface.call('badgeJS',action);
    }
    ...
}

Since I only care about the install or upgrade actions, I’ll only send those out to javascript. Re-compile the badge and deploy.

Step 3: Last, add the badgeJS() javascript callback to the page containing the badge and do whatever you want with the incoming badge data:

function badgeJS(action) {
    //do metrics here...
    alert('badge action=' + action);
}

Conclusion

With an hour of effort, and a very small amount of code, we’ve managed to get the useful metrics of installs and upgrades out of the AIR Install Badge and into our analytics engine of choice. A job well done.

Walking Into The Wrong Bathroom: Lack of Affordances

Posted in Dave Rodenbaugh on May 19th, 2010 by admin

admin originally posted this on Lessons of Failure.

Jakob Nielsen recently published his report on iPad’s usability and application interface consistency.  To no one’s surprise, he discovered a few issues.

What was the main problem Jakob uncovered?  Many iPad applications aren’t obvious to use:  non standard controls, confusing graphics, and counter-intuitive metaphors.  In psychology parlance, it’s because these apps lack constraints and affordances.

Constraints and affordances are nothing new, even in the real world.  You encounter them every day, but you’re only barely aware of them most of the time.  Joseph Hallinan has a great example in “Why We Make Mistakes”:

“One way to reduce errors is by introducing constraints.  Constraints are essentially simple mental aids that keep us on the right track by limiting our alternatives.  Try repeating the Star Spangled Banner if you’re American without singing it.  How much can you remember?  Now let yourself sing it.  I’ll bet you get most, if not all, of the song.  That’s a constraint against forgetting the song because that’s the only way you’ve ever learned it.

Another way to reduce errors is to use affordances.  If constraints tell us what we can’t do, affordances indicate what something can do.  Affordances may appear in many forms:  texture, shape, or size may indicate usage.  For example, a ball’s shape affords bouncing or throwing.  A knob affords turning.  Slots afford the insertion of things.  When we encounter some basic object, affordances help us answer basic questions like, “How does this work?” and “What is this used for”

An everyday affordance you’re familiar with is the pull-handle on a door.  Just by looking at it, you can immediately tell that you’re supposed to grasp on to it and pull the door open.  The opposite affordance would be the push-pad on a door, where there’s nothing to grab, only a metal surface against which to exert force as you pass through it.  Sometimes constraints are added on top of this, such as “Exit” signs on the door you use to go out as well.  These are all the clues we get on how to use a door, but you’re rarely thinking to yourself, “Oh, there’s a PULL handle, I should PULL on it.”  Affordances are subtle, important cues on how to interact with things.

Those cues can go awry.  For example, building architects foul it up occasionally by putting pull handles on the push side of doors.  Or put the “Exit” sign on the “Enter” side with an arrow pointing to the other door.  These confuse us, make us hesitate, and often force us to enjoy the embarrassment of pulling on the door you’re supposed to push (a personal favorite of mine).  Sometimes they’re done on purpose, like at a famous bar I went to in college that has two doors side by side each a large arrow pointing to the other door and a gender.

Courtesy of ldanderson, Flickr

Um, which door?

They are intentionally mislabeled so women walk into the men’s restroom and vice-versa, much to the delight of the inebriated patrons.  While that sort of bad affordance was humorous in college, it’s patently frustrating to encounter when I’m struggling with a new app on the iPhone.

This lack of affordances is why the iPad and iPhone can be so bloody hard to figure out sometimes.  We have no hints–no obvious clues what to do with things mostly because the metaphors are new and the controls are often non-standard.  Consider this interface below, heavily laden with nothing but custom graphics in the UI.  Can you tell which items allow you to interact with them, and which are merely display artifacts?

Yes, I’m confused too.  And to add to the confusion, these devices allow actions we couldn’t possibly take on the desktop, like the accelerometer.  How do you give an affordance for that?  Or the shaking action?  We aren’t used to these metaphors yet, so the affordance isn’t quite obvious.

A Clear iPad Actionable UI

Contrast that with this one from the iPad, where the actions you can take are fairly clear from the interface.  (Courtesy of LandingPad.org).  Without knowing what the app is all about, you can already tell (if you’ve used touch interfaces, particularly iPhone) what you can touch, what will likely result in an action, and what items are just eye candy.

There are even more great examples on that site, I encourage you to check them out.

User interface design is hard.  Punting to a graphic designer sounds like a good idea, but consider that the difference between adequate and excellent on a user interface isn’t subtle or small.  It’s the difference between usable and frustrating.  The difference between good and beautiful.  And maybe even the difference between viral and doomed to obscurity in the App Store’s bargain bin.  Make sure you don’t just create pretty graphics, put the time in to make a pretty AND usable UI.

Don’t let your users walk into the wrong gender bathroom in your applications:  use affordances to make your UI obvious and intuitive.

No related posts.

FlexMonkium: Get ready for the 119th element!

Posted in Stu Stern on May 15th, 2010 by Stu Stern

Stu Stern originally posted this on Big Gorilla - Stu Stern's Blog.

FlexMonkium, the Selenium Plugin that adds FlexMonkey recording and playback to Selenium-IDE and Selenium-RC, is undergoing final testing and packaging in preparation for its forthcoming release.

In this pair of videos smuggled from Gorilla Logic labs, deep beneath the surface of the Earth, we see FlexMonkium interleaving Flex with HTML recording and playback, and generated JUnit test scripts being run with Selenium-RC.



Separating Drag-and-Drop from View components

Posted in Glen Whitbeck on May 12th, 2010 by admin

I was recently working on a set of view classes that, among other things, implemented custom drag-and-drop behavior. As we all know, Drag-and-drop requires several different event handlers for the various drag events (DRAG_START, DRAG_ENTER, etc.). Adding these event handlers to your view class adds a lot of bulk to the existing view logic.

In addition to the issues that are directly related to the sheer size of the class, including drag-and-drop logic in a view can often be considered a 2nd responsibility of the view. I often find that, when I’m working on a view that contains drag-and-drop behavior, I’m typically doing one of two things:

  1. Working on the view (look-and-feel, data set-up, gathering results after user interaction, etc.).
  2. Working on the drag-and-drop behavior.

Thus, if I am working on the view, all of the drag-and-drop logic is excess clutter in my way (and vice versa).

This should actually be an immediate red flag. Good coding practice suggests that a class should have a single responsibility. The Single Responsibility Principle, a term coined by Uncle Bob, correlates a “responsibility” with “a reason to change”. In other words, a class should have only one reason to change. In this example, there are two reasons that I might change the view. Therefore, one of the reasons-for-change should be refactored out of this class. It seems silly to refactor the view out of the view class. So, my approach was to move the drag-and-drop functionality into its own class.

There are probably a number of ways to structure the association between the view and the class containing the drag-and-drop functionality. However, one simple method is to inject the view component into the drag-and-drop class. This will allow the drag-and-drop class to register for the drag events emitted by the view. To limit coupling, the injected reference can be typed as a generic UIComponent (to have access to the drag events).

private var viewComponent:UIComponent;

public function DragAndDropFunctionality(component:UIComponent) {
	viewComponent = component;
	viewComponent.addEventListener(DragEvent.DRAG_ENTER, onDragEnter, false, 0, true);
	viewComponent.addEventListener(DragEvent.DRAG_EXIT, onDragExit, false, 0, true);
	viewComponent.addEventListener(DragEvent.DRAG_DROP, onDragDrop, false, 0, true);
}

Some events, such as DRAG_DROP will require the view to take action (add the dropped item to the appropriate place). Again, we want to limit coupling in our communication. The standard technique to maintain separation is for the lower-level component (the drag-and-drop class, in this case) to dispatch events. Then, the higher-level component (the view, in this case) can listen for those events and take the appropriate action.

Once this separation is achieved, we will have classes that have (hopefully) a single responsibility. When you need to work on the drag-and-drop logic, you can go directly to the drag-and-drop class. I find it much easier to follow the drag-and-drop logic without the view code cluttering the class. Similarly, the view component is no longer cluttered with all of the drag-and-drop event handlers. The classes are smaller and more obvious. And, the two “responsibilities” can now be worked on by multiple developers without lock conflicts or merging, to boot.

Flex 4 Support Now Available From FlexMonkey / Gorilla Logic

Posted in FlexMonkey on May 11th, 2010 by jonr

jonr originally posted this on FlexMonkey :: Flex UI Testing Tool.

Latest Version of Open-Source Testing Tool for Flex Applications Delivers Full Flex 4.0 Spark Component Support

Broomfield, CO – May 11th, 2010 – Gorilla Logic, an enterprise IT consulting services firm known for its top consulting talent, today announced the availability of FlexMonkeyTM 4.0 Beta 1. The new version provides support for the latest Flex 4 release from Adobe, including the entire Spark component set. With over 6,200 registered users, FlexMonkey has become the industry standard for automated record and playback testing of Adobe Flex interfaces used by companies around the world.

“The FlexMonkey 4.0 Beta 1 release delivers what our users have been asking for: support for Flex 4 including all Spark components. This lets FlexMonkey continue to answer to the Flex community’s need for quality assurance and unit testing for Flex applications,” said Eric Owens, FlexMonkey Guru, Gorilla Logic.

As a leading consulting services firm specializing in enterprise application development using Adobe Flex, HTML5, Java and mobile application development, Gorilla Logic developed FlexMonkey to deliver unparalleled quality to their Fortune 500 clients. In addition to providing a forum for the community of FlexMonkey users to assist each other (FlexMonkey Forum), Gorilla Logic also provides annual support contracts, implementation services and custom enhancement development for clients interested in optimizing their implementation of FlexMonkey.

“We use a continuous integration environment and are deploying FlexMonkey on the desktops of nearly 150 developers. For us, FlexMonkey is an option that cannot be ignored because it was obviously developed with one goal in mind – to facilitate the creation of high-quality Flex applications,” said Josse Brayelle, MAAF Assurances.

FlexMonkey is well suited for use by both developers and QA testers. It provides for regression and functional testing, and can be run from popular build systems and continuous integration environments, like CruiseControl. Gorilla Logic has assisted several companies in setting up their continuous integration environments and ensuring a production quality implementation of FlexMonkey.

In response to FlexMonkey’s value and ease-of use, Jokichi Oguri from HP commented, “The work you guys have done is incredible. May Gorillas rule the earth some day!”

FlexMonkey 4.0 Beta 1 is available today at www.gorillalogic.com/flexmonkey. Gorilla Logic also offers complete FlexMonkey training, implementation and off-shore testing services.

About Gorilla Logic

Gorilla Logic is an enterprise application development services and consulting firm known industry-wide for providing “gorilla” consultants that can dramatically improve development team productivity. Gorilla Logic has long demonstrated their industry-leading expertise in enterprise Java / JEE development, Adobe Flex / RIA development, and mobile device
application development, including the iPhone, Android and Blackberry. Gorilla Logic has been engaged to ensure the success of their most mission critical projects by Fortune 500 companies as well as small and medium-sized businesses and startups in industries ranging from financial services to entertainment to aerospace and the government sector.

Gorilla Logic also develops open source tools for Java, Flex, and iPhone developers.

For more information about Gorilla Logic, please visit www.gorillalogic.com or email info@gorillalogic.com.

Gorilla Logic Media Contact
Chad Sanderson
303.974.7088 ext. 7002
chad.sanderson@gorillalogic.com

Perfect Gradients for Perfect Buttons

Posted in Justin Shacklette on May 10th, 2010 by admin

admin originally posted this on Saturnboy.

Photoshop does this annoying thing where purely vertical gradients have some horizontal variation. Yes, it’s usually only plus or minus one bit of color, but it offends! I’ve battled Photoshop for a while on this, but I just can’t seem to get exactly what I want out of it. So to make a perfect gradient, I decided to write some code. The requirements are simple: given a starting color and a set of deltas, output a perfect gradient.

Here are some quick examples:

1
gradient1
2
gradient2
3
gradient3
#000000
4, 1, 0.25
#eeeeff
-2.2, -1, -0.3
#ff0099
-1, 0, 1
 

If we zoom in on example #1, which starts with black (#000000) and has deltas of 4, 1, 0.25, we see the following:

zoomed gradient
 

The diagram shows the first ten rows of the gradient. The delta values are accumulated with each row, and only the whole part of the resulting color value is used (aka I take the floor of each color bit). So in this example, using the fractional delta of 0.25 results in exactly one additional blue bit every four rows. Ahhh, perfect!

The Code

No need to use some fancy new language, I wrote a simple PHP program to handle commandline input and output a perfect PNG gradient. The interesting part is the function that generates and saves the gradient:

function build_image($filename, $w, $h, $color, $delta) {
  $img = imagecreatetruecolor($w, $h);
 
  $c = imagecolorallocate($img, $color[0], $color[1], $color[2]);
  $d = $delta;
 
  for ($y = 0; $y < $h; $y++) {
    imagefilledrectangle($img, 0, $y, $w - 1, $y + 1, $c);
 
    $c = imagecolorallocate($img,
      clamp(floor($color[0] + $d[0])),
      clamp(floor($color[1] + $d[1])),
      clamp(floor($color[2] + $d[2]))
    );
 
    $d = array($d[0] + $delta[0], $d[1] + $delta[1], $d[2] + $delta[2]);
  }
 
  imagepng($img, $filename);
  imagedestroy($img);
}

The code is straight forward. First, create the image via imagecreatetruecolor(). Then, starting with the starting color, draw a one pixel tall rectangle for each row of the image. The next row’s color is computed in each iteration by adding the accumulated delta to the starting color. Finally, output the image as a PNG via imagepng() and free the memory. The complete php source can be downloaded here.

Button Time

Once we have our perfect gradient engine in place, it’s time to make some perfect buttons. To achieve the standard glass button look-and-feel, I typically fuse two gradients together: light on the top, dark on the bottom.

Here are the two halves of a pretty red button, along with their starting color and deltas:

TOP
BOTTOM
top
bottom
#ff8080
-3,-3,-3
#d23c3c
-3,-3,-3
 

And the two commandline invocations of gradient.php to create the gradients:

php gradient.php 100x16 ff8080 -3,-3,-3 top.png
php gradient.php 100x16 d23c3c -3,-3,-3 bottom.png

If I want my buttons to be sexy, rounded corners are a must. My favorite photoshop trick to create multiple rounded buttons is to use a rounded alpha-transparent button with each gradient as a clipping mask. Using a clipping mask is a simple way to guarantee button geometry remains fixed while colors are changed.

Here is the layers pane showing the two gradients fused together and used as a clipping mask for the rounded alpha-transparent button:

clip mask
 

The result is a horizontally stretchable gradient button, that doesn’t look half bad. See for yourself:

button
 

Custom UIButton

The final button asset can be used as desired, but here is a simple Objective-C example since I’ve been in iPhone world lately:

UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setFrame:CGRectMake(20, 20, 140, 32)];
[btn setBackgroundImage:[[UIImage imageNamed:@"btn-red.png"]
      stretchableImageWithLeftCapWidth:10.0
      topCapHeight:0.0] forState:UIControlStateNormal];
[btn setTitle:@"BUTTON" forState:UIControlStateNormal];
[btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[btn.titleLabel setFont:[UIFont boldSystemFontOfSize:14]];

Create a new UIButton of type UIButtonTypeCustom and then set the button skin as the backgroundImage. The horizontal stretchability is due to the stretchableImageWithLeftCapWidth and topCapHeight.

Here is a screenshot from the iPhone simulator showing the button in action:

screenshot
 
Files
  • gradient.php – the perfect gradient engine
  • gradient-button.psd – the photoshop source for the red button image, including the rounded alpha-transparent button and fused red gradients
  • btn-red.png – the red button image

Schizophrenic Following

Posted in Justin Shacklette on May 5th, 2010 by admin

admin originally posted this on Saturnboy.

This post is a follow-up to my previous post, The Schizophrenic Programmer. I must have struck a chord, because I got a ton of fantastic feedback not just on this blog, but also on Reddit and DZone.

After further reflection, I still agree with what I said and my conclusions. Moving forward, I plan to learn fewer languages and less syntax. My daily pain is that too much of my knowledge is too tightly bound to the implementation details, and when I switch languages I can’t bring my solutions to bear. It sucks, and it makes me feel stupid. So the simple fix is to put my energy into learning more unbound concepts (like my soft skills of speaking and writing) and more easily transferable concepts (like APIs).

Analytics

google-analytics

I had a huge bump in traffic mostly due to Reddit and DZone that basically crushed my regular traffic down into the noise. My poor slice at Slicehost was taking a beating, so I quickly installed the Hyper Cache plugin. It’s dead simple and it really works. On Sunday morning, my load went from 0.2 to 0.02 instantly.

I also tracked my twitter analytics via bit.ly. As a side note, you can just put a plus “+” at the end of any bit.ly url to see it’s analytics. So, since the original post was shortened to http://bit.ly/cR6cnY, the analytics are available here: http://bit.ly/cR6cnY+.

Commentary

Lots of stuff was said, but I just wanted to touch on some of the key points.

  1. I feel your pain – thanks. I find it comforting to know I’m not alone.
  2. definition of schizophrenia – a couple of comments mentioned that my post had nothing to do with schizophrenia. First, I suggest you look it up: “contradictory or antagonistic qualities or attitudes”. My Erland knowledge is definitely in opposition with my Java, which is in opposition with my Actionscript, etc. If you don’t have this problem, good on you. Second, there’s thing called artistic license and if you are a writer you get to use it. I picked a sensational word for a reason. I welcome criticism of the choice, but it’s silly to take umbrage with its validity.
  3. short sighted – my plan was called out as short sighted a couple of times. I tend to think of life and plans like this… There are three choices when it comes to plans. First, you can have no plan, and just drift along. Sometimes you get smashed into the rocks, and other times you wash up on a tropical paradise with beer, virgins, and fiber broadband. Second, you can have a short term plan that gets revisited and revised as things change. Third, you can have a short term plan, but be so unbelievably naive that you think it is actually some awesome long term plan. Life is agile. All plans are short term.
  4. embrace and extend – a few people said don’t fight it and embrace the insanity. I really lust after new stuff, so it was easy to try to the embrace-the-insanity method first. Alas, it didn’t work out and I think it actually made matters worse. Thus, I decided to go with a new plan to fight against the insanity.
  5. python – a couple people mentioned I should switch to python. Yes I’ve written many thousands of lines of python, but none in 2010 so far.

Thanks for reading. As always, I love feedback.

FlexMonkey 4 is here!

Posted in Stu Stern on May 5th, 2010 by Stu Stern

Stu Stern originally posted this on Big Gorilla - Stu Stern's Blog.

We just posted the new installer and accessories zip to FlexMonkey Project Home. Getting FlexMonkey to work with Flex 4 proved to be a bit more work than we'd anticipated but ultimately we got everything working and the result is a solid release that includes support for all Spark components.

Happily, we now return our attention back to FlexMonkium, our FlexMonkey/Selenium bridge, which is rapidly nearing it's first public release!