Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Better Exception Testing in ICE with J-Unit

Better JUNIT Testing

In many developing software applications (including ICE), unit testing has become a vital role in developing reliable, safer, and more robust products. JUNIT is one of the tools that can be used to run unit and integration tests for Java-based applications in test-driven development. Below is an example of utilizing better methods for developing unit tests for handling Exceptions on tested objects with the testing tool.


Here is a sample exception try/catch statement within a JUnit test:

   //A class that tests the operation
   //StringToIntegerUtility.customStrToInt(String number)
   @Test
   public void checkStringToInteger() {
       //Local declaration
       int number;
       String number = "Not a number";
       boolean expectedFail = false;
   
       //Setup class
       StringToIntegerUtility utility = new StringToIntegerUtility();
   
       //Call operation with try/catch statement
       try {
           number = utility.customStrToInt(number);
       } catch (NumberFormatException e) {
           //We expect this to happen
           expectedFail = true;
       }
       
       //Test is valid if it failed
       assertTrue(expectedFail); 

When the utility operation is called, there has to be a try/catch statement. Try/catch statements can clutter code and confuse some forms of unit testing. What can be done is to separate these specific exception unit tests into their own methods and have JUNIT check the exceptions. Below is a better way to handle the exceptions in a JUNIT test.

   //A class that tests the operation
   //StringToIntegerUtility.customStrToInt(String number)
   @Test(expected=java.lang.NumberFormatException.class)
   public void checkStringToInteger() throws NumberFormatException {
       //Local declaration
       int number;
       String number = "Not a number";
   
       //Setup class
       StringToIntegerUtility utility = new StringToIntegerUtility();
   
       //Call operation, and this operation should
       //throw an exception.
       number = utility.customStrToInt(number);
   
   } 

This method cuts down on some of the more excessive try/catch statements in unit testing. It also helps to modularize the codebase in unit testing by separating out the exception cases from other tests. The expected statement catches the exception when it is thrown. Nevertheless, there are some limitations to this method. For example, when the exception is thrown, the testing ends in that method. Thus, if one were to need to write more expansive tests that utilize many exceptions, there would need to be an individual method for each exception. Secondly, this can pose a problem for identifying messages in exceptions for generic Exception handling or classes with multiple types of references. The second issue can be resolved by using the thrown.expect(class) and thrown.expectMessage(String) from the JUnit API. These types of calls are declared within the method and not annotated.


Locations of Exceptions

There are many areas in NiCE where native and customized exceptions are thrown and caught within the applications. Many of them are required by overloaded applications, while others are created to catch specific errors in NiCE. Below is a list of the operations that throw and/or catch exceptions within NiCE's general architecture. It will also mention if the error prints out a stack trace or not. If it does, it will mention whether or not the operation is handled within the method. Note that just printing a stack trace does not constitute an operation as "being handled". Returning false on a boolean method for a failed initialization of another method because of a try/catch statement is an example of "handling" an issue.


This is a table for exceptions caught within each method.

ICEClient
Class Method Exception Prints a stack trace? Handles error?
EclipseFormWidget display() PartInitException Yes No
EclipseTestEditor display() PartInitException Yes No
NiCEFormEditor addPages() PartInitException Yes No
NiCEMatrixComponentSectionPart modify() NumberFormatException No No
NiCEGeometryPage createFormContent() PartInitException Yes No
GeometryApplication commit() ClassCastException No No
RealSpinner validateText() NumberFormatException No Yes
ShapeMaterial applyShape() NumberFormatException No No
Itemprocessor run() InterruptedException Yes No


ICECore
Class Method Exception Prints a stack trace? Handles error?
failedAuthorization() IOException Yes No
BasicAuthSecuredContext getResource() MalformedURLException No Yes
BasicAuthSecuredContext handleSecurity() LoginException Yes Yes
NiCECore start() ServletException, NamespaceException, IOException All yes All no
NiCECore setLocation() CoreException Yes Yes
NiCECore loadDefaultAreaItems() IOException, CoreException All yes Yes, No
SimpleLogin login() IOException, UnsupportedLoginException All yes All yes


NiCEDataStructures


Class | Method | Exception | Prints a stack trace? | Handles error? ------------- | ------------- | ------------- | ------------- | ------------- DataComponent, Entry, Form, MasterDetailsComponent, MasterDetailsPair, MatrixComponent, TableComponent, ComplexShape, GeometryComponent, PrimitiveShape, Transformation, NiCEObject, NiCEResource | loadFromXML() | NullPointerException, JAXBException, IOException | All yes | All yes Entry | setValue() | NumberFormatException | No | Yes AbstractShape | getProperty() | IndexOutOfBoundsException | No | Yes
NiCEObject | persistToXML() | NullPointerException, JAXBException, IOException | Yes | No NiCEResource | setContents() | NullPointerException | No | Yes


NiCEItem


Class | Method | Exception | Prints a stack trace? | Handles error? ------------- | ------------- | ------------- | ------------- | ------------- Item | process() | CoreException | Yes | No
Item | loadFromXML() | IOException, JAXBException, IOException | Yes | Yes Item | persistToDatabase() | Exception | Yes | Yes
Item | deleteFromDatabase() | Exception | Yes | Yes Item | updateToDatabase() | Exception | Yes | Yes
Item | loadFromDatabase() | Exception | Yes | Yes JobLaunchAction | createSession() | JschException | Yes | No
JobLaunchAction | BufferedWriter() | IOException | Yes | No
JobLaunchAction | isLocalHost() | UknownHostException | Yes | No JobLaunchAction | launchLocally() | IOException | Yes | Yes JobLaunchAction | launchRemotely() | InterruptedException, JschException, FileNotFoundException, SftpException | All yes | All no TaggedOutputWriterAction | execute() | IOException | Yes | Yes JobLauncher | createOutputFiles() | CoreException, IOException | All yes | All no JobLauncher | setupForm() | CoreException | Yes | No JobLauncher | loadFromXML() | IOException, JAXBException, NullPointerException | Yes | Yes MultiLauncher | run() | InterruptedException | Yes | No JobProfile | process() | CoreException | Yes | No


This is a table for a list of exceptions thrown within each method of each class. Usually when an exception is thrown, an issue is handled in a higher level operation/method. Therefore "handles error" does not apply here.


NiCEClient


Class | Method | Exception Thrown | Prints a stack trace? ------------- | ------------- | ------------- | ------------- EntryComposite | EntryComposite() | RuntimeException | No NiCEDataComponentSectionPart | NiCEDataComponentSectionPart() | RuntimeException | No NiCEFormEditor | Init() | RuntimeException | No NiCEMatrixComponentSectionPart | NiCEMatrixComponentSectionPart() | RuntimeException | No NiCESectionPage | NiCESectionPage() | RuntimeException | No NiCETableComponentSectionPart | NiCETableComponentSectionPart() | RuntimeException | No ShapeTransient | read() | IOException | No ShapeTransient | write() | IOException | No Tube | read() | IOException | No Tube | write() | IOException | No


NiCECore


Class | Method | Exception Thrown | Prints a stack trace? ------------- | ------------- | ------------- | ------------- BasicAuthSecuredContext | handleSecurity() | IOException | No BasicAuthSecuredContext | login() | IOException, UnsupportedCallbackException, LoginException | No SimpleLogin | abort() | LoginException | No SimpleLogin | commit() | LoginException | No SimpleLogin | login() | LoginException | No NiCECoreIApplication | start() | Exception | No


NiCEDataStructures


Class | Method | Exception Thrown | Prints a stack trace? ------------- | ------------- | ------------- | ------------- Form | addComponent() | RuntimeException | No PainfullySimpleEntry | loadFromPSFBlock() | IOException | No PainfullySimpleForm | loadComponents() | IOException | No PainfullySimpleForm | loadEntries() | IOException | No NiCEJAXBManipulator | read() | JAXBException, IOException | No NiCEJAXBManipulator | write() | JAXBException, IOException | No NiCEResource | NiCEResource() | IOException | No NiCEResource | setContents() | IOException, NullPointerException | No


NiCEItem


Class | Method | Exception Thrown | Prints a stack trace? ------------- | ------------- | ------------- | ------------- Item | Item() | RuntimeException | No Item | loadFromPSF() | IOException | No SerializedItemBuilder | SerilaizedItemBuilder() | IOException | No


References

http://weblogs.java.net/blog/johnsmart/archive/2009/09/27/testing-exceptions-junit-47


http://kentbeck.github.com/junit/javadoc/4.10/org/junit/rules/ExpectedException.html

Back to the top