Monday, December 31, 2007

Publish to your blog directly from Google Docs

Do you know that you can publish documents directly from Google Docs ?
It's very handy and you can use Google Docs editor with its full power to add formating, links, pictures, tables and check spelling.

If you usually post large pieces of text with formatting t your blog you should take this seriously.

Help can be found here.

Saturday, December 29, 2007

Test Driven Development and GUI Testing: Unit tests

Previous article:Test Driven Development and GUI Testing: Temperature Converter details

We now have an idea of the application requirements as we defined our Use Case: Convert Temperature.
Using Test Driven Development we will implement this use case. We are also using UML to maintain our model.

Main project

Using Netbeans 6.0
  1. Create a Java project (File | New Project... | Java | Java Application)
  2. Name the project something like TDD
  3. Select the desired location
  4. Uncheck Create Main Class
  5. Finish

UML Project

  1. Create a new UML project (File | New Project... | UML | Java Platform model)
  2. Name it something like TDD-UML
  3. Choose previous location. If the previous project folder was TDD select this project folder
  4. Finish

Create Class Diagram

  1. Create a Class Diagram and name it TDD Class Diagram
  2. Create a package tdd dragging a package from the palette
  3. Create a TemperatureConverter class
  4. Create a Nested Link from TemperatureConverter to tdd package
Now, you should have a diagram like this


Generate code

  1. Select the tdd package
  2. Right click and select Generate Code...
  3. Select the previously created project, TDD as Target Project
  4. Select Source Packages as Source Root
  5. Press OK
We now have the structure of an empty class inside the tdd package

Add testing infrastructure using XTest

  1. Select TDD project node in Projects
  2. Right click and select New | Other...
  3. Select Testing Tools and then XTest infrastructure (if it's not there go to the plugin manager and install it)
  4. Finish

Generate test cases

  1. Right click on the TemperatureConverter class node in the TDD project
  2. Select Tools | Create JUnit Test...
  3. IMPORTANT: Select JUnit 3.x
  4. Accept the name tdd.TemperatureConverterTest for the class
  5. Select Location: Unit Test Packages
  6. OK
Now we will add our tests, even though our TemperatureConverter class is not clearly defined yet. Adding those tests will help us define our TemperatureConverter class and it's the essence of Test Driven Development.

Adding the test class to the UML model

  1. Right click on the editor window of the TemperatureConverterTest class
  2. Select Reverse Engineer...
  3. Select Use Existing UML Project and Target Project as TDD-UML
  4. OK

Complete the TDD Class Diagram

  1. Select TDD Class Diagram in the editor
  2. Drag and drop the TemperatureConverterTest class, which is inside the tdd package node, from the Model (TDD-UML | Model | tdd) to the diagram. Sometimes it's also needed to drag and drop the tdd package.
  3. You may want to change the color of the class to recognize it visually as a test, right click on it and select Class | Background color, we use green in this example.

Define the tests

Accordingly to our use case in TemperatureConverter we can define two tests
  • testCelsiusToFahrenheit, to test our converter
  • testInvalidCelsiusTemperature, to validate that wrong temperatures are detected
As a method to verify our converter we will use some results obtained from an external converter source and we will build a table with some representative values.
An online converter can be found at http://www.onlineconversion.com/temperature.htm.
Let's add these components to get our tests finished.

Add the tests methods

In TDD Class Diagram
  1. Right click on the TemperatureConverterTest Operations compartment and select Insert Operation... and insert the operations mentioned previously
  2. add testCelsiusToFahrenheit method
  3. add testInvalidCelsiusTemperature method

Add conversion table

In TDD Class Diagram
  1. Right click on the TemperatureConverterTest Attributes compartment and add attribute conversionTable, set its type to Map<Integer, Integer> and be sure to check the static and final properties
  2. Set the default value to new HashMap<Integer, Integer>()
We should have now this diagram

Generate the code

  1. Select the TemperatureConverterTest class only (be sure that no other component is selected), right click and Generate Code...
  2. Be sure to select Source Root: Unit Test packages
  3. OK

Initialization code

  1. Right click on the ConversionTable attribute and select Navigate to Source...
  2. If some imports are missing just press Shift+Ctrl+I
  3. Initialize the conversion table to this code, just after its definition

    static {

    // initialize (c, f) pairs

    conversionTable.put(0, 32);

    conversionTable.put(100, 212);

    conversionTable.put(-1, 30);

    conversionTable.put(-100, -148);

    conversionTable.put(32, 90);

    conversionTable.put(-40, -40);

    conversionTable.put(-273, -459);

    }

  4. Add this method (the prefix test is important for JUnit 3.x)

    public void testCelsiusToFahrenheit () {

    for (int c: conversionTable.keySet()) {

    int f = conversionTable.get(c);

    String msg = "" + c + "C -> " + f + "F";

    assertEquals(msg, f, TemperatureConverter.celsiusToFahrenheit(c));

    }

    }


  5. Add this method (the prefix test is important for JUnit 3.x)

    public void invalidCelsiusTemperature () {

    try {

    int f = TemperatureConverter.celsiusToFahrenheit(-274);

    } catch (RuntimeException ex) {

    if (ex.getMessage().contains("below absolute zero")) {

    return;

    }

    else {

    fail("Undetected temperature below absolute zero: " + ex.getMessage());

    }

    }


    fail("Undetected temperature below absolute zero: no exception generated");

    }

  6. If some imports are missing just press Shift+Ctrl+I

Create the real code

We have now the tests for code that still doesn't exist. If everything was fine, you should see a light bulb in the line where TemperatureConverter.celsiusToFahrenheit is invoked and gives you the to Create Method celsiusToFahrenheit(int) in tdd.TemperatureConverter
But, sometimes things use to fail, and if it's not appearing use this work around:
  1. Double click on the TemperatureConverter class node, and go to the editor, add an empty line, delete it, just to force the change, then save the file.
  2. Is this a Netbeans bug ?
Now Create Method celsiusToFahrenheit(int) in tdd.TemperatureConverter should have appeared, select it and create the method.

Running the tests

Our code compiles now, and we are in the condition of running the tests. After all, we are using Test Driven Development, don't forget it.
Go to the TDD project node and
  1. Right click and select XTest | Run unit Tests...
These tests will fail, because we haven't already implemented the celsiusToFahrenheit conversion method.
We obtain something like this



We can see that one test failed because celsiusToFahrenheit converter was not implemented and the other because this method didn't generate the expected exception on an invalid temperature.

So, what's left is to go there an implement it !

Implement celsiusToFahrenheit

We need to replace the default implementation of this method

throw new UnsupportedOperationException("Not yet implemented");


with

return (int)Math.round(celsius * 1.8 + 32);


Remember to change the parameter name from i to celsius.

Run the tests again

Running the tests again we will see how one test succeed but the other fails with the message

Undetected temperature below absolute zero: no exception generated

That's because we are expecting an exception to be thrown if the temperature is below the absolute zero but our first attempt doesn't do that.

Let's add this condition, but we first need the ABSOLUTE_ZERO_C constant.

  1. Synchronize the code with the UML by right clicking on the TemperatureConverter editor and then Reverse Engineeer...
  2. Select Use Existing UML PRoject and set it to TDD.
  3. Then OK and Yes to all.

Add ABSOLUTE_ZERO_C constant

This is the absolute zero temperature in Celsius. Now, our code and model are synchronized.

Go to the TDD Class Diagram.

Right click on the TemperatureConverter Attributes compartment in the class diagram

  1. Add ABSOLUTE_ZERO_C, with type int, default value set to -273, and check static and final in properties
  2. Select the TemperatureConverter class and right clicking select Generate Code..., be sure to select Source Root: Source pckages
  3. Select Add mergers to existing source
  4. OK


Now

  1. Select the celsiusToFahrenheit method and then right clicking Navigate to Source...

Modify celsiusToFahrenheit

Add the absolute zero check

if (celsius < ABSOL?UTE_ZERO_C) {

throw new RuntimeException("Invalid temperature: " + celsius + " below absolute zero");

}

return (int)Math.round(celsius * 1.8 + 32);





For some reason (Netbeans bug ?) conversionTable disappear from the Class Diagram and from the model, but it's still there because it's not possible to add another attribute with the same name and if code is generated the attribute is still there.

Run the tests one more time

And both tests pass


Next article

Next article Test Driven Development and GUI Testing: Functional tests will show how to build the swing based GUI using Test Driven Development approach and we will obtain our working and fully tested application.

Friday, December 28, 2007

Jemmy library problem with multiscreen captures

There's a small, but annoying, problem in the way the screen is capture with Jemmy's captureScreen method, as far as I know it's only evident in multiscreen configurations.
The root of the problem is the use of Toolkit.getDefaultToolkit().getScreenSize() which is not multiscreen aware and thus virtual screen bounds are incorrect.

I've detected the problem writing some Java Swing GUI tests that capture the screen or part of it as they run in multiscreen configurations and got weird results. After some investigation and debugging I've found the use of Toolkit.getDefaultToolkit().getScreenSize() in PNGEncoder module.
Anyway, I'm providing a link to a patch using multiscreen aware display dimensions available from GraphicsConfiguration and GraphicsDevice.

The captures you may be obtaining are either incomplete or noisy like the examples shown here.
Showed before and after applying the patch.
Screen capture
Text field capture
Patch
Patch can be downloaded from http://codtech.com/downloads/jemmy-encoder-multiscreen.patch.

Thursday, December 27, 2007

Test Driven Development and GUI Testing: Temperature Converter details

We will be introducing Test Driven Development concepts applied to GUI testing in this series. Obviously, to do it we need a GUI.
In this case we are using a very simple GUI application which is a variation of the Temperature Converter used in the Java Tutorials: Lesson: Learning Swing with the NetBeans IDE.


The original GUI looks like this. However we are introducing some modifications to the design.
One of the problems is that errors are not reported to the user, and the other, which is perhaps a matter of taste is the use of a label to show the result and no button to close forcing the user to use windows manager's close button.

Use Case: Convert Temperature
Although this example is extremely simple, it doesn't hurt if we apply the same set of techniques we would be applying in a more complex problem.















Actor Action System Response
1. The user enters a temperature in Celsius, and then press Convert
2. The system converts the temperature to Fahrenheit and the result is presented to the user
3. The user wants to enter another temperature and continues from 1 or presses Close to exit.
4. The process finishes.
Alternative Courses
Temperature is below absolute zero
Indicate error
Invalid input characters entered
Indicate error


Next article, shows how to start developing this simple use case using Netbeans IDE 6.0, UML, and Test Driven Development.

Wednesday, December 26, 2007

Test Driven Development and GUI Testing: First things first

As you can guess from some previous articles (e.g: http://dtmilano.blogspot.com/2007/04/pyhton-and-test-driven-development-part.html) I'm a proud supporter of Test Driven Development and I've been using it successfully in most of my projects. There are plenty of online resources explaining TDD so we are not going deeper on the subject. What it is not so easy to find is how to use TDD in GUI development and this is the article thread we are stating now.
We will use Netbeans 6 IDE to develop a very simple application (Temperature Converter: lets you convert temperatures in different units, pretty obvious duhh...) presenting a swing GUI which is our testing target. As usual JUnit is used for the testing infrastructure and Jemmy for the GUI components.
We will also be adding some UML to the recipe

Despite the fact that this is an extremely simple application, we will also drive the model from the UML perspective and at least this will help you understand how this can be done for more complex projects.

This Temperature Converter is a slight variation of the one appearing in the Java Tutorials: Lesson: Learning Swing with the NetBeans IDE.

Fasten you seat belts. We are ready to launch.

Next article: Test Driven Development and GUI Testing: Temperature Converter details

Monday, December 03, 2007

Dogfish Administration Console Watchdog for Glassfish


Have you ever been caught by this screen ?
Having to login to the machine where Glassfish domains are installed just to run a simple administrative command to get the server online again. Perhaps requiring a trip to the data center.

The message says:

The domain can be restarted using the asadmin start-domain command. In order to restart the domain:
  • login to the machine where domain is installed.
  • run /bin/asadmin list-domains to ensure that the domain shutdown process is complete
  • run /bin/asadmin start-domain command with appropriate parameters.

Well, I decided to start this tool would help to alleviate this situation.
Dogfish is kept as simple as possible (KISS philosophy), it's a secure web server, based on '
com.sun.net.httpserver' and relative classes, relies on Glassfish authentication, and let's you send the administrative commands to start, stop and restart domains and will be able to define some actions to restart domains in case of failure or no response.
More on this later.

Comments are gladly welcome.

Preview