
I think in many teams, one way or another connected with the development of Flex-applications, sooner or later the question arises about automated product testing. And the way our team develops an AIR client for online poker is completely natural, and we have the same question.
At first it was worked out exclusively by the QA-team, they considered some tools, including FlexMonkey. In particular, this
article on Habré was not ignored.
The testing cycle includes adding a table through the admin area, the registration process on the site, followed by downloading, installing and running the client. For this, the Selenium Test cases were written in Java. What to do next was not clear, since the standard FlexMonkey plugin for Selenium - FlexMonkium - can work only with Flex-applications running in the browser in the Flash-plugin, because it is written in JS and interacts with the Flash via ExternalInterface, which is absent in AIR Runtime. In turn, the standard FlexMonkey console interacts with any Flex application, including AIR, through the pure LocalConnection Flash technology, the Java implementation of which has not existed before. Now it exists.
')
It was decided to write a client to FlexMonkey in Java, the estimate was made, and I set to work. Immediately, I would like to say that on July 19 of this year, after the completion of the main work on our library, a new generation of FlexMonkey framework (now called MonkeyTalk) was released and, after a quick acquaintance, the problems with “cross-technology” seemed to be eliminated, by organization of client-agent connection through sockets, but I am pleased with the experience gained and I think that we will further develop this product based on the old architecture from GorillaLogic.
Prologue
So, first of all, it was necessary to figure out what LocalConnection is and how to work with it. There is only one source in the entire Network, which describes, if not fully, the insides of LocalConnection, and the information there is a bit outdated. Here is the
article .
What can we understand from this article? That LocalConnection is a Memory File Mapping object that is 65535 bytes in size and has the name MacromediaFMOmega in the system, exclusive access to which is provided by capturing a mutex named MacromediaMutexOmega. Here is an example map of this memory area:

As can be seen from the card, this protocol uses AMF coding for both versions. AMF (Action Message Format) is a binary data presentation protocol developed by Adobe. The AMF0 specification is available
here on AMF3
here .
In general, the process for receiving a message looks like this:
- 1. Register the listener by adding its name to the chain
- 2. Capturing mutex
- 3. Get the file mapping and check the recipient
- 4. If we are the recipient, we read the message and reset the timestamp and the length, so we mark the message as read
- 5. Repeat endlessly starting from step 2
The message writing process looks like this:
- 1. Capture mutex
- 2. We receive file mapping and check if the recipient exists, to which we must send a message
- 3. Write the message
- 4. Release the file mapping and mutex.
Java part
Since the standard Java library lacks the normal tools for working with Memory File Mapping, it was decided to write a native
JNI library to work with this technology. The library was written in C ++ in Visual Studio Express 2010 and compiled under a 32-bit architecture. It contains methods for creating / capturing / releasing a mutex, creating / receiving / releasing a file mapping object and writing / reading to / from it, and a wrapper over the WinAPI function GetTickCount (), which is needed to get the timestamp.
Next, the Java class LocalConnection was written, which completely rotates the interface of its Flash partner, with the exception of events. It has a setClient () method that accepts an instance of a class that implements the LocalConnectionSink interface, which defines an onInvoke method (String method, Object ... args), which actually accepts incoming calls by the name of the target method with its parameters. The send () method repeats the one from Flash, accepts the name of the connection, the name of the method to be called, its parameters, and puts it all into the send queue.
In the class itself, there is a separate stream that in the loop adds a listener / reads the message, checks the recipient / writes the message. When a new message arrives, the client's onInvoke () method is pulled. The corresponding library from
BlazeDS is used as a serializer / deserializer to / from AMF. Everything is quite simple.
Next, we needed to adjust the message with the FlexMonkey automation-agent in our application. It connects to the project by adding a SWC library and the input point in it is the MonkeyLink class, the protocol itself is also called. On the agent side, it registers an endpoint with the name "_agent", the client, in turn, must register under the name "_flexMonkey" . This class contains several public methods. The "ping" method serves for symmetric pinging of a client / agent once every half second. During his call, the isConnected flag is set, which indicates that the opposite side is still alive and accepts messages. By timer, every 5 seconds, this flag is cleared.
This class also contains a number of methods that accept instances of MonkeyRunnable class heirs. These are commands, which are actions that we see on the toolbar of the classic FlexMonkey console.
Based on this, a Java equivalent of this class was developed, and Java analogs of FlexMonkey commands from ActionScript. These are commands such as SetProperty, CallFunction, VerifyProperty, UIEvent, etc. This class contains the playCommand () method, which takes an instance of a command with the necessary parameters, serializes it and sends it to the agent via LocalConnection.
Also this class contains 2 additional streams - the first time in half a second sends a ping to the agent, and the second time in 5 seconds resets the isConnected flag.
A wrapper is made above it in the form of the FlexMonkeyAutomator class, which provides the QA-engineer with a simple API for synchronously calling actions on the agent. You can also specify the number of attempts to call the action and the delay between them. In general, a session with a test application looks like this:
MonkeyLink monkeyLink = new MonkeyLink(); if (monkeyLink.startLink(2000)) {
All FlexMonkeyAutomator methods contain overloaded versions that take a timeout with the last parameter. This is useful, in particular in this case: in the last action, we press the exit button from the application, the application closes and does not have time to send the result of the action, in this case the normal version of the action call method will never return and our test script will not hang. here the timeout version will complete safely.
All sources of this library are available on
BitBucket . I ask you not to take seriously the JMonkeyLinkTest project, which contains a test Swing application with an abundance of govnokod - it is intended solely for situational testing of individual library features, and our QA and basic combat scripts do the main testing.
PS: I completely forgot. Despite the fact that when seralizing commands on the Java side, I assign them a FQDN corresponding to their FQDN in ActionScript, for some reason they are still deserialized into a regular Object, so in the application under test they need to be registered via registerClassAlias ​​(), like this:
registerClassAlias("com.gorillalogic.flexmonkey.monkeyCommands.CallFunctionMonkeyCommand", CallFunctionMonkeyCommand);
Well, and I hope this product will benefit someone, and will also be useful to those who want to build interaction between Java and Flash / Flex code in their project through LocalConnection. Thanks for attention.