Blog from May, 2009

Work Completed

  • Attended CET Staff Meeting
  • Downloaded JMock 2.5.1 and added it to an eclipse plugin.
  • Started working with some code that uses JUnit and JMock to learn more about using JMock for the Data Catalog testing framework. I also started a blog entry that gives an introduction to JUnit and JMock and I will add more text next week along with a complete example so others can learn from what I have done and so I can capture lessons learned as I use JMock.
  • Started setting up some test classes to begin building the Data Catalog so that unit tests become an integral part of the development of the Data Catalog and not something that happens after classes are designed. This will also allow the unit tests to evolve with the class.

Work Planned

  • Monday - Holiday
  • Attend CET Staff Meeting Thursday, 3 - 4pm
  • Take a closer look at JMock for unit testing the new Data Catalog. I will be writing a blog entry about what I learn along with a complete example of using JMock for unit testing with Eclipse.
  • Start setting up unit testing framework for the new Data Catalog

Comments

This week went as planned. I expect to continue learning more about JMock and JUnit next week and adding more text to my blog entry.  Also, we will find out whether we have been invited for a full TRANSIMS proposal this week so I might be writing more text for the proposal towards the end of the week.

Introduction


The intent of this blog entry is to track what I learn while working through an example using JUnit 4.3.1 and jMock 2.5.1. This entry is a work in progress and will be updated as I go along. By the end of this, I think you will agree that jMock is awesome and can provide you with a very good tool to mock-up something that might be heavyweight and unit testing in general is absolutely critical to production software.

JUnit


Let's get the introductions out of the way for those who don't know about JUnit. Put simply, JUnit is an open source testing framework used to test source code. It is critical for any production application to include a thorough set of unit tests so that errors can be detected immediately, even before checking new code in. Every class should have a unit test to verify that it behaves as the author expected and to ensure this is the case, a unit test should be written along with the new class so that tests can be set up immediately. Any subsequent changes to the class can be verified by re-running its test before the changes are commited to the repository. If an untested scenario is discovered, then it can be added to the unit test so that the unit test evolves with the class so that future changes that cause the same problem can be detected immediately and fixed.

jMock


jMock is a library that supports test-driven development of Java code with mock objects. Mock objects are useful because they can help you test the interaction between the objects in your program. Here are some bullet points from their website:

The jMock library:

  • makes it quick and easy to define mock objects, so you don't break the rhythm of programming.
  • lets you precisely specify the interactions between your objects, reducing the brittleness of your tests.
  • works well with autocompletion and refactoring of your IDE
  • plugs into your favorite test framework
  • is easy to extend

Now, imagine you need an object that requires an LDAP (lightweight directory access protocol) server to construct. Now, you could start an LDAP server, give it some data, run your test and then tear it down, but that's a lot of work and more closely resembles integration testing. However, a faster alternative would be to use jMock to mock up an object that returns the data you need. Mocking up objects is only the tip of the iceberg. You can also set expectations of objects (e.g. this method is only called once), set the order methods should be called in, test multi-threaded code, etc.

Example


In this example, we will create a mock object of a Sensor with jMock and add it to a SensorNetwork. We will set the expectation that the sensor receive a message from the sensor network. If no message is received, then the test will fail. This example is intended to be simple in order to illustrate the potential of jMock. It is worthwhile to note that we will extend MockObjectTestCase which uses the legacy JUnit 3 classes. The reason for this is that eclipse comes bundled with JUnit 4.3.1 and to use the @RunWith(JMock.class) notation of the latest version of jMock requires JUnit 4.4 or later. To add JUnit 4.4 or later, we would have to delete the JUNIT4 folder from the Eclipse plugins directory to avoid a security exception thrown because Eclipse will load it's JUnit 4 before ours. We want to avoid altering the Eclipse plugins directory, so we will use as much JUnit 4 notation as possible until the next Eclipse update. This example only would require a few minor modifications to run with the latest jMock using JUnit 4.4+ so if you want, you can make the altercation and see the jMock website for the minor changes to our test case.

Setup

  1. Get the plugin org.jmock (2.5.1) from MAEviz SVN (svn+ssh://subversion.ncsa.uiuc.edu/CVS/ncsa-plugins).
  2. JUnit 4.3.1 or later.

That's it for external plugins. Now, we'll need to create a project to contain our class under test and a project to contain the tests. I prefer the following packaging conventions:
ncsa.myexample - eclipse plugin
ncsa.myexample.tests - eclipse fragment with ncsa.myexample as the host plugin

After creating those projects, we'll need to create something to mock up and test. First, we are going to create a simple Sensor interface that can receive a message and a SensorNetwork class that contains some sensors and can publish messages to them.

Sensor.java
// interface class for a sensor

// send the sensor a message
public void receive( String message );
SensorNetwork.java
// contains a network of sensors, simplified with one real method to publish messages

private List<Sensor> sensors;

public void publish( String message)
{
  for(Sensor sensor : getSensors()) {
    sensor.receive( message );
  }
}

public void addSensor(Sensor sensor)
{
  getSensors().add( sensor );
}

public List<Sensor> getSensors()
{
  if(sensors == null) {
    sensors = new LinkedList<Sensor>();
  }
  return sensors;
}

Next, we need to create a test class to test out our sensor. You should create the following class in your test fragment:

SensorNetworkTest.java
public class SensorNetworkTest extends MockObjectTestCase {


  SensorNetwork network;

  @Before
  public void setUp() throws Exception
  {
    network = new SensorNetwork();
  }

  @Test
  public void testOneSensorReceivesMessage() throws Exception
  {
    // Our mock object
    final Sensor sensor = mock( Sensor.class );

    // Add our mock sensor to the network
    network.addSensor( sensor );

    final String message = "Hello World";

    // Define Expectations
    checking( new Expectations() {
      {
        oneOf( sensor ).receive( message );
      }
    } );

    // send a message, without this line the test will fail
    network.publish( message );
  }
}

The last step will be to run this as a unit test, not a JUnit Plug-in Test. If you try to run it as a JUnit Plug-in Test, it will fail saying it cannot find certain classes because it needs JUnit 3.8.2 or 3.9.0 so there are definitely some odd dependency issues where some parts of eclipse seem to depend on JUnit and you get a clash between JUnit 3 and JUnit 4. I have only been able to successfully use JUnit 3 as a Plugin Test; however, you would need to remove the JUnit 4 annotations and run everything as JUnit 3.

Problems Encountered


  1. I get a java.lang.SecurityException when trying to run my unit test.
    • This exception occurs because in the Eclipse plugins folder there is a JUNIT4 folder which contains junit.jar version 4.3.1 and lower in the build we are using org.junit version 4.4, which contains JUnit4ClassRunner, a class that we need. The solution is to delete the folder in the plugins directory so that the latest junit 4 is used. There is no way around this because we need that class runner to use JMock.
  2. My tests pass even though I have set an expectation using JMock that does not pass (e.g. method must be called once and it is not called).
    • This can happen if at the top of the class you have not specified that the test should be run with JMock by using the tag @RunWith(JMock.class)

Links


Links to the libraries used in the above example.

Work Completed

  • Final review of submitted TRANSIMS - TRANSviz proposal using MAEviz/Bard as the base platform
  • Updated more wiki text for Bard v1.0 architecture(NCSA-GIS) documenting the current APIs and adding images and started documenting some of the current Bard v2.0 work that has been completed and called int v2.0 of the architecture. This will eventually include the new Data Catalog that will replace the old Data Catalog currently in MAEviz.

Work Planned

  • Finish TRANSIMS/TRANSviz proposal
  • Continue working on the Bard v1.0 wiki and start v2.0 wiki to keep a well documented page available to increase our web presence.

Comments

This week went as planned. I took a personal day on Friday May 22, 2009.  I expect this coming week I will focus more on documenting the Data Catalog API wiki as Shawn and I continue to flesh out the details with the recent comments from Jim Myers.

Work Completed

  • Wrote text and helped edit the TRANSIMS - MAEviz proposal
  • Wrote text for the Bard v1.0 wiki. MAEviz was runner up for the best open source RCP application this year and the most likely reason was the lack of a great web presence. For Bard, we intend to create a better web presence, starting with a wiki that provides good documentation on the design and technologies it uses.
  • Wrote text for the MAEviz v1.0 wiki and uploaded images for both the old MAEviz (D2k version) and the current RCP based version. The intent was to preserve the past work and what was done as well as documenting the current version of MAEviz and increasing its web presence.
  • Attended Cyberarch meeting and CET meeting via google chat.

Work Planned

  • MAEviz - TRANSIMS proposal is the top priority this week. The pre-proposal is due May 20, 2009.
  • Create a wiki for Bard v1.0
  • Create a wiki for the old version of MAEviz to preserve the work done for the precursor of the current MAEviz. Add screenshots and text. Also, add images for the current MAEviz versions wiki.

Comments

This week went as planned.

Work Completed

  • Helped add details to the Data Catalog API, added an image of what we expect the UIRegistry will look like for the import/export options. Also added text to describe what the ModelDescription, PhysicalModel and LogicalModels will look like and how we can utilize a lot of the Tupelo Bean API. I also discussed several parts of the Data Catalog API with Shawn to better understand how he envisioned the various parts working together.
  • As part of the above, I did some digging around to learn more about both the Tupelo Bean API and the usage of Java Beans.  I went through the tutorial on the tupelo page and read through the Java Beans tutorial on Sun's website.

Work Planned

  • Assist Shawn in fleshing out the details of the new Data Catalog API
  • Learn more about the Tupelo Bean API

Comments

This week went as planned. Next week I will be helping Jong put together a TRANSIM proposal.

Work Completed

  • Created an extension point for the UI wizard pages for setting up a context (e.g. an H2 context) so that as new context types become available in tupelo, we can create a setup page appropriate for that context to initialize it (if it makes sense).  This work was tracked as Bard-5, which had been partially completed for a while.  I added the extension point to make this a cleaner implementation than manually adding wizard pages.
  • Bard-56 - Looked into Eclipse property testers, which can be used to test conditions for manipulating menus.  In the RDF page view, the navigating forward and backward arrows were always visible, regardless of whether navigating forward/backwards was possible.  The property testers check whether it is possible to navigate either direction and makes a suggestion that the menu button should be updated.
  • Bard-87 (ttp://jira.ncsa.uiuc.edu/browse/Bard-87) - numerous UI components lacked any unit testing.  This was addressed and several bugs were found and fixed.  The tupelo shapefile adapter for directly reading shapefiles did not implement all constructors that the other shapefile adapters had and this was addressed with unit tests (red/green/refactor) and was tracked as Bard-82 (ttp://jira.ncsa.uiuc.edu/browse/Bard-82).  ApplicationContextModelFactory test was created to test creating context models.  PredicateImageServiceTest was created to test obtaining predicate images.  A bug was found in the class and fixed.  HistoryTest was created to test navigating forward/backwards under various conditions. ContextPageSetupTest was created to test the aforementioned extension point for creating pages associated with creating new contexts.
  • Read through the wiki pages shawn is creating/editing for the data catalog view
  • Attended 2pm CET meeting via google voice chat.

Work Planned

  • Bard-5 - UI for creating new contexts (e.g. new H2 Context, new Simple File Context)
  • Bard-56 Investigate PropertyTesters and use to determine when menus are available
  • Bard-87 (ttp://jira.ncsa.uiuc.edu/browse/Bard-87) several UI features lack unit tests
  • Bard-82 (ttp://jira.ncsa.uiuc.edu/browse/Bard-82) - table adapter for shapefiles
  • Looked over the data catalog wiki pages that Shawn is working on.

Comments

This week went as planned.