Recently, I needed to do some programmatic animation in Flex for a client project. I was looking to achieve a kind of “mouse following” effect where an object would move towards the mouse even as the mouse itself was moved. And since Grant Skinner just updated his tiny GTween tweening engine, I thought I’d give it a whirl in Flex 4.
Click and drag the slider up and down to see the “following” effect. The height of each bar is always being tweened to match the target height set by the slider, and each bar moves with a different easing. Depending on the type of easing, the bars do a better or worse job of following the slider. In the code, all the magic happens via GTween’s proxy object, which allows me to adjust the target height of the bar even if the bar is already in motion.
Here is the relevant section of code:
privatefunction slideHandler():void{for each (var tween:GTween in _tweens){
tween.proxy.barHeight = slide.value;
}}
The slideHandler() is called whenever the slider is moved. Looping through each bar, I simply set the target barHeight via the proxy object and GTween does all the work. In the end, I get exactly the animation effect I want with a minimum of effort. I love lazy. Thanks Grant!
Cloud computing is clearly not where we want it to be.
On the one hand, we have folks actively trumpeting the benefits and utilitarian nature of cloud computing and data storage. It’s attractive for sure. Access data anywhere. Avoid the hassles of local backups. Prevent data recovery disasters. Pay-for-what-you-eat models. Unlimited computing potential. It’s all sounds great on a blog. Clearly the proponents want us to think Cloud computing is exactly like living on “Cloud Nine“.
The reality is still more hype than help to most of us. Mostly early adopters are using it today. There are steep learning curves to use the APIs. Costs of usage and storage are decreasing, but are far from the “zero cost” models touted. Nightmarish security issues arise when you don’t know where your data lives. And people are losing control of their data. That brings me to today’s Google infraction.
Google Docs is the classic example of storing data in the cloud and it’s proving to be somewhat unreliable and unpredictable. Not exactly what you’d want to hear when you are storing away personal and important information. Here’s a small list of documents that have been recently rejected with “inappropriate content” messages from Google:
Some of these issues have lingered for over a month, and still have no resolution or response from Google. Some are brand new. Either way, how can you feel good about your data in Google Docs? And if the one of the largest cloud computing advocate-providers can’t get it right, who can? Do you really want to play guesswork with important information like that? That’s just insane.
- 8.3 Google reserves the right (but shall have no obligation) to pre-screen, review, flag, filter, modify, refuse or remove any or all Content from any Service.
I understand the intent of this statement. Google probably doesn’t want the liability of Al Qaeda using the Cloud to do predictive modeling for their next attack. Or to storing documents spewing anti-Semitic hate speech. But the reality of what they’re protecting is a bit more utilitarian and ugly: copyrights. There’s nothing worse than the MPAA or RIAA coming after you because you posted some content they own the copyrights to and you’re using without their permission. This is a CYA move by Google for sure.
But what about my daughter’s homework? If her upload somehow violates a magic filter, completely obscured from public scrutiny during upload and Google prevents her from accessing it, does she get to claim that the Cloud Ate Her Homework? Never have Microsoft Word, a local hard drive and laptop in her room looked so attractive for safety and security. Precisely the opposite of what the cloud says.
Are we getting this level of (dis)service because Google is tired of providing things for free now? Are they going to force us to pay for the data we already put into the cloud?
Google’s entire history is about creating useful applications (GMail, GTalk, Wave, Google Docs) that are free to use, and allowing those that wish, premium features for a modest upgrade. I don’t think it’s too much to ask that basic reliability (Google saves my documents and keeps them safe) and predictability (Google gives me access to them next time, or at least tells me why I can’t see them) are part of the “free service”, within some reasonable limits of storage. If I have to pay just to ensure that Google will store a simple document in the first place, and not lose, modify or reject the content, that model really fails the general public and breaks with Google history to date.
Ed Wood as DataCenter Manager...Scary!
As long as the cloud can freely mess with my information without my consent, “Cloud 9″ computing sounds more like “Plan 9 from Outer Space” and I doubt I’d want Ed Wood in charge of my family spreadsheets.
This blog post is the first announcement to the world of FoneMonkey, an open source iPhone testing tool that I've been developing for the last several months. FoneMonkey automates iPhone application testing by recording and playing back user interactions, and verifying the results. FoneMonkey was inspired by FlexMonkey, the open source Flex testing tool I wrote a little more than a year ago, and which has subsequently been significantly enhanced by my colleagues at Gorilla Logic, especially Eric Owens. Today FlexMonkey has more than 4,000 registered users and an active community.
We plan to release FoneMonkey source and binaries (with attendant fanfare) in early January. Here's a sneak preview of what's coming.
Some Technical Background
FoneMonkey has been more challenging than FlexMonkey to create because the iPhone SDK, unlike the Flex SDK, provides no Automation API. Before I could develop FoneMonkey, I had to develop an automation framework. The resulting FoneMonkey API is simple, extensible and initially supports nearly all native iPhone (ie, Cocoa Touch) components.
Like FlexMonkey, FoneMonkey is designed to be used by both programmers and QA testers. Rather than simply recording and playing back low-level events, FoneMonkey records "semantic" events. In other words, FoneMonkey doesn't record that you touched a pixel at coordinate (125, 210), but instead records that you selected table row 5. The resulting scripts are relatively forgiving with respect to cosmetic UI changes. They can also be composed from scratch by directly specifying sequences of commands. (FoneMonkey Command Guide coming soon....).
Each FoneMonkey command is composed of a command name, a component identifier, and a set of command-specific arguments. For example:
Touch UIButton Send (touches the UIButton labeled "Send") InputText UITextField, your name, Fred (types "Fred" into the UITextField with a field prompt of "your name")
The Flex Automation API provides an AutomatDelegate corresponding to each Flex UIComponent, and a delegate instance is created for each UIComponent instance created at run-time. Automation delegates subscribe to their component counterparts for all UI events, and translate these low-level keyboard and mouse events into high-level component events. FoneMonkey uses a logically similar mechanism, but is instead implemented with Objective-C categories that extend UI component classes with record and playback logic.
While recording, the FoneMonkey framework monitors all UI events and forwards them to the FoneMonkey category methods that provide recording for each component class. During playback, FoneMonkey sends each command to the playback methods also provided by the class's FoneMonkey extension category.
The FoneMonkey framework provides categories that record and play back events for instances of the UIView class and all UIView subclasses. It is straightforward to create a category for any custom UI class that requires custom recording and playback logic, or to further enhance the recording and playback logic provided out of the box by the FoneMonkey framework. (FoneMonkey Extension Guide coming soon....)
To test an application, you simply statically link it with the FoneMonkey library. (FoneMonkey Setup Guide coming soon....) Upon starting your application, the FoneMonkey Console "drops down" over your application window, displaying the recording and playback controls at the bottom of the screen.
The Elements application
The Elements application with FoneMonkey controls (at the bottom).
The video below shows FoneMonkey being used to test Apple's "The Elements" sample application.
In the video, we touch the record button to hide the FoneMonkey Console and begin recording our interactions with "The Elements" application. FoneMonkey monitors for periods of inactivity and drops back down over the application if we stop interacting with it for more than the current inactivity timeout setting (by default, 2.5 seconds). Touching the play button replays the recorded script.
You might need to view this video in a new window.
FoneMonkey provides the ability to edit scripts and save them for later replaying.
The FoneMonkey script editor
You can add Verify commands to a script to test the values UI component properties or the values of associated object properties (ie, you can use a key-value encoded key path) . In The Elements sample application, a custom class called AtomicElementView is used to display data for the currently selected element. The AtomicElementView has a property called element that references an instance of the AtomicElement class, which in turn as a property called name. In the Verify command below, we test that the current AtomicElementView's element.name has a value of "Lead".
Adding a Verify command to a script
Script results with failed Verify (in red)
The next video shows how to edit a script, add a verify command, save the modified script, and then replay it.
You might need to view this video in a new window.
Over the next several weeks I'll be continuing to update the doc in preparation for our putative January launch. Stay tuned.
Posted in Jerry Andrews on December 11th, 2009 by admin
I’m trained as a nuclear and mechanical engineer. In those disciplines, there’s an underlying body of knowledge and practice for design and implementation, based on a couple hundred years of experimentation and data analysis, on what works and what doesn’t, and why.
Software “engineering” as it is practiced where I usually have worked, seems to be 75% gut feel and 20% anecdotal experience, with the remaining 5% subject to real analysis. I am committed to bringing at least some of the discipline of field engineering (those parts I understand well, and can adapt) to the practice of producing software.
A group of the leading lights in methodology and architecture have come together to form SEMAT — an acronym of “Software Engineering Method and Theory”, with the goal to “refound software engineering based on a solid theory, proven principles, and best practices”. It would sound like so much smoke, but consider some of the signatories:
Scott Ambler Barry Boehm Bill Curtis James Odell Ivar Jacobson Erich Gamma
The list is quite long, and luminous.
I suggest you go have a look: http://www.semat.org. I’m looking forward to finding out what Scott Ambler and Ivar Jacobson can agree on.
FlexMonkey is an open source Adobe AIR application used for testing Flex and AIR applications. It provides the functionality to record, playback, and verify Flex UI interactions. It also generates ActionScript / fluint tests that you can easily include within a continuous integration environment.
Who is FlexMonkey for?
Like many in the Flex community, we came to Flex development after many years of developing traditional web applications, where there are multiple tools that allow a developer to simulate a UI client for testing (like HTMLUnit). For testing our Flex user interfaces, we had a strong desire to continue using this paradigm for our developer level testing.
As software consultants, ensuring quality is an important part of what we do. So, we created FlexMonkey to fill the gap between a unit test and what’s really needed to ensure quality (and protect against regression) when developing user interfaces. While we initially created FlexMonkey for developers, many in the FlexMonkey community have found it just as valuable for use in creating QA / Functional tests.
So, we believe that FlexMonkey is useful to both software developers and quality control engineers on Flex development projects.
So, what’s so game changing about it?
If you ask Mike Labriola (one of the Fluint/FlexUnit 4 guys), ‘How do I unit test my Flex user interfaces?’ He will quickly respond, ‘You don’t.’ He won’t tell you this because he doesn’t believe in unit testing (as I can assure you that he strongly believes in Unit Testing), but because there are parts of a user interface that cannot be sufficiently tested with unit tests.
So, as we jump into the reasons why FlexMonkey matters for you, I’ll note that we do not believe that FlexMonkey replaces the need for traditional unit tests. There are still parts of a Flex application that are best tested this way (e.g. service clients, business logic, etc.). If you are building a framework, it’s likely that the majority of your testing will be done through unit tests, but if you are focusing on features and functionality you will likely be able to achieve upwards of 80% of your testing goals with FlexMonkey. Nevertheless, here are the high level places where FlexMonkey changes the game:
FlexMonkey fills the gap left between unit testing and a truly successful test suite, as it provides a tool for doing developer level functional tests that replace traditional unit testing activities that developers perform in other tiers of application development.
FlexMonkey allows developers to write their user interface code in the most natural way. Typically, when developing a user interface application without a tool to simulate a client of the running application, the code has to be written differently to support testing. This often leads to many unnatural acts, which can be avoided when using FlexMonkey.
For the Java folks, I like to bring up the SpringFramework here, as it provides us with a powerful example of a framework that largely succeeded because it allows developers to write their code in a natural way. Over the long run, the frameworks and tools that make it possible for developers to work in the most natural way will always win out.
Tools like FlexMonkey are able to facilitate this simply through the paradigm they provide for testing user interfaces, as they allow developers to test applications without any knowledge of the underlying code.
Cost. FlexMonkey is free. So, even though it’s not a perfect tool, it does enable one to build and deploy a successful test suite, a task that is extremely difficult and costly in Flex development without FlexMonkey.
You can find the FlexMonkey project at: http://flexmonkey.gorillalogic.com/
FlexMonkey is built and open-sourced by Gorilla Logic, Inc.
In Part One of this post, we discussed the Great Concurrency Problem and the promise of Go in taking the throne from Java. Today, I show why Go isn’t going to get us there.
Back in the heady days of C++, if you wanted to add concurrency support to your application, you had to work for it. And I don’t mean just find a few calls and shove them into your application. I mean:
Find a threading library available on your platform (maybe POSIX, maybe something more nightmarish, maybe even a custom thread library that would run you a few hundred bucks per license)
Locate the obscure documentation on threading APIs
Figure out how to create a basic thread
In the process, read the encyclopedia-sized docs about all the real issues you’ll hit when building threads
Decode the myriad of options available to you to synchronize your threaded application via header files
Add the library to your makefile
Code the example and
Make it all work
Contrast that with Java:
Create a Runnable interface
Implement the run() method
Call new Thread(myRunnable).start();
Debug the obscure errors you get after about 6 months of production
Whoa. At least with C++, the Threading Shotgun wasn’t loaded, the safety was on and it was hanging on the wall. You had to do the hard work of loading the gun, removing the safety and pulling the trigger. Java took all that away by handing you the loaded shotgun, safety off. That shotgun is the Great Concurrency Problem.
Java’s great contribution and Achilles Heel, in my opinion, was the choice to make threading so darned easy to do, without making developers innately aware of the implications or difficulties of concurrent programming with the shared memory model. C++ made you wade through all the hard shared-memory stuff just to get to threads, so by the time you wrote one, you at least felt smart enough to give it a go. The concurrency models in Java and C# hide all sorts of ugliness under the covers like shared memory models, caching of values, timing issues, and all the other stuff that the hardware must implement to make these concurrent threads do their jobs. But because we don’t understand those potential pitfalls before we write the software, we blithely assume that the language semantics will keep us safe. And that’s where we fall down.
Write a multi-threaded program in any shared-memory concurrent language and you’ll struggle with subtle synchronization issues and non-deterministic behavior. The timing bugs arising from even moderately concurrent applications will frustrate and annoy the most seasoned of developers. I don’t care if it’s in Java or not–the issues are similar.
My specific beef with Java is the ease with which we can create these constructs without understanding the real problems that plague us down the road. Until we have the right tools to produce concurrent applications in which we can reliably debug and understand their behavior, we can’t possibly benefit from the addition of a new language. In other words, if you want to create a Java killer, you’re going to need to make concurrent programming safer and easier to do. A tall order to say the least.
Enter Google’s Go in November, 2009. The number one feature trumpeted by reviewers is the use of goroutines (the message-based concurrency mechanism for Go) and channels to improve concurrent programming. Initial reviews are mixed at best. But I don’t think we’re anywhere close to killing Java off with this new arrival on the scene for a variety of reasons:
Going nowhere?
Go decided to use a foreign syntax to C++, C and Java programmers. They borrows forward declarations from BASIC (yep, you heard me right…BASIC), creating declarations that are backwards from what we’ve been using for close to 20 years. Incidentally, syntax similarity was one of the main reasons C++ programmers easily migrated to Java during the Language Rush of 1995, so this is disappointing.
Performance benchmarks that put it slower than C++ (and therefore, slower than Java today since Java finally caught up to C++ years ago). OK, I’ll grant you that Java wasn’t fast out of the gate, but Java was also interpreted. Go is statically linked, and not dynamically analyzed at runtime, so it’s not likely to get better immediately.
A partial implementation of Hoare’s CSP model using message-based concurrency. I almost got excited about this once I finally understood that message passing really makes for safer concurrency. But they didn’t get the model quite right. For example, did you know you can take the address of a local variable and pass that via a channel to another goroutine to be modified? Bringing us right back to the same crappy problems we have in Java and C#. Oh yes. Not that you should do that, but even Java was smart enough to drop the address of operator for precisely that reason.
A few low-level libraries bundled with language, but just barely enough to be functional for real world applications. Completely AWOL: Database and GUI. (translation: “I get to rewrite database access. One. More Time.“ Neat.) Did I mention Java had those during it’s 1.0 release?
Static linking. OK, I admit I’m an object snob and I like a strongly-typed, dynamically-bound language like Java. I like reflection and dynamic class loading and the fact I can pass strings in at runtime, instantiate objects and execute functions in ways the original code didn’t explicitly define (and yes, I’ve done this in enterprise production systems!). Not with Go, instead we’re back to C++ static linking. What you build is what you get. Dynamic class loading was probably one of the most useful aspects of Java that allowed for novel ways of writing applications previously unseen. Thanks for leaving that one out.
Excepting Exceptions. Go decided to omit exceptions as the error handling mechanism for execution. Instead, you can now use multiple return values from a call. While it’s novel and perhaps useful, it’s probably a non-starter for the Java crowd used to error handling using exceptions.
This feels like some academic research project that will be infinitely pontificated about for years to come, but not a serious language for enterprise development (obligatory XKCD joke). In short, I’m not impressed. And I kind of wanted to be. I mean this is freakin’ Google here. With the horsepower of Robert Griesemer, Rob Pike, Ken Thompson in one building. The #1 search engine in the world. The inventor of Google Wave that created so much buzz, people still don’t have their Wave Invites yet.
Enterprise Languages should be evolutionary steps in a forward direction. But Go doesn’t really get us anywhere new. And it certain isn’t much of a threat to Java. Sorry Google, maybe you need to give it another go?
* Many thanks to my friend Tom Cargill (who you may know from the “Ninety-Nine Rule“) who reviewed early drafts of these 2 posts and corrected my mistaken notions of concurrency, parallelism, Goroutines and Go syntax. He didn’t stop the bad jokes, though. Sorry about that.
Devoxx is an annual developer conference in Antwerp, Belgium. Devoxx is typically held at the coldest, most miserable time of year to allow attendees to concentrate on the most important thing: Belgian Beer. Drunk on Software’s, Chet Haase, was at the conference this year, talking to various people in bars, in restaurants, and in bars about what they were interested in drinking, er, enjoying at the conference this year.
With over 4,500 downloads of the GUI version, and 1,700 downloads of the console version, the 2.0 release of iTunes Export appears to be a success. Thank you to all who have helped out.
This release provides a few bug fixes and incremental improvements based on the feedback received so far. Thank you to everyone who has helped out, and please reach out if you have issues or suggestions.
This release as a few fixes for both versions, including:
iTunes uses different values for 'Type' based on the user's language. Changed logic to match file extension instead of value of 'Type' for MP3 file matching.
Updated processing of Playlist Name. All characters are replaced with an underscore (_) except A-Z,a-z,0-9,.[]{}-$=. This should resolve any issues with playlists containing illegal characters. This may result in some characters in non-western character sets to be replaced with _. GUI and Console versions now contain the exact same logic.
And a few changes to the GUI version:
Resolved issue with File Separator replacement (/ \) on Windows.
Fixed issue where scroll bars would appear with long Music Path.
Fixed Show Songs feature to update the song list when a different playlist is selected.
Implemented basic 'type to find' logic for Playlist list. Only matches first character, and you must select an item before the search works.
If you find any issues or have questions please email me (eric@ericdaugherty.com). Please include which application and version (GUI or Console, 2.1.1 etc.) of iTunes Export and the operating system you are using.
There’s buzz in the air about Google’s new language Go. Naturally, I was excited hearing about it. After all, Google has produced so many interesting tools and frameworks to date there’s almost automatic interest in any new Google software release. But this wasn’t just a product, this was a Google language release. My programmer brain pricked up immediately.
Language releases always catch my attention. Since 1995, I’ve constantly wondered what is going to be the Great Java Killing Language. Java’s release was the Perfect Storm of Language Timing–the rise of the internet, the frustration with C++, the desire for dynamic web content, a language bundled with a large series of useful libraries (UI, database, remoting, security, threading) previously never seen. Lots of languages have been released since, but none with quite the reception of Java. But with that perfect storm came some serious fallout.
Java vs. C++
At the same time Java rose to prominence as the defacto web and enterprise language of choice, Moore’s Law was hard at work and hardware companies were creating new kinds of processors–not just faster ones, but also motherboards that supported multiple processors. And then multiple cores on those processors. Concurrency became the new belle of the ball, with every language making sure they added support for it. Which gave rise to the widespread use of concurrency features in languages. In essence, Java brought attention to the Great Concurrency Problem that has haunted us almost two decades now.
Before I address the Great Concurrency Problem, we have to agree that most people confuse Concurrency with Parallelism. Let’s start with the definitions from Sun’s Multithreaded Programming Guide:
Parallelism: A condition that arises when at least two threads are executing simultaneously.
Concurrency: A condition that exists when at least two threads are making progress. A more generalized form of parallelism that can include time-slicing as a form of virtual parallelism.
Parallelism has only come about with multi-processor/multi-core machines in the last decade or so. Previously, we used Concurrency can simulate Parallelism. We program our applications to run as concurrent threads. And we’ve been doing that for years now on multithreaded processors. But the Great Concurrency Problem is really a problem about the differences between Human Thinking and actual Machine Processing. We tend to think about things linearly, going from Breakfast to Lunch to Dinner in a logical fashion. In the background of our mind, we know things are going on. You might even be semi-aware of those yourself. And occasionally, we get those “Aha!” moments from that background processing of previous subjects. We use this mental model and attempt create a similar configuration in our software. But the shared-memory concurrency model used by Java and other languages creates implicit problems that our brains don’t really have. Shared memory is a tricky beast. You have objects and data inside Java that multiple threads can access in ways that aren’t intuitive or easily understood, especially when the objects you share get more and more complex.
Shared memory communication is the most common of the two and is present in most mainstream languages we use today. Java, C#, C++ and C all used shared memory communication in their thread programming models. Shared memory communication depends on the use of memory locations that two or more threads can access simultaneously. The main danger of shared memory is that we share complex data–whole objects on the heap for example. Each thread can operate on that data independently, and without regard to how other threads need to access it. Access control is granted through monitors, mutexes and semaphores. Making sure you have the right control is the tough part. Too little and you corrupt your data. Too much and you create deadlocks.
Let me give a concrete example to show just how nasty this can get for shared memory communication: Let’s say you’re handling image processing via threads in a shared-memory model–like Photoshop does for image resizing. And let’s say you’re trying to parallelize this processing such that more than one thread handles a given image. (Yes, I understand we don’t do that today and there’s a good reason for that. This is an analogy, just keep your shirt on a sec.) An image is an incredibly complex object: RGB values, size, scale, alpha, layers if you’re in Photoshop, color tables and/or color spaces depending on the format, compressed data, etc. So what happens when Thread A is analyzing the pixel data for transformation and Thread B is trying to display that information on the screen? If Thread A modifies something that Thread B was expecting to be invariant, interesting things happen*. Thread A may accidentally corrupt the state of the image if Thread B doesn’t lock the entire object during read operations. That’s because Threads A and B are sharing the entire object. Oh sure, we can break the image down into smaller, simpler data abstractions but you’re doing that because of the shared memory problem. Fundamentally, Java objects can be shared between threads. That’s just a fact.
Keep in mind this is just a TWO thread example. When you write concurrent systems, two threads is like a warm up before the Big Game–we’re barely getting started. Real systems use dozens, if not hundreds of threads. So if we’re already having trouble keeping things straight with two threads, what happens when we get to 20? 200? The problem is that modeling any system using concurrent programming tools yields a subtle mess of timing bugs and problems that rarely appear until you have mountains of production data or traffic hammering your system. Precisely when it’s too late to do anything about it.
Even Java’s own documentation from ages ago cautions just how hard this problem really is:
‘‘It is our basic belief that extreme caution is warranted when designing and building multi-threaded applications … use of threads can be very deceptive … in almost all cases they make debugging, testing, and maintenance vastly more difficult and sometimes impossible. Neither the training, experience, or actual practices of most programmers, nor the tools we have to help us, are designed to cope with the non-determinism … this is particularly true in Java … we urge you to think twice about using threads in cases where they are not absolutely necessary …’’
Hey, what's behind that Runnable there? Uh oh...
Harsh words (at the bottom) from a language that really opened Pandora’s Box in terms of giving us the tools to make concurrency an everyday part of our applications.
Message-passing communication is perhaps the safer of the two models. Originally derived from Hoare’s Communicating Sequential Processes (CSP), message-passing communication is used in languages like Erlang, Limbo and now, Go. In message-passing communication, threads exchange messages with discreet amounts of local data via channels. I like to think of message-passing communication to be kind of algorithmic atomicity–you are performing some action, say transforming an image and at a certain step, you need the data from the image’s color table. So you wait to get a message from another thread when that data is available. And then continue processing locally in your own algorithm.
Because threads are restricted in what they can share, the risk of corrupt data and deadlocks drops considerably. But this comes with a higher processing cost than shared memory communication. With shared memory, there was no re-writing of the data before thread access. Just the opposite is true for message-passing. Until recently, message-passing communication was considered far to expensive to use for real-time systems. But our multi-core, multi-processor world of the 21st century has finally broken down that barrier.
The question is, does Go really solve that problem in a way that overthrows Java as King of the Enterprise? Tune in tomorrow for Part Two, where we look at Go’s features, whether Go really addresses any of these problems, and if Java is doomed.
* “Interesting” is the default programmer adjective we tend to apply when what we really mean is “incredibly BAD”.
FlexMonkey is an open source Adobe AIR application used for testing Flex and AIR applications. It provides the functionality to record, playback, and verify Flex UI interactions. It also generates ActionScript / fluint tests that you can easily include within a continuous integration environment.
Who is FlexMonkey for?
Like many in the Flex community, we came to Flex development after many years of developing traditional web applications, where there are multiple tools that allow a developer to simulate a UI client for testing (like HTMLUnit). For testing our Flex user interfaces, we had a strong desire to continue using this paradigm for our developer level testing.
As software consultants, ensuring quality is an important part of what we do. So, we created FlexMonkey to fill the gap between a unit test and what’s really needed to ensure quality (and protect against regression) when developing user interfaces. While we initially created FlexMonkey for developers, many in the FlexMonkey community have found it just as valuable for use in creating QA / Functional tests.
So, we believe that FlexMonkey is useful to both software developers and quality control engineers on Flex development projects.
So, what’s so game changing about it?
If you ask Mike Labriola (one of the Fluint/FlexUnit 4 guys), ‘How do I unit test my Flex user interfaces?’ He will quickly respond, ‘You don’t.’ He won’t tell you this because he doesn’t believe in unit testing (as I can assure you that he strongly believes in Unit Testing), but because there are parts of a user interface that cannot be sufficiently tested with unit tests.
So, as we jump into the reasons why FlexMonkey matters for you, I’ll note that we do not believe that FlexMonkey replaces the need for traditional unit tests. There are still parts of a Flex application that are best tested this way (e.g. service clients, business logic, etc.). If you are building a framework, it’s likely that the majority of your testing will be done through unit tests, but if you are focusing on features and functionality you will likely be able to achieve upwards of 80% of your testing goals with FlexMonkey. Nevertheless, here are the high level places where FlexMonkey changes the game:
FlexMonkey fills the gap left between unit testing and a truly successful test suite, as it provides a tool for doing developer level functional tests that replace traditional unit testing activities that developers perform in other tiers of application development.
FlexMonkey allows developers to write their user interface code in the most natural way. Typically, when developing a user interface application without a tool to simulate a client of the running application, the code has to be written differently to support testing. This often leads to many unnatural acts, which can be avoided when using FlexMonkey.
For the Java folks, I like to bring up the SpringFramework here, as it provides us with a powerful example of a framework that largely succeeded because it allows developers to write their code in a natural way. Over the long run, the frameworks and tools that make it possible for developers to work in the most natural way will always win out.
Tools like FlexMonkey are able to facilitate this simply through the paradigm they provide for testing user interfaces, as they allow developers to test applications without any knowledge of the underlying code.
Cost. FlexMonkey is free. So, even though it’s not a perfect tool, it does enable one to build and deploy a successful test suite, a task that is extremely difficult and costly in Flex development without FlexMonkey.
You can find the FlexMonkey project at: http://flexmonkey.gorillalogic.com/
FlexMonkey is built and open-sourced by Gorilla Logic, Inc.