Feedback welcome: session proposals for Agile 2010


I just finished writing two proposals for Agile 2010. As usual, I asked for feedback to my friends through Twitter.

Since the conference’s site requires registration and some of my friends don’t have an account, I’m blogging about them (thanks Jonathan for the suggestion!)

As a side (and funny) note, this is what Rémy said about it:

dood, a longer feedback loop because of mandatory registration ? How agile is that :p

First proposal, co-presenting with Ted Young:

Fluent Interfaces: Improving Specification Readability in Plain-Old Java

In Test-Driven Development the tests are the specification of the behavior to create. A language targeted at the kind of problem to solve can simplify the creation of readable and compact specifications. This is known as a domain-specific language (DSL.)

By providing the most direct representation of a language, dynamic languages have renewed interest in DSLs. However, discarding the compiler and the ability to use powerful IDEs is a disadvantage with this approach.

This session describes how it is possible to write DSLs using Java and suggests patterns for constructing them.

Process/Mechanics

  • 10 minutes – Introduction to domain-specific languages (DSLs)
    • What are DSLs?
    • Types of DSLs: internal and external
    • Internal DSLs vs APIs
  • 10 minutes – Is Java suited for creation of internal DSLs?
    • Pros and cons of using Java (the language) to create internal DSLs
    • Can Java-based DSLs be written by business users?
    • Introduction to Fluent Interfaces
  • 5 minutes – Java as a platform for internal DSLs
    • Example of a Java-based internal DSL
  • 25 minutes – Patterns for creating DSLs in Java
    • Method chaining: use cases and examples
    • Static Factory Methods and Imports: use cases and examples
  • 5 minutes – Organizing DSL code
    • Inner classes vs. top-level classes
  • 5 minutes – Documenting DSL code
    • Overcoming limitations of Javadocs
  • 30 minutes – Live coding demos

Learning outcomes

  • What a domain-specific language (DSL) is
  • Types of DSLs
  • Pros and cons of using Java to write internal DSLs
  • Creating DSLs in Java using Fluent Interfaces
  • Patterns for creating DSLs in Java, use cases and potential shortcomings
  • DSLs applied to test code
  • How to organize code in a Java-based DSL
  • How to document a Java-based DSL

Second proposal, co-presenting with Stephen Chin:

Test-Driven GUI Development Made Easy

Despite the fact that Test-Driven Development (TDD) can help us build software better and faster, GUI development has been slow to include TDD as a core practice. The main reason is that writing tests for GUIs is difficult and error-prone.

In this session, we will explore several recommendations, practices and tools that can simplify test-driven GUI development. This session focuses on Swing and JavaFX GUIs. However, the practices covered in this session can be applicable to other GUI toolkits.

Process/Mechanics

  • 5 minutes – Introduction to TDD and GUI testing
  • 10 minutes – Requirements for robust GUI testing
    • Reliable lookup of GUI components
    • Challenges related to changes in layout or look-and-feel
    • Native event generation vs. toolkit-specific events
  • 5 minutes – Limitations of GUI testing
  • 10 minutes – Introduction to open source (and free) tools that can make Test-Driven Development of GUIs possible
    • Pros and cons of each
  • 45 minutes – Live-code demo
    • Creating a Twitter client using TDD (one in Swing and one in JavaFX)
  • 15 minutes – Troubleshooting failing GUI tests
    • External/environmental factors
    • A GUI component cannot be found
    • Multiple GUI components satisfy some search criteria

Learning outcomes

  • What robust GUI tests mean
  • Create GUIs using a test-first approach
  • How to create testable GUIs
  • How to troubleshoot failing GUI tests
  • How to find and fix threading issues
  • What to look for in a GUI testing tool/library

Feedback is always welcome! :)

, , , , , ,

No Comments

A (overlooked?) use case for the Strategy pattern, part 2: it’s not about Template Method

Recap

As I explained in my previous post, I think there is a use case for the strategy pattern that, in my opinion, we often overlook:

This is what I’ve seen: class A has method x. Just after method x is done doing its thing and before it exits, it calls a (sometimes empty) protected method y meant to be overridden to handle some result or side effect of x (is there a name for this anti-pattern?)

This is the example I used to illustrate this particular case:

/**
 * Understands a <code>{@link SecurityManager}</code> that does not allow an application 
 * under test to terminate the current JVM. Adapted from Abbot's own 
 * {@code SecurityManager}.
 */
public class NoExitSecurityManager extends SecurityManager {
  @Override public final void checkExit(int status) {
    if (!exitInvoked()) return;
    handleExitRequest(status);
    throw new ExitException(concat(
      "Application tried to terminate current JVM with status ", status));
  }
 
  /**
   * Implement this method to do any context-specific cleanup. This hook is provided since 
   * it may not always be possible to catch the <code>{@link ExitException}</code> 
   * explicitly (like when it's caught by someone else, or thrown from the event dispatch 
   * thread).
   * @param status the status the exit status.
   */
  protected void handleExitRequest(int status) {}
}

and the issues with this approach:

Misunderstanding?

Some of the comments, both from this blog and Javalobby’s post, related this anti-pattern with the template method pattern. I respectfully disagree.

Although they may seem similar, the template method pattern and the anti-pattern I described are not the same. Let’s start with the definition of the template method pattern:

Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.

The key differentiator is the Single Responsibility Principle. The template method pattern has one job: implement an algorithm. It defers some steps to subclasses, but those steps are part of the class’ main job. On the other hand, the anti-pattern I described provide a method that works as a “hook” that subclasses may want to use for handling some side effect or a result of an operation. The functionality of this “hook” may not be related at all to the original responsibility of the class, ending up with a class that is doing too much.

Of course, the template method pattern can be abused as well: deep hierarchy trees can make code difficult (or impossible) to understand, and the notion of a “single responsibility” can be subjective. What it seems to me like a single responsibility may be seen as multiple responsibilities by others. IMHO, the best ways to prevent these issues are education, lots of practice and having someone else look at our code.

Feedback is always welcome!

(Image taken from davis.jacque’s flickr stream under the creative commons license)

, , ,

2 Comments

FEST’s JavaFX Maven plugin 1.0a1

I’m proud to announce the release of FEST-JavaFX-Maven 1.0a1!

FEST-JavaFX-Maven is Maven plugin for compiling JavaFX source files. This is a complete rewrite of the plugin, as a Java Mojo.

The original plugin was written as a wrapper for an Ant script. This approach didn’t work well: I couldn’t find a way to make the Ant script see the dependencies declared in a POM and Ant itself is not a programming language (try to do a simple “if-then-else.”) In addition, it seems to me that writing Maven plugins with Ant is discouraged, since the related documentation has been removed from the Maven official online book.

Features

  • Compiles JavaFX sources (currently supports desktop profile only)
  • Does not require JavaFX distribution to be in a Maven repository (according to its license, only Sun/Oracle can distribute JavaFX)
  • Does not require to list all JavaFX libraries as dependencies in your pom.xml

Example

<build>
  <plugins>
    <plugin>
      <groupId>org.easytesting</groupId>
      <artifactId>fest-javafx-maven</artifactId>
      <version>1.0a1</version>
      <executions>
        <execution>
          <phase>compile</phase>
          <goals>
            <goal>compile</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

The example above will call the “compile” goal in the standard Maven “compile” phase.

Release Notes

Bug

  • [FEST-288] – loader constraint violation. Thanks to Viktor Hedefalk.
  • [FEST-289] – Compilation fails if folder ‘target/classes’ is not already created. Thanks to Johannes Schneider.
  • [FEST-290] – Dependencies on other Maven projects (particularly other Maven JavaFX projects) didn’t seem to work. Thanks to William Billingsley.
  • [FEST-294] – Allow configuration of JavaFX home in POM, as well as environment variable. Thanks to nicerobot.

The FEST JavaFX Maven plugin can be obtained from our Maven Repository.

Links

Feedback is always appreciated :)

, , ,

3 Comments

A (overlooked?) use case for the Strategy pattern

Composition over inheritance. It seems that we all agree and understand this valuable principle. I’ve been reading a good amount of code lately from some open source projects (including mine,) and I think we are still missing at least one use case where to apply it.

This is what I’ve seen: class A has method x. Just after method x is done doing its thing and before it exits, it calls a (sometimes empty) protected method y meant to be overridden to handle some result or side effect of x (is there a name for this anti-pattern?)

Here is a concrete (and oversimplified) example, taken from FEST:

/**
 * Understands a <code>{@link SecurityManager}</code> that does not allow an application 
 * under test to terminate the current JVM. Adapted from Abbot's own 
 * {@code SecurityManager}.
 */
public class NoExitSecurityManager extends SecurityManager {
  @Override public final void checkExit(int status) {
    if (!exitInvoked()) return;
    handleExitRequest(status);
    throw new ExitException(concat(
      "Application tried to terminate current JVM with status ", status));
  }
 
  /**
   * Implement this method to do any context-specific cleanup. This hook is provided since 
   * it may not always be possible to catch the <code>{@link ExitException}</code> 
   * explicitly (like when it's caught by someone else, or thrown from the event dispatch 
   * thread).
   * @param status the status the exit status.
   */
  protected void handleExitRequest(int status) {}
}

At first glance this code looks OK. Subclasses can do whatever they want when “exit” is called, and since the method checkExit is final, there is no way that subclasses can accidentally (or intentionally) change the intended behavior of the super class.

There are, IMHO, some issues with this approach:

Let's take a look at a simple (silly?) subclass of NoExitSecurityManager that writes a message to a file when exit is called:

public class WriteToFileNoExitSecurityManager extends NoExitSecurityManager {
  // The class FileWriter only exists for the purposes of this example
  private final FileWriter fileWriter = new FileWriter("${temp}/log.txt");  
 
  @Override protected void handleExitRequest(int status) {
     fileWriter.write(concat("Exit called with status ", status));
  }
}

This subclass is actually doing too much: it is preventing an application from exiting (inherited behavior) and it is also handling the “exit request.”

WriteToFileNoExitSecurityManager is not really a NoExitSecurityManager, but an “exit request handler.” Inheritance in this case is, IMHO, unnecessary: the implemented functionality (not the inherited one) in WriteToFileNoExitSecurityManager is self-contained, and it does not depend on the internal state (or identity) of the superclass. In addition, since the method checkExit is final, there can only be one implementation. On the other hand, there can be different implementations of handleExitRequest, each of them forced to be a subclass of NoExitSecurityManager.

Testing is also more complicated in this scenario. To test NoExitSecurityManager, we would need to subclass it (more unnecessary inheritance) and set some flag in handleExitRequest to verify it is called (we could also create a mock, but at the end it’s all the same):

public class NoExitSecurityManagerTest {
  private TestNoExitSecurityManager securityManager;
 
  @Before public void setUp() {
    securityManager = new TestNoExitSecurityManager();
  }
 
  @Test public void should_prevent_application_from_exiting_and_handle_exit_request() {
    // test that an application trying to exit is effectively stopped
    ...
    // here we verify that the call to 'handleExitRequest' was made
    assertThat(securityManager.handleExitRequestCalled).isTrue();
  }
 
  private static class TestNoExitSecurityManager extends NoExitSecurityManager {
    boolean handleExitRequestCalled;   
 
    @Override protected void handleExitRequest(int status) {
      handleExitRequestCalled = true;
    }
  }
}

Enter the Strategy pattern

We can clean up our example by using the strategy pattern.

First, we introduce the interface ExitRequestHandler. It only has one responsibility: to handle “exit requests.”

public interface ExitRequestHandler {
  void handleExitRequest(int status);
}

Then, we can replace the call to the method handleExitRequest with a call to an instance of ExitRequestHandler:

/**
 * Understands a <code>{@link SecurityManager}</code> that does not allow an application 
 * under test to terminate the current JVM. Adapted from Abbot's own 
 * {@code SecurityManager}.
 */
public final class NoExitSecurityManager extends SecurityManager {
  private final ExitRequestHandler exitRequestHandler;
 
  public NoExitSecurityManager(ExitRequestHandler exitRequestHandler) {
    this.exitRequestHandler = exitRequestHandler;
  }
 
  @Override public void checkExit(int status) {
    if (!exitInvoked()) return;
    exitRequestHandler.handleExitRequest(status);
    throw new ExitException(concat(
      "Application tried to terminate current JVM with status ", status));
  }
}

Finally, we can rewrite WriteToFileNoExitSecurityManager as a WriteToFileExitRequestHandler:

public class WriteToFileExitRequestHandler implements ExitRequestHandler {
  // The class FileWriter only exists for the purposes of this example
  private final FileWriter fileWriter = new FileWriter("${temp}/log.txt");  
 
  @Override public void handleExitRequest(int status) {
     fileWriter.write(concat("Exit called with status ", status));
  }
}

It looks like I just moved code around and actually created even more code! True, we have more code, but better-quality code:

  • each class has a single, well-defined responsibility
  • there is no tight coupling between the class using the strategy interface and a specific strategy implementation
  • implementing a small interface is easier than extending a class (no need to worry about the state of the superclass in a particular context)
  • testing is simpler

Here is the updated test:

public class NoExitSecurityManagerTest {
  private ExitSecurityManager securityManager;
  private TestExitRequestHandler requestHandler;
 
  @Before public void setUp() {
    requestHandler = new ExitRequestHandler();
    securityManager = new ExitSecurityManager(requestHandler);
  }
 
  @Test public void should_prevent_application_from_exiting_and_handle_exit_request() {
    // test that an application trying to exit is effectively stopped
    ...
    // here we verify that the call to 'handleExitRequest' was made
    assertThat(requestHandler.handleExitRequestCalled).isTrue();
  }
 
  private static class TestExitRequestHandler implements ExitRequestHandler {
    boolean handleExitRequestCalled;   
 
    @Override public void handleExitRequest(int status) {
      handleExitRequestCalled = true;
    }
  }
}

I had a hard time writing this blog post because the points I just made seemed to be too obvious and well-understood by now. But, by reading code (both mine and written by others) I got the impression that although we understand the “composition over inheritance” concept, it is still not easy to apply it in practice.

Am I being too picky? I hope not (although I admit this issue has been annoying me for some time, I finally had the chance to complain.) IHMO, every detail counts when writing clean code :)

Feedback is always welcome!

Update: This post has been published at Javalobby.

(Image taken from etringita’s flickr stream under the creative commons license)

, ,

8 Comments

FEST-Swing 1.2a4: GUI Testing Made Easy

I’m proud to announce the release of FEST-Swing 1.2a4!

FEST-Swing is a Java library that provides a fluent interface for functional Swing GUI testing. This library provides an easy-to-use API that makes creation and maintenance of GUI tests easy.

This is the fourth and last alpha release planned for version 1.2. This new release includes a good number of bug fixes, new features and improvements. After this release, we’ll have a beta one that will include bug fixes and low-risk improvements only, followed by a release candidate.

Release notes

Bug

  • [FEST-98] – Finding Components is unreliable on Linux. Thanks to Mihael Vrbanec, Julia Koep, Martin Ginkel, Martin Bachmann.
  • [FEST-175] – German umlauts not working since upgrade from 1.1->1.2a2. Thanks to Jan Zuchhold.
  • [FEST-207] – FailOnThreadViolationRepaintManager does not work on Java 5. Thanks to Daniel Dyer.
  • [FEST-210] – JSplitPaneDriver does not respect the limitations of the BasicSplitPaneDivider.DragController. Thanks to Martin Ginkel.
  • [FEST-215] – FEST-Swing does not compile, since project configuration claims Java 1.5 compatibility, but source uses classes/methods from Java 1.6 runtime.
  • [FEST-219] – invokeAndWait() in JApplet.init() causes Exception. Thanks to Dominik Wild, Kyle Murphy.
  • [FEST-227] – JTableFixture.cell(String value) expects a regex. Thanks to Uli Schrempp.
  • [FEST-231] – JScrollPane : up & down inverted. Thanks to Florian SIMON.
  • [FEST-232] – Problems with French keyboard. Thanks to Florian SIMON.
  • [FEST-246] – JTreeDriver: drop() fails when root tree not visible. Thanks to Pavol Marko.
  • [FEST-250] – optionPane() fails to find JOptionPane with null parent. Thanks to Stephen Gade Esven, Morten Breum Mikkelsen.
  • [FEST-254] – JComboBoxFixture.requireSelection(String) method with an editable JComboBox does not use cell reader. Thanks to Glen Schrader.
  • [FEST-262] – fest-swing 1.2a3 swinghelper-debug dependency incorrect in pom.xml. Thanks to Luke Nezda.
  • [FEST-274] – ‘requireSelection‘ in JComboBoxDriver should return value of ‘getSelectedItem‘ if selection index is -1 in editable JComboBox.
  • [FEST-280] – JTextComponentFixture obtains text of JTextComponent outside EDT.
  • [FEST-285] – Typo in error message. Thanks to Steve Farrell.

Improvement

  • [FEST-123] – ItemGroupFixture: separate notion of select/click. Thanks to Jeanette Winzenburg.
  • [FEST-222] – JProgressBar has no Fixture. Thanks to Jacob Qvortrup.
  • [FEST-244] – JListFixture needs a requireRowCount method. Thanks to Harry L.
  • [FEST-248] – Add rightClickPath to JTreeFixture. Thanks to Huib.
  • [FEST-251] – Update FEST-Assert dependency to version 1.2.
  • [FEST-267] – JOptionPaneFixture missing many of ContainerFixture’s methods. Thanks to Morten Breum Mikkelsen.
  • [FEST-269] – add "requireSelection" in JTableFixture. Thanks to Florian SIMON.

New Feature

  • [FEST-8] – Method on JTreeFixture to return a fixture for a cell (issue 185.)
  • [FEST-43] – Add selectedRow() to TableCell and TableCellByColumnName (issue 226.) Thanks to Ken Geis.
  • [FEST-213] – Add method ‘clickRow(int)‘ to JTreeFixture.
  • [FEST-225] – Referencing a JTableFixture row by its cell contents. Thanks to Morten Breum Mikkelsen.
  • [FEST-249] – fest allows system.exit calls that kill running multiple tests. Thanks to Brandon, Jean-Francois Poilpret.
  • [FEST-266] – Add method "rightClickRow(int)" to JTreeFixture.
  • [FEST-283] – Provide a way to install custom AWT Exception Handlers.
  • [FEST-284] – Call scrollToVisible when clicking on a button. Thanks to Steve Farrell.

FEST-Swing can be downloaded here (file fest-swing-1.2a4.zip.) FEST requires Java SE 5.0 or later.

Links

Feedback is always appreciated :)

, , , ,

1 Comment

Dean Iverson joins the FEST team!



I’m so happy to announce that Dean Iverson, member of the open source project JFXtras and co-author of “Pro JavaFX Platform,” has joined the FEST team!

Welcome Dean!

(Image taken from Bob Xu’s flickr stream under the creative commons license)

, ,

No Comments

Thoughts about "UI Test Automation Tools are Snake Oil"

I just finished reading "UI Test Automation Tools are Snake Oil" by Michael Feathers. Although I agree with many of the ideas in the article, I also think it contains some hasty generalizations and misplaced blame.

Mr. Feathers points out that “selling UI test automation tools is irresponsible” and these tools are sold “with a dream, a very seductive and dangerous one.” The scenario that he refers to, to my understanding, is the one where tool vendors sell their (expensive) tools promising:

  • “click and type,” quick test generation with a record/playback tool, no coding required
  • test the whole application, including all different use case and data permutations, using this tool

This can be easily interpreted as “with my tool, you will have a comprehensive test suite in no time, and you can hire cheap monkeys to do all the testing.” It is indeed a very seductive promise: spend some money and get what you want fast and with minimal effort, just like “weight loss, without diet and exercise.”

I completely agree with Mr. Feathers that selling something based on a fallacy is irresponsible. At the same time, I also think this is the point where blame is misplaced. Instead of blaming the tool, blame should be shared between tool vendors and the people buying the tool, as long as the business transaction is based on the “seductive dream.” IMHO, this is a people problem: on one hand we have vendors taking advantage of the customers’ lack of knowledge and the customers, that did not do their proper homework on time and by now have a big, untestable mess.

Another good point that Mr. Feathers makes is that UI testing tools are brittle. Selling a UI testing tool promising that the generated test suite will never break is also careless. The fact is, when testing UIs there are many external elements that can introduce false failures. IMHO, it is impossible to fix all of them, but at least, the tool vendor should warn their customers about these limitations and offer ways to overcome them (more on that later.)

I also agree with Mr. Feathers that record/playback doesn’t work. I wish he went into more details to see if we agree based on the same premises. In my opinion, the major weakness of existing record/playback tools is expensive maintenance of the generated tests. Recorded scripts are often long and written in proprietary languages lacking object-oriented features. Modularization/refactoring is hard or impossible, resulting in duplicate test code. The common end result is that changes in the application requires re-recording all tests scenarios, a labor-intensive and error-prone task.

Not everything is black and white. UI test automation tools still have a place. Not every shop has the resources or time to rewrite an application, just to make it more testable. I’ve seen applications with massive code bases, that were not written with testability in mind. Extending or refactoring is scary due to the lack of the safety net that automated tests provide. The only way to test them is through the UI. UI testing can provide the initial safety net, which later on can be enhanced (or replaced) with API-based unit tests.

In his post, Mr. Feathers asks “Developing them open-source? Well, let your conscience be your guide.” I don’t sell a UI test automation tool per se. What I provide is an open source, API-based UI testing library, called FEST (you can find some testimonials here.) I think I’ve been pretty responsible by pointing out that UI testing is fragile and offering ways to overcome this limitation. What I’m missing, and I have to thank Mr. Feathers for it, is a guide on how to test the UI layer in isolation (which I will be doing soon.)

Like I mentioned in a previous post, I’m currently working on my spare time on a playback/recording tool. My intention is to create a tool that generates clean Java code, as if it was hand-crafted, to overcome to what I think are the problems with this technique. We’ll see if I can accomplish this ambitious goal :)

Overall, I liked and enjoyed Mr. Feathers article. It has pretty good points and observations. I wish he backed up his ideas with more details and examples, to sound less emotional and more objective. The problem is in the human factor, not in the tool. Ideally, vendors (in general) should set the right expectations about their products, and customers should have enough knowledge to avoid being taken advantage of. At least, some of us are trying to do the right thing :)

Feedback is always welcome :)

Update: This post has been published at Javalobby.

,

No Comments

Resolutions for 2010


As an attempt to document my plan for this year, the following are tech-related resolutions for 2010:

  1. Learn one or more programming languages.

    I spent most of 2009 working on FEST. Even though I learned a lot more about Swing, enjoyed writing clean and testable object-oriented code, and implemented many interesting features, all the development was done in Java. I think it’s time to learn a new language!

    My plan is to learn at most two languages. Like I mentioned in a previous post, I think that it takes a considerable amount of time and effort to learn a language well. I have worked in Java for quite some time, and I’d love not only to learn a new syntax, but also new programming concepts/paradigms. My intention is to learn Groovy and Scala.

    I wouldn’t want to learn these languages using simplistic exercises. I’d prefer to learn them by working on a non-trivial, useful project. In fact, my plan is to create alternative APIs for FEST-Swing using both Groovy and Scala.

  2. Refresh and increase my knowledge of algorithms.

    I have enjoyed studying design patterns and have been using them both at my day job and on my open source project. Needless to say, it was been a useful and rewarding experience. For one of my side-projects (and to become a better developer,) I’m going to need a deeper knowledge of algorithms, which are also patterns. I already started studying them. My resolution is to not break the chain.

  3. Finish and release the FEST record/playback tool.

    This tool will record user interactions with a Swing UI and generate FEST-Swing UI tests. The goal is to generate clean code, as if it was hand-written. This is something that I wanted to do since 2008, but I was too busy building the open source API. I started working on this project a few months ago. Progress has been slow but steady. I hope to have a preview in a couple of months.

    Many thanks to my good friends Andy Glover, Kirill Grouchnikov and Andres Almiray for their valuable feedback and advice :)

  4. Figure out a way to create a testing library for JavaFX.

    I’ve been working on a robot-based library for functional testing of JavaFX UIs, similar to FEST-Swing. At this moment I’m stuck. FEST-JavaFX needs to work with compiled JavaFX code, which is different to what we see in a JavaFX script. I have to deal with hierarchies of SGNodes, an implementation detail that can change at any time (most likely with Prism.) It seems to make sense for what JavaFX tries to accomplish: to have the same application executed on different device types. I think it’s time to ask my JavaFX-guru friends for help :)

  5. Create a domain-specific language (DSL) for testing UIs.

    The idea here is to create a simple DSL for writing functional UI tests. The target audience are QA engineers that do not know Java. I plan to explore Xtext to accomplish this task.

IMHO, it is an aggressive plan. I hope to be well-organized and focused enough to accomplish most of it :D

Feedback is always welcome! :)

(Image taken from tnarik’s flickr stream under the creative commons license)

, ,

4 Comments

FEST: new JavaFX Maven plugin

I’m back to working on FEST-JavaFX, an open source library for functional testing of JavaFX GUIs. To keep consistency with the rest of FEST modules, I decided to use Maven to compile and build the project.

I blogged some time ago how to compile JavaFX code with Maven. I wasn’t too happy with it, since it was verbose and I’d have to copy/paste the Ant build for every JavaFX project. I found JFrog’s JavaFX Maven plugin and gave it a try. Although configuration was easy, I couldn’t make it work.

The plugin expects the JavaFX jars to be installed in a local Maven repository. This is something that I don’t agree with, for the following reasons:

  • I don’t see the point of having JavaFX jars in a Maven repository, since those jars cannot be distributed (per JavaFX’s license)
  • Installing those jars in a local repository is easy but time-consuming: it needs to be done one by one
  • So far, with each release, the number and some of the names of JavaFX jars change; I wouldn’t want to go through the process of installing them in a local repository every time there is a JavaFX release

Since Maven already supports creating plugins based on Ant, I just had to wrap my existing Ant script with a Maven plugin.

Creating the plugin was really easy, it took no more than 10 minutes. Maven’s documentation and online book are pretty good and they helped me a lot.

The main difference between FEST’s JavaFX Maven plugin and JFrog’s is that FEST’s does not require the JavaFX jars to be installed in a local repository. Instead, it uses an environment variable, JAVAFX_HOME, to locate the path of the JavaFX jars.

I just released version 0.1. Since it is a Maven plugin, I don’t think it is necessary to add a distribution file to the “downloads” page. The plugin can be obtained from our Maven repository.

The following example shows how to use the plugin to compile JavaFX source when the standard “compile” goal is executed:

<build>
  <plugins>
    <plugin>
      <groupId>org.easytesting</groupId>
      <artifactId>fest-javafx-maven</artifactId>
      <version>0.1</version>
      <executions>
        <execution>
          <phase>compile</phase>
          <goals>
            <goal>desktopCompile</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Please note that it is not necessary to specify the JavaFX jars as project dependencies (at least I haven’t had to do it, so far.)

Currently the plugin has only one goal: “desktopCompile”, to compile JavaFX sources under the desktop profile. For more information about configuring the plugin, please visit the plugin’s homepage.

I originally created version 0.1 to satisfy the needs of the FEST-JavaFX project. There is a lot of room for improvement.

Please give the plugin a try. Feedback is always welcome! :)

As an additional note, the Silicon Valley JavaFX user’s group (SvJugFx) will be holding its first meeting, with a live streaming presentation from Richard Bair. The SvJugFx is organized by my good friend and FEST teammate Stephen Chin. See you there!

, , , ,

6 Comments

FEST-Reflect 1.2: Fluent Interface for Java Reflection

We are proud to announce that FEST-Reflect 1.2 is out!

FEST-Reflect is a Java library that provides a fluent interface that simplifies the usage of Java Reflection and JavaBeans Introspection, resulting in improved readability and type safety. It supports class loading, access to static inner classes constructors, methods and fields, and more!

Example:

Person person = constructor().withParameterTypes(String.class)
                             .in(Person.class)
                             .newInstance("Yoda");
 
method("setName").withParameterTypes(String.class)
                 .in(person)
                 .invoke("Luke");
 
field("name").ofType(String.class)
             .in(person)
             .set("Anakin");
 
List<String> powers = field("powers").ofType(new TypeRef<List<String>>() {})
                                     .in(jedi)
                                     .get();

Release notes

Bug

  • [FEST-68] – FEST-Reflect is catching my RuntimeException while it should not! (issue 310.) Thanks to Francis.ANDRE.
  • [FEST-257] – FEST-Reflect should throw exception if static inner class is not found.

Improvement

  • [FEST-256] – Replace constructor calls with fail-fast static factory methods.

New Feature

  • [FEST-235] – Add API to reflect bean properties. Thanks to Jean-Francois Poilpret.

    Example:

    // equivalent to calling "getName()"
    String name = property("name").ofType(String.class)
                                  .in(person)
                                  .get();

FEST-Swing can be downloaded here (file fest-reflect-1.2.zip.) FEST requires Java SE 5.0 or later.

Links

Feedback is always appreciated :)

, , , ,

2 Comments