Using JUnit to unit test IBM Rational HATS applications

Off
Strongback Consulting

Why unit testing?

Any developer worth their salt, uses unit tests to validate that their code satisfies the task or tasks the code is supposed to do. Unit testing encourages modular development. Junit for Java was one the first and certainly the most well known. Other frameworks for other languages have popped up all over the industry for other languages (nUnit for .NET, cppUnit for C++, etc). I won’t lecture on the benefits, but will refer you to other sites for proof:
Why not just use a debugger?
Why not just use System.out.println()?
Why use JUnit for testing?

Why it’s difficult to unit test HATS

Not all HATS applications require complex testing. Many (and I mean MANY) HATS applications just use some simple customizations and one of the existing out of the box templates. Very few use anything more complex than a custom page template, and rarely ever use any custom Java code. This is quite normal. IF this is your scenario, and you have no custom Java code, then skip down to the bottom of the article. 

However, some shops might need more customization than what is available out of the box. This is where some unit testing may be needed.

HATS relies on a runtime (Telnet connection) back to a host system. With JUnit, you really do not want to have to run a test that only tests a single class while having the whole system running and connected to the host. This is similar to issues with unit testing EJB 2.x, where you could really only test in a live environment and it required a secondary framework such as Cactus to get the results out of the live environment.

This can be overcome by using what’s called mocking and stubbing. By that, I mean mocking the runtime connection and stubbing the API’s results. Mockito and Powermock are excellent tools for mocking, and can be used with HATS to mock the runtime. However, there is a major hurdle in using this, it is because when running a JUnit test that uses the mocking framework, you’ll run into a NoClassFoundException issue, where the mocking framework cannot stub a return result because it cannot find the class to stub. Fear not, however, as we’ve found the solution. Keep reading.

Introducing Mocking and Stubbing with Mockito

This presentation (courtesy of Richard Paul), covers Mockito pretty well. Mockito also has EXCELLENT JavaDoc detailing the ins and outs of using the framework (it is such excellent JavaDoc, I use it as an example of how a developer should be creating Javadoc for his/her custom code). 

Mocking in Java with Mockito from Richard Paul

Mockito is excellent at creating concrete mock objects. One of the first things you may want to mock, is a specific host screen. This is detailed below. Mockito cannot, however, mock static classes. Those must be handled by PowerMock. Keep in mind, that there are several HATS API objects that are static, and you will have to use PowerMock to mock those items (such as the ECLPS class).

Mocking i or z Screens

When we were creating this framework, we came across a neat little constructor in the HATS API, that allows you to create a HostScreen object from an XML file. If you pass in an XML Document object  to the constructor new HostScreen(), you will get an object you can then interact with. The HATS Screen Captures are XML files, but you must read them in, and get them into a org.w3c.dom.Document object. This little snippet above will do that for you. 

protected HostScreen buildHostScreen(String fileName) 

    throws UnsupportedEncodingException, ParserConfigurationException, IOException , SAXException  {
      //Courtesy of Strongback Consulting – www.strongback.us      
        URL url=this.getClass().getResource(fileName);        
        String file= URLDecoder.decode(url.getFile(), “UTF-8”);
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document screencapture = builder.parse(file);
        HostScreen hostscreen = new HostScreen(screencapture);    
        return hostscreen;
    }

Overcoming a key HATS impediments (missing code)

So, if you’ve attempted to mock and stub, you will eventually run into a NoClassFoundException on com.ibm.eNetwork.HOD. You can try and look in the HATS runtime jar files (any of them), but you will not find it.

On a recent project, we were working with one of the HATS product architects and asked about this particular dilemma. As it turned out, the reference to this object is never used, and thus not ever included in the hatsruntime.jar, nor any included HATS jar files. It is a class that is part of the Host on Demand API, and only parts of that API are actually included in the HATS toolkit – only those that are actually used. By simply creating an empty class, we were finally able to get this mock to work! 

Just create a new package, and a new class in the package as follows:

package com.ibm.eNetwork.HOD;

public class ScreenHistory {
//this is never used, but required to complete 
//a mock object
}

Now, you should be able to build your mock object.

What to test

If you have a Java class that does not use any HATS API (such as a convenience class, a POJO, or utility class), then you likely do not need to mock it. However, there are several types of HATS objects that require mocking. These include:
    • Business logic – use the snippet of code above to help you create the HostScreen object
    • Custom Widgets 
    • Custom Components
    • Custom Screen Recognition (yes, this is a real thing you can create to handle custom screen recognition if all the other options leave you dry)
    • Macro Custom Actions (yep, another thing you can create custom)
In general, not only can you mock these items, but you should mock the objects above. Testing them in a mock framework will prove highly fruitful. You can debug the code in isolation, without being connected to a mainframe or AS/400. You do need to gather screen captures first. This is beneficial also, because in some conditions, you might have to have different test data everytime you go to a specific screen. Mocking, allows you to use the same screen capture for multiple tests. Also, you can run through multiple scenarios in a single unit test. Just grab screen capture for each scenario. 

Guidelines

Here are a few general guidelines to to help you with this process:
    • “Pull up” common code into a super class, so all subclasses can reuse the same code (keep it D.R.Y.)
    • It may not seem like it at first, but unit testing is FASTER than debugging in a live environment.
    • Debugging JUnit code is even faster. 
    • Be sure to account for multiple scenarios.
    • Make it part of your continuous integration plan – have Team Concert, or Jenkins run a build on every checkin of code.

Other types of testing to be concerned with

Unit testing only goes so far. It is not a replacement for full system testing, or security testing. Keep these testing types in mind also:
    • Functional testing – RFT, and Selenium. RFT has the benefit of being able to run function tests against a telnet application (5250 or 3270). Reuse the same data in HATS
    • Performance Testing
    • Policy and compliance testing (ADA, screen readers, etc)
    • Security testing (white box, and black box)

Comments are closed.