Monday, December 31, 2007
Publish to your blog 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
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- Create a Java project (File | New Project... | Java | Java Application)
- Name the project something like TDD
- Select the desired location
- Uncheck Create Main Class
- Finish
UML Project
- Create a new UML project (File | New Project... | UML | Java Platform model)
- Name it something like TDD-UML
- Choose previous location. If the previous project folder was TDD select this project folder
- Finish
Create Class Diagram
- Create a Class Diagram and name it TDD Class Diagram
- Create a package tdd dragging a package from the palette
- Create a TemperatureConverter class
- Create a Nested Link from TemperatureConverter to tdd package
Generate code
- Select the tdd package
- Right click and select Generate Code...
- Select the previously created project, TDD as Target Project
- Select Source Packages as Source Root
- Press OK
Add testing infrastructure using XTest
- Select TDD project node in Projects
- Right click and select New | Other...
- Select Testing Tools and then XTest infrastructure (if it's not there go to the plugin manager and install it)
- Finish
Generate test cases
- Right click on the TemperatureConverter class node in the TDD project
- Select Tools | Create JUnit Test...
- IMPORTANT: Select JUnit 3.x
- Accept the name tdd.TemperatureConverterTest for the class
- Select Location: Unit Test Packages
- OK
Adding the test class to the UML model
- Right click on the editor window of the TemperatureConverterTest class
- Select Reverse Engineer...
- Select Use Existing UML Project and Target Project as TDD-UML
- OK
Complete the TDD Class Diagram
- Select TDD Class Diagram in the editor
- 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.
- 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
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- Right click on the TemperatureConverterTest Operations compartment and select Insert Operation... and insert the operations mentioned previously
- add testCelsiusToFahrenheit method
- add testInvalidCelsiusTemperature method
Add conversion table
In TDD Class Diagram- 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
- Set the default value to new HashMap<Integer, Integer>()
Generate the code
- Select the TemperatureConverterTest class only (be sure that no other component is selected), right click and Generate Code...
- Be sure to select Source Root: Unit Test packages
- OK
Initialization code
- Right click on the ConversionTable attribute and select Navigate to Source...
- If some imports are missing just press Shift+Ctrl+I
- 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);
}
- 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));
}
}
- 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");}
- 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.TemperatureConverterBut, sometimes things use to fail, and if it's not appearing use this work around:
- 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.
- Is this a Netbeans bug ?
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
- Right click and select XTest | Run unit Tests...
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 methodthrow 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
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.
- Synchronize the code with the UML by right clicking on the TemperatureConverter editor and then Reverse Engineeer...
- Select Use Existing UML PRoject and set it to TDD.
- Then OK and Yes to all.
Add ABSOLUTE_ZERO_C constant
Go to the TDD Class Diagram.
Right click on the TemperatureConverter Attributes compartment in the class diagram
- Add ABSOLUTE_ZERO_C, with type int, default value set to -273, and check static and final in properties
- Select the TemperatureConverter class and right clicking select Generate Code..., be sure to select Source Root: Source pckages
- Select Add mergers to existing source
- OK
Now
- 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 passNext 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
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
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
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: |
|
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.
Comments are gladly welcome.
Preview