flexRpcStubs version 0.2 released

Brian LeGros | March 1st, 2010 | programming  

I burned the midnight oil tonight and was able to get release 0.2 of the flexRpcStubs project out on Github. In this release I’ve added the ability to add a rootCause to a fault on RemoteObjectStub, the ability to match parameters and headers on HTTPServiceStub, and the ability to use hamcrest-as3 matchers along with literals for both HTTPServiceStub and RemoteObjectStub. Additionally, I’ve thrown up some concise examples which, I hope, will help to show simple use cases using stubs in your unit tests. Here are links to the examples for HTTPServiceStub and RemoteObjectStub, just in case you don’t want to dig in. As always I look forward to feedback on the project. If you don’t want to build it yourself, I’ve thrown out a SWC for download on GitHub as well.

Stubs for mx.rpc classes moved to GitHub

Brian LeGros | February 9th, 2010 | programming  

A short note. For simplicities sake, I’ve created a project on GitHub (http://github.com/blegros/flexRpcStubs) to house the mx.rpc stubs which help with testing Flex service classes. The HTTPServiceStub and RemoteObjectStub classes have had a couple of bugs fixes and I’ve added build script to generate a SWC for simplicity. You can read more about the stubs in my initial posting; I hope to update the project soon with some practical usage examples.

If you have any suggestions for changes, feel free to fork and pass a pull request my way. Hope this helps those who asked for a bit more structure.

FlexUnit and Continuous Integration Updates

Brian LeGros | January 19th, 2010 | programming  

This past weekend, I finished my port of the Hudson Xvnc plugin to the FlexUnit Ant task. I’m hoping this will help those who don’t have access to the plugin, or dont’ use Hudson, but want to execute headless builds using FlexUnit and Xvnc. In addition to this work, I’ve added a few wiki pages to the newly launched FlexUnit.org’s wiki instance. A break down of the all the features available in the FlexUnit Ant task can be found @ http://docs.flexunit.org/index.php?title=Ant_Task. Additionally, to see the Ant task in action in a few variations, check out the FlexUnit4SampleCIProject on Github; I also show a basic POM using Flexmojos and FlexUnit4. For a general culmination of FlexUnit and continuous integration experience for running headless builds, check out http://docs.flexunit.org/index.php?title=Continuous_Integration_Support. Hopefully this information can help to prevent some people from experiencing the painstaking lessons I had to go through.

Next I’m off to update the FlexUnit 4 CI builds to work with versioning as well as integrate the new FlexPMD (CPD, Metrics) to get some more sexy Hudson reporting going on. If you’re interested in seeing the latest rendition of our CI process, check out http://flexunit.digitalprimates.net.

Using Xvnc to create headless CI builds for Flex and AIR applications

Brian LeGros | December 20th, 2009 | programming  

Over the last year or so, I’ve worked to integrate xvfb into the projects I work with at the office and in the community to allow the execution of truly headless builds for Flex-based applications. Since the Flash Player and AIR require a windowing environment and typically unit and integration tests require this environment to be executed, integrating Flex into a CI process on Linux gets pretty hairy without having X-Windows support. Recently I’ve found myself switching from xvfb to Xvnc to more easily support headless builds in Flex. VNC server packages are pretty ubiquitous for most Linux distros, so getting something installed is pretty simple. What took me a couple of steps was getting setup based on the configuration of my CI server. In an effort to make searching a little simpler, here are the steps for using the Xvnc-plugin with Hudson on Ubuntu Desktop 8.10 with the default Tomcat 6 installation:

  1. Install the vnc4server package (i.e. – “apt-get install vnc4server”).
  2. Assuming the Ubuntu installation came with Tomcat 6 and is setup to run as the tomcat6 system user, do the following:
    1. Execute vncpassword as any user, following the prompts to set a password to be used by the “vncserver” command. This will create the “~/.vnc/password” file needed to run the vncserver command.
    2. Copy the file at ~/.vnc/password to /usr/shared/tomcat6/.vnc/password which is the default home directory for the tomcat6 user on the standard install of Ubuntu Desktop.
    3. Change the ownership rights on the “password” file to be owned and created by the “tomcat6″ user (i.e. – chown tomcat6:tomcat6 /usr/shared/.vnc/password)
    4. Edit /etc/init.d/tomcat6, adding a line to set the HOME environment variable to “/usr/shared/tomcat6″ (i.e. – export HOME=/usr/shared/tomcat6). Since “tomcat6″ is setup as a system user, from what I can tell, this environment variable is not set by default when a process is running as this user. The “vncserver” command will need this variable to determine where the “password” file is located to launch its process.
  3. If Tomcat is running as a standard user, execute the “vncserver” command using any display number (e.g. – vncserver :99) as the user. The command will force a prompt to enter a password to use for the server which will create the “~/.vnc/password” file with the appropriate ownership rights in the appropriate home directory.
  4. In Hudson, install the Xvnc-plugin for Hudson (http://wiki.hudson-ci.org/display/HUDSON/Xvnc+Plugin)
  5. OPTIONAL: In Hudson, under “Manage Hudson” -> “Configure system” -> “Xvnc”, set the “Base display number” field to 99. This is the base display number xvfb-run uses and I’m partial to reusing this setting.
  6. Under the configuration for you CI build, check the box labeled Run Xvnc during build.
  7. If all goes as expected, then your build should kick off the “vncserver :99″ command, set the DISPLAY environment variable to 99, execute your build to completion, and then execute “vncserver -kill :99″ to kill the Xvnc process.

Based on these steps, I’m am currently building Xvnc support into the FlexUnit4 Ant task for those who don’t use Hudson and can’t take advantage of the Xvnc-plugin. The Xvnc support is a basic mirror of what the plugin for Hudson aims to provide. Hopefully someone will find this footwork useful and save some time. I’m by no means a Linux guru, so if anyone has more insight, please feel free to share so others can benefit from your knowledge as well.

Happy building!

UPDATE: I’ve now tested and deployed the Xvnc support for the FlexUnit Ant task. Hopefully this will help anyone who’s not using Hudson but wants to take advantage of headless FlexUnit test executions using Xvnc.

Vintage 56 – Rockledge, FL

Brian LeGros | October 19th, 2009 | food  

I’m happy to report that Brevard county finally has a gastropub that is worth patronizing. Vintage 56 is the most tasteful and affordable dining experience that my wife and I have had in the last year. Let’s do the walk-through.

When you come upon Vintage 56’s location, you may find yourself taken back a bit. The restaurant is tucked away in a shopping plaza which looks like it hasn’t seen much traffic in the last few years. In fact, if you’re a little faint of heart, you may turn back wondering how what you’ve heard is such a great place found it’s way there. Please trust me when I say, forge ahead, you don’t have to go into the clothing outlet and wig store; you’re just there for the restaurant. Once you make your way in, you’ll soon forget about the outside and appreciate the open floor plan and simple decor. The restaurant contains tables and half-booths (?) and open seating for its guests. We went on a Monday night and there were only a few couples dining which contributed to a nice and quiet ambiance.

I was excited to see that Vintage 56 stays fairly true to the gastropub style with its simple, seasonal menu and beer selection. I was even more ecstatic to see one of my favorite beers, Dogfish Head Pumpkin Ale ($5), on draft; they also had 2 for 1 martinis all evening, each ranging from $8 – $10 a piece. We each started with a cup of soup. I ordered a cup of the Portuguese Sausage and Kale ($3) and my wife ordered a cup of the Lobster Bisque ($4). The Portuguese Sausage soup was the perfect magnitude of spicy, made with chicken broth, kale, and diced carrot, celery, potato, and Andouille sausage; it reminded of the portions of a Zuppa Toscana that I enjoy with even more flavor. The Lobster Bisque has some small chunks of lobster in the broth and is served with a side of sherry crème fraîche which is must add to achieve the full flavor of the soup.

For our meals we went the sandwich route ordering the BLT ($8) and the Vintage Chicken Sandwich ($9). Part of what makes Vintage 56 so great is the way they can take menu items, like these simple sandwiches, and not break from your expectations, but still pleasantly surprise your palate. Both sandwiches are served on fresh baked Ciabatta bread with your choice of homemade sea-salt and cracked pepper potato chips or sweet potato fries (both of which taste great). The BLT is served with a light slathering of mayonnaise, melted whole-milk mozzarella, baby greens, yellow tomatoes, and an ample amount of crispy bacon. The Vintage Chicken Sandwich is made up of a reasonably portioned, grilled chicken breast, baby greens, brie cheese, and a pear and sun-dried cherry chutney. Although we didn’t try them, the menu also offers a selection of flat bread pizzas, burgers, tapas (cold and hot), and entrees. This evening there was also a paella for two on special, but I’m unsure of the price.

By the end of the meal, we were both stuffed, but when I heard a slice of homemade pumpkin pie ($6) was on the menu, I didn’t hesitate to order it. The texture of the pie wasn’t as smooth as I had hoped, but the flavor was amazing and definitely tasted as if the pumpkin was blended fresh. I also ordered a coffee ($2) which had a pretty typical flavor but was a nice complement to the pie.

On top of the great food, the table service was friendly and timely. We were able to sit and talk with the waiter and bartender who were very friendly and attentive. According to our waiter, by the second time he’d eaten at the restaurant he knew he wanted to work there. Being open for ~3 months thus far, it looks like he’s gotten in on the ground floor of what promises to be a great establishment. Also serving lunch, there are plenty of opportunities to stop in and see what I’m raving about. I can’t wait to see what the menu will hold as time goes on.

Vintage 56 is going into our permanent “dinner out” rotation and I’m already eager to visit again. I will go even as far as to say that Vintage 56 is the best restaurant in Rockledge at which I’ve eaten for all of my time in Brevard. Due yourself a favor and make time to stop in for a great meal and a great gastropub experience.

Vintage 56 is located at 200 Barton Boulevard, Rockledge, FL 32955.


Vintage 56 on Urbanspoon


Converting a FlexCover CVR to Cobertura XML report

Brian LeGros | October 19th, 2009 | programming  

If you’re using FlexCover as a code coverage tool within your Flex build process, the resulting report will be an XML file with a .cvr file extension. Currently there are no FlexCover plugins for the popular CI servers (i.e. – Hudson, Cruise Control, Bamboo, etc), so to take advantage of the cool baked-in reporting for code coverage, an XML report for a supported report format (e.g. – Emma, Cobertura, Clover) is needed. Currently Paul over at eyefodder has a solution using a custom build of the CoverageViewer and CoverageAgent which will produce an Emma formatted report.

Instead of creating my own custom build of FlexCover, I decided to work on an XSL transformation to the Cobertura XML report format to see if I could have any success. After a pain-staking journey back into the world of XSL, I was able to throw together an XSLT that is working with Hudson’s Cobertura plugin. You can find the XSLT under FlexUnit4 source control @ http://opensource.adobe.com/svn/opensource/flexunit/branches/4.x/FlexUnit4Test/fc-to-cobertura.xsl. If you’d like to see the reports generated for Hudson in action, check out http://flexunit.digitalprimates.net/view/Flex%203.2/job/FlexUnit4-Flex3.2/cobertura/. We currently only have the builds using Flex SDK 3.2 running with FlexCover since the latest version of FlexCover (0.81) only supports versions 3.0 and 3.2 of the SDK. Looks like some work has been done to integrate with Flex 4.0, so as support is added to FlexCover, I’ll add that work into the FlexUnit4 CI builds.

To use this XSLT to transform the CVR file, make sure you are using an XSLT 2.0 compatible engine (e.g. – Saxon) with your build tool of choice. Additionally, you will need to provide three paramaters to the stylesheet for it to work correctly:

  • sourcePath – A comma delimited list of absolute paths to the source directories, each excluding a trailing slash, for which the instrumented SWC/SWF was created.
  • version – The version number of FlexCover you used to generate the CVR file.
  • timestamp – The date/time in which the transformation occurred in ms from epoch. I’m using a date format of “MM/DD/yyyy HH:mm:ss.SSS’ and I’m not having any issues, but it may be ignored by the Hudson plugin.

If anyone has any suggestions on rewriting the XSLT using XSL 1.0 instead of 2.0, please let me know, I’m definitely open to refactoring it. Thus far the results look fairly consistent with a Cobertura XML report and integration with Hudson’s Cobertura plugin is working out great. Hope this helps those who are trying to tackle the FlexCover CI integration problem.

Presenting at the September Adogo/ORUG meeting

Brian LeGros | September 3rd, 2009 | news  

I will be presenting on Flex, Rails, and RubyAMF with Jake Swanner at the September 10th Adogo meeting. What’s great about this meeting this month, is that we’re pairing up with the ORUG and having a joint meeting, so this audience will hopefully be a good mix of Ruby and Flex developers. Jake’s been busting ass on the Rails side of things, so I think the presentation is gonna go great. If you’re in town on that Thursday and feel like taking in some Ruby and Flex love, stop by Devry at Millenia at 7:00 PM, Room 114. We will also be using Connect to broadcast the presentation, so if you’re interested in attending remotely, just let me know and I’ll try to get you a couple URLs for the meeting. I’m sure, as is our usual pre-Adogo tradition, we will be meeting at BJ’s Brewhouse for beers around 6:00 PM. Hope you can make it out.

FlexUnit 4 Beta 2 Released

Brian LeGros | August 24th, 2009 | news  

Today the 2nd beta release of FlexUnit4 was published. This release comes with a large list of bug fixes and improvements. This past weekend I burned the midnight oil with Mike and we buttoned up the FlexUnit4AntTasks project and I threw together a new sample project for FlexUnit4 showing how to integrate with Ant and Maven (via the Flex-Mojos plugin). Currently xvfb support isn’t available but we hope to add it in the next beta along with a few bug fixes and refactorings that we have time to finish. If you’re running your CI server on Windows using the Local System account, you should be able to take advantage of the new FlexUnit Ant task; the MacOS X and Linux crowd will have to work with source for now.

If your interested in more details, check out Mike’s latest blog post on the Beta 2 release.

Experiences from using Grails to migrate legacy web services

Brian LeGros | August 15th, 2009 | programming  

Recently I was tasked with migrating a version of PHP web services to our new and growing Java stack. I had to maintain the current XML interface over HTTP but use our Java services behind the scenes to satisfy the requests. In an effort to make things easier on myself, I decided to use Grails because we were using a fairly typical Java stack of technologies (Spring, Hibernate, JUnit, etc.) that integrate extremely well with Grails’ underlying architecture. Basically, I had everything I needed in terms of persistence, domain, validation, etc in our existing stack, I just had to use Grails to expose it with a specific XML interface. Now that the proof of concept phase is complete for the project, I figured I’d share some of the niceties and challenges I encountered while approaching this problem with Grails.

First off, the expressiveness of Groovy as a language (I used 1.6.3) made the biggest task of mapping a very rigid, existing XML interface to our internal domain much easier and shorter than if I would have written it in Java. The messages were basically a flattening/expanding of our internal object graph with a couple of really quirky translations of data. Being able to treat literals as objects and the use of collection operators (*.) and methods (collect, each, find) saved me quite few lines of code. On the testing side of things, strictly from the perspective of Groovy, the as operator just kicks ass. Since mapping these interfaces was my focus, I didn’t find the need to mock too many expectations from our services, so stubbing out dependencies using maps and closures made testing SO much easier. I did find a down side to stubbing directly in Groovy however. If you are attempting to stub out a class without a no-arg constructor, you’re going to have to use a library like GMock which will allow you to create a stub passing constructor arguments. I’m not too partial to play, rewind type mocking frameworks, so I was a little bummed to have to pull in another resource to test, but it got the job done.

On the Grails side of things, integration with our existing services couldn’t have been easier. We used Grails 1.1.1 for our implementation. With a few tweaks to resources.xml, I was able to reuse our entire set of bean declarations and have them injected by name into our controllers. Although, we didn’t place our Hibernate mapping files in the /hibernate folder, I was able to create my own session factory with relative ease to get Hibernate up and running. Once I had this working, I knew I could eventually take advantage of the real reason I wanted to use Grails, RESTful interfaces over HTTP. The former PHP interface implemented a Front-Page Controller for all of its services, so using URLMappings I was able to emulate index.php to the rest of the world pretty easily. On a side note, the former interface was expecting a request variable name action which Grails reserves, but using a simple closure in UrlMappings allowed me to map it as a new request variable name and go on my way. In any case, since this is a specific endpoint, I am left open to create new controllers using Grails’ REST support as we migrate away from the older interfaces. This also means, from what I understand (thanks implicit GORM support from setting up Hibernate), I can start to use xml property binding to create my domain objects and the encodeAsXml() and encodeAsJson methods to serialize those object across the wire. This is pretty huge for us and has definitely improved my opinion of working with Java as a langauge on the web. It also solidified for me that Grails has matured quite a bit since I last gave it a test run. Lastly, I have to say that I’m really digging the simplicity of functional-testing plugin. Initially I had looked at WebTest, but this plugin is much less intimidating and was dirt simple to get started with.

Let me just stop hear and say that there were quite a few challenges to bringing Grails into our stack as well. The challenges weren’t particularly due to the implementation code itself but more on the supplemental side of things in terms of testing, continuous integration, and IDE support. Coming from an existing Java code base, we already had a set of testing tools we liked based on JUnit 4, JMock, and Spring testing. This included some really productive tools we built around dbunit supporting yaml for integration testing. Currently, Grails only supports JUnit 3, so ideally test cases should extend GroovyTestCase; there is also GrailsUnitTestCase which helps out with the mocking story quite a bit on unit tests for domain classes. Having to use JUnit 3 meant making a decision to go back and refactor testing support to work with both JUnit 4 and JUnit 3 or just rely more heavily on the functional testing support in Grails. Since I was just building controllers and a couple of domain classes, I chose to rely more on functional testing. For what its worth, there is a ticket out there for JUnit4 support. JUnit4 support aside, probably one of the most detracting things from testing with Grails is the tedium involved when testing controllers. Grails will inject a MockHttpServletRequest, MockHttpServletResponse, and MockHttpSession object for use by your controllers in the test case so you check redirected/forwarded urls, what responses will look like, easily create request edge cases, etc. By executing grails test-app -integration you can quickly see what I’m talking about. The injection process is painfully slow, at least on my last gen Macbook Pro, and I feel like I am always sitting, waiting around for these tests. I could have probably thinned down my controllers a bit, but most of the cost of executing these tests was on startup of the overall run. The only other thing I would have like to seen supported is the ability to have multiple test classes for the same domain, service, controller class. The permutations of response messages from each controller action were quite numerous, so I would have liked to create a test case per controller action rather than just one for the entire controller for readability. I only had luck getting a single test case to execute following the Grails naming conventions per object.

On the CI side of things, we build our Java projects using Maven. For large Java applications, we’ve been unable to find a simpler approach to build our software than using multi-module projects in Maven. Grails’ Maven support unfortunately did not work well with our multi-module project although it looks like they’ve made some updates for a quick fix that may help. Until then, I have our project POM hacked together a bit marking the executions of the plugin myself and using the dependency plugin to create a lib directory so I can work with grails outside of Maven w/o issues. Here are some of the relevant changes I made for my POM:

...
   <build>
      <plugins>
         <plugin>
            <groupId>org.grails</groupId>
            <artifactId>grails-maven-plugin</artifactId>
            <version>1.1-SNAPSHOT</version>
            <extensions>true</extensions>
            <executions>
               <execution>
                  <id>grails-clean</id>
                  <goals>
                     <goal>clean</goal>
                  </goals>
                  <phase>clean</phase>
               </execution>
               <execution>
                  <id>grails-test-app</id>
                  <goals>
                     <goal>test-app</goal>
                  </goals>
                  <phase>test</phase>
               </execution>
               <execution>
                  <id>grails-war</id>
                  <goals>
                     <goal>war</goal>
                  </goals>
                  <phase>package</phase>
               </execution>
            </executions>
            <dependencies>
               <dependency>
                  <groupId>org.codehaus.groovy</groupId>
                  <artifactId>groovy</artifactId>
                  <version>1.6.3</version>
               </dependency>
            </dependencies>
         </plugin>
         <plugin>
            <artifactId>maven-antrun-plugin</artifactId>
            <executions>
               <execution>
                  <id>copy-grails-test-results-for-ci</id>
                  <phase>test</phase>
                  <configuration>
                     <tasks>
                        <property name="report.loc" location="${project.build.directory}/surefire-reports" />
                        <mkdir dir="${report.loc}" />
                        <copy todir="${report.loc}">
                           <fileset dir="${project.build.directory}/../test/reports">
                              <include name="**/TEST-*.xml" />
                              <exclude name="TEST-TestSuites.xml" />
                           </fileset>
                        </copy>
                     </tasks>
                  </configuration>
                  <goals>
                     <goal>run</goal>
                  </goals>
               </execution>
               <execution>
                  <id>copy-grails-war-to-target-for-lifecycle</id>
                  <phase>package</phase>
                  <configuration>
                     <tasks>
                        <copy todir="${project.build.directory}">
                           <fileset dir="${project.build.directory}/..">
                              <include name="*.war" />
                           </fileset>
                        </copy>
                     </tasks>
                  </configuration>
                  <goals>
                     <goal>run</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-clean-plugin</artifactId>
            <version>2.3</version>
            <executions>
               <execution>
                  <id>clean-dependencies-in-lib-for-clean</id>
                  <phase>pre-clean</phase>
                  <goals>
                     <goal>clean</goal>
                  </goals>
                  <configuration>
                     <filesets>
                        <fileset>
                           <directory>${basedir}/lib</directory>
                           <includes>
                              <include>**/*.jar</include>
                           </includes>
                        </fileset>
                     </filesets>
                  </configuration>
               </execution>
            </executions>
         </plugin>
         <plugin>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
               <execution>
                  <id>copy-dependencies-into-lib</id>
                  <phase>generate-sources</phase>
                  <goals>
                     <goal>copy-dependencies</goal>
                  </goals>
                  <configuration>
                     <outputDirectory>${basedir}/lib</outputDirectory>
                     <excludeGroupIds>org.grails,org.codehaus.groovy</excludeGroupIds>
                  </configuration>
               </execution>
            </executions>
         </plugin>
         ...
      </plugins>
   </build>
...

In terms of CI server integration, we use Hudson and the only hiccup I ran into was to make sure the user the app server is running as has rights to create a /.grails folder in its home directory. It would be nice to be able to run the unit and integration tests with lifecycle rather than all at once (GRAILS-4569) as well as have a goal to just run functional tests, but I know they are working on it. It looks like a lot of work has been done with this plugin since the 1.1-SNAPSHOT we were using, so I’m eager to give it another try as we add more web services to the mix.

The last hurdle I had to overcome in using Groovy and Grails was IDE support. Working with Java and Flex, I’ve come to find that Eclipse is my staple development tool. Unfortunately, working with the combination of Maven, Groovy, and Grails, I found myself continually frustrated with the Groovy Eclipse plugin. m2eclipse really didn’t help either since a Grails application directory structure doesn’t match the traditional Maven project layout. In the end I found myself just using the code highlighting and limited refactoring support in Groovy Eclipse and then command-line for everything Grails related. I’d heard a lot about Netbeans 6.7 support for Grails, so I was optimistic, but the experience was more of a honeymoon than anything else. Netbeans has great Maven support, but unfortunately Grails projects in Netbeans can’t take advantage of that support; Netbeans doesn’t seem to have project nature support like Eclipse. I found myself using the built-in context menus for the Grails commands to keep me from going out to the command line, but this was pretty much the only feature I could justify using in Netbeans. The code completion support was far from responsive. I found myself waiting almost 30s in some cases for the “Please wait…” pop-up to only find that the Groovy editor couldn’t tell me anything about my typed/untyped variable other than the defaults. The Subversion client is terrible. When committing, each file in the changeset has a drop-down box for what you’d like to do with the file (exclude, add, commit) and the default is add or commit. If you have a working copy with lots of files you want to exclude (e.g. – artifacts from a build process) you have to one-by-one exclude each file. Also, I’m not sure why but the patch command is not available from the SVN context-menu on the project or files view. I had to hunt through the Team menu under Subversion to finally find the option. Subversive and Subclipse for Eclipse are a reason enough to avoid Netbeans if you’re an SVN user, IMO. Maybe I couldn’t find the hotkey or context menu option, but there also didn’t seem to be the ability to refresh a folder on the project or files view? I noticed that Netbeans was constantly “scanning folders” to find changes on the file system but I had no manual way of just saying refresh. Consequently I had a lot of folder sync’ing issues between the file system and Netbeans in the rare case I needed to use the command line. In the end, a lot of the day-to-day niceties I had become accustom to just weren’t in Netbeans and for the way I was using it, it just wasn’t for me. I had heard really good things about the IntelliJ support for Grails, but due to a license fee, my poor experience with Netbeans, and the fact that Eclipse does everything else I need for development, I ended up just sticking with Eclipse. On a more positive note, SpringSource has released an alpha build of a new Groovy plugin for Eclipse which has some great promise. There is also talk of STS for Eclipse adding Grails support, so I’m hopeful the Groovy/Grails IDE experience can only improve from here.

Overall, despite the challenges I encountered, Grails is a dynamite web framework if you’re already working with Spring and Hibernate in your stack. I’ll acknowledge I may be a complete n00b in terms of the learning curve still, so if I’ve totally missed the boat on some of my points, please let me know so I can update this post. I’m excited to continue using Grails, especially with the newer releases coming up which will including Spring 3.0 and Spring-Flex.

Custom test runner for FlexUnit 4 and mock-as3

Brian LeGros | August 6th, 2009 | programming  

At the August Adogo meeting, I presented on the new features coming in FlexUnit4 and mock-as3. During the presentation, I showed the following sample (which has been updated) of how a FlexUnit 4 test using a customer runner for mock-as3 would work. Please keep in mind the example is a bit contrive but exemplifies the configuration options for the runner.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package us.adogo.mock
{
   import com.anywebcam.mock.Mockery;
 
   import org.flexunit.Assert;
   import org.flexunit.assertThat;
   import org.hamcrest.core.not;
   import org.hamcrest.object.equalTo;
   import org.hamcrest.object.hasProperty;
   import org.hamcrest.object.nullValue;
 
   [RunWith("com.anywebcam.mock.runner.MockAs3TestRunner")]
   public class ExampleUsingMockAs3Runner {
      public var mockery : Mockery;
 
      [Mock]
      public var user : User;
 
      [Mock(inject="false")]
      public var account : Account;
 
      private var controller : UserController; 
 
      [Before]
      public function setUp() : void {
         account = mockery.nice(Account, ["1234567890"]) as Account;
         this.controller = new UserController(); 
      }
 
      [Test]
      public function testAddUserWithUsernameAndPasswordOnly() : void {
         //setup mock
         mockery.mock(user).method("save").calls(function () : void {
            user.id = 1;
         }).once;
 
         //populate object properties as you usually would
         user.username = "bobdobbs";
         user.password = "mysecret";
 
         //execute my controller method being tested
         controller.addUser(user);
 
         //test that the currentUsers went up by one and that its id is 1
         assertThat(controller.currentUsers.length, equalTo(1));
         assertThat(controller.currentUsers.getItemAt(0).id, equalTo(1));
         assertThat(controller.currentUsers.getItemAt(0).username, equalTo("bobdobbs"));
         assertThat(controller.currentUsers.getItemAt(0).password, equalTo("mysecret"));
      }
 
      [Test]
      public function testValidateUserAccount() : void {
         //setup mock
         mockery.mock(account).method("isValid").withArgs(User).returns(true).once;
 
         //execute my controller method being tested
         var expected : Boolean = controller.validateUser(new User(), account);
 
         //test that the account is valid
         Assert.assertTrue(expected);
      }
 
      [Test(verify="false")]
      public function testDefaultUserSize() : void {
         assertThat(controller, hasProperty("currentUsers"));
         assertThat(controller.currentUsers, not(nullValue()));
         assertThat(controller.currentUsers.length, equalTo(0));
      }
   }
}

This evening I updated the Adogo SVN with a working version of this runner and thought I’d detail its initial implementation.

  • To use the runner place the metadata [RunWith("com.anywebcam.mock.runner.MockAs3TestRunner")] on the test class’ declaration.
  • Once annotated with metadata, the test class will not run unless a public variable, or setter, is available of type com.anywebcam.mock.Mockery. This will allow the runner to inject a Mockery object and prepare() the mockery to produce mock objects. Using and preparing a mockery is a new requirement for mock-as3 if you’re utilizing type-safe mocks due to the asmock integration.
  • Any public variable, or setter, annotated with the metadata [Mock] will have a type safe version of it injected automatically prior to the execution of each test method. By default a nice mock will be used, but if you specify the “type” attribute (e.g. – [Mock(type="strict")]) as “strict” then a strict mock will then be used. The difference between nice and strict mocks, is the equivalent of the “ignoreMissing” constructor argument on com.anywebcam.mock.Mock being set to true, or false, respectively.
  • If the [Mock] metadata is used on a class with a constructor requiring arguments, whether they are optional or …rest, the runner cannot automatically inject the mock due to a limitation in its underlying dependency on the asmock library. If you need a mock object instance using constructor arguments, set the attribute “inject” as false (e.g. – [Mock(inject="false")]. Doing so will tell the runner that you’re going to use the mock-as3 framework directly to create the mock. The ideal place to do this in your test is within the [Before] methods defined for the test class. By going through all this hoopla, you get automatic mock prepration and verification, just as with the automatically injected mock objects.
  • After the execution of each test method, the runner will automatically call verify() on each object variable/property marked with the [Mock] metadata. If you’d like to disable verify() from being called on all mocks for a test method, simply add the attribute “verify”, with a value of false, to your [Test] metadata (e.g. – [Test(verify="false")]). This can be helpful if you want the runner to inject the mockery and all of your mocks, but you would like to specify which mocks are verified for the test.
  • Currently this runner requires FlexUnit 4 Beta 2 and a custom build of mock-as3 to work as stated. You can find SWCs for each in the Adogo August project linked above.

What’s important to note, is that this runner is more restrictive than using the mock-as3 framework directly, so it may not suite your needs. I based this runner off of concepts I saw in the JMock runner for JUnit 4, the @Mock annotation found in Mockito for Java, and my own testing practices. If anyone finds time to play with it and you find any gremlins, let me know. In speaking with Drew, it looks like this may make it into the next release of mock-as3 along with a couple of other cool features, so I hope people find it helpful.

UPDATE: Drew has been kind enough to deploy this FU4 test runner to the mock-as3 SVN repository under the class name com.anywebcam.mock.runner.MockRunner. Please use this copy for future reference. Please also note this version will only work with FlexUnit4 Beta2 and earlier. FlexUnit4 RC1 has changed the implementation for test runners and this code will need to be updated.