Difference between revisions of "Better Exception Testing in ICE with J-Unit"
m (Bennettar.ornl.gov moved page Better Exception Testing with J-Unit to Better Exception Testing in ICE with J-Unit: Mention project in title) |
R8s.ornl.gov (Talk | contribs) (Added parsing to code blocks) |
||
(One intermediate revision by one other user not shown) | |||
Line 1: | Line 1: | ||
− | = Better JUNIT Testing = | + | == 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. | 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. | ||
Line 6: | Line 6: | ||
Here is a sample exception try/catch statement within a JUnit test: | Here is a sample exception try/catch statement within a JUnit test: | ||
− | + | <source lang="java" style="overflow:auto">//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); | number = utility.customStrToInt(number); | ||
− | + | } catch (NumberFormatException e) { | |
− | }</code> | + | //We expect this to happen |
+ | expectedFail = true; | ||
+ | } | ||
+ | |||
+ | //Test is valid if it failed | ||
+ | assertTrue(expectedFail); | ||
+ | |||
+ | }</source> | ||
+ | |||
+ | |||
+ | 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. | ||
+ | |||
+ | <source lang="java">//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); | ||
+ | |||
+ | }</source> | ||
+ | |||
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. | 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 = | + | == Locations of Exceptions == |
− | There are many areas in | + | There are many areas in ICE 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 ICE. Below is a list of the operations that throw and/or catch exceptions within ICE'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. |
Line 79: | Line 85: | ||
| No | | No | ||
|- | |- | ||
− | | | + | | ICEFormEditor |
| addPages() | | addPages() | ||
| PartInitException | | PartInitException | ||
Line 85: | Line 91: | ||
| No | | No | ||
|- | |- | ||
− | | | + | | ICEMatrixComponentSectionPart |
| modify() | | modify() | ||
| NumberFormatException | | NumberFormatException | ||
Line 91: | Line 97: | ||
| No | | No | ||
|- | |- | ||
− | | | + | | ICEGeometryPage |
| createFormContent() | | createFormContent() | ||
| PartInitException | | PartInitException | ||
Line 150: | Line 156: | ||
| Yes | | Yes | ||
|- | |- | ||
− | | | + | | ICECore |
| start() | | start() | ||
| ServletException, NamespaceException, IOException | | ServletException, NamespaceException, IOException | ||
Line 156: | Line 162: | ||
| All no | | All no | ||
|- | |- | ||
− | | | + | | ICECore |
| setLocation() | | setLocation() | ||
| CoreException | | CoreException | ||
Line 162: | Line 168: | ||
| Yes | | Yes | ||
|- | |- | ||
− | | | + | | ICECore |
| loadDefaultAreaItems() | | loadDefaultAreaItems() | ||
| IOException, CoreException | | IOException, CoreException | ||
Line 177: | Line 183: | ||
{| class="wikitable" | {| class="wikitable" | ||
− | !colspan="5" | | + | !colspan="5" | ICEDataStructures |
|- | |- | ||
! Class | ! Class | ||
Line 203: | Line 209: | ||
| All yes | | All yes | ||
|- | |- | ||
− | | Transformation, | + | | Transformation, ICEObject, ICEResource |
| loadFromXML() | | loadFromXML() | ||
| NullPointerException, JAXBException, IOException | | NullPointerException, JAXBException, IOException | ||
Line 221: | Line 227: | ||
| Yes | | Yes | ||
|- | |- | ||
− | | | + | | ICEObject |
| persistToXML() | | persistToXML() | ||
| NullPointerException, JAXBException, IOException | | NullPointerException, JAXBException, IOException | ||
Line 227: | Line 233: | ||
| No | | No | ||
|- | |- | ||
− | | | + | | ICEResource |
| setContents() | | setContents() | ||
| NullPointerException | | NullPointerException | ||
Line 236: | Line 242: | ||
{| class="wikitable" | {| class="wikitable" | ||
− | !colspan="5" | | + | !colspan="5" | ICEItem |
|- | |- | ||
! Class | ! Class | ||
Line 352: | Line 358: | ||
{| class="wikitable" | {| class="wikitable" | ||
− | !colspan="4" | | + | !colspan="4" | ICEClient |
|- | |- | ||
! Class | ! Class | ||
Line 364: | Line 370: | ||
| No | | No | ||
|- | |- | ||
− | | | + | | ICEDataComponentSectionPart |
− | | | + | | ICEDataComponentSectionPart() |
| RuntimeException | | RuntimeException | ||
| No | | No | ||
|- | |- | ||
− | | | + | | ICEFormEditor |
| Init() | | Init() | ||
| RuntimeException | | RuntimeException | ||
| No | | No | ||
|- | |- | ||
− | | | + | | ICEMatrixComponentSectionPart |
− | | | + | | ICEMatrixComponentSectionPart() |
| RuntimeException | | RuntimeException | ||
| No | | No | ||
|- | |- | ||
− | | | + | | ICESectionPage |
− | | | + | | ICESectionPage() |
| RuntimeException | | RuntimeException | ||
| No | | No | ||
|- | |- | ||
− | | | + | | ICETableComponentSectionPart |
− | | | + | | ICETableComponentSectionPart() |
| RuntimeException | | RuntimeException | ||
| No | | No | ||
Line 412: | Line 418: | ||
{| class="wikitable" | {| class="wikitable" | ||
− | !colspan="4" | | + | !colspan="4" | ICECore |
|- | |- | ||
! Class | ! Class | ||
Line 444: | Line 450: | ||
| No | | No | ||
|- | |- | ||
− | | | + | | ICECoreIApplication |
| start() | | start() | ||
| Exception | | Exception | ||
Line 452: | Line 458: | ||
{| class="wikitable" | {| class="wikitable" | ||
− | !colspan="4" | | + | !colspan="4" | ICEDataStructures |
|- | |- | ||
! Class | ! Class | ||
Line 479: | Line 485: | ||
| No | | No | ||
|- | |- | ||
− | | | + | | ICEJAXBManipulator |
| read() | | read() | ||
| JAXBException, IOException | | JAXBException, IOException | ||
| No | | No | ||
|- | |- | ||
− | | | + | | ICEJAXBManipulator |
| write() | | write() | ||
| JAXBException, IOException | | JAXBException, IOException | ||
| No | | No | ||
|- | |- | ||
− | | | + | | ICEResource |
− | | | + | | ICEResource() |
| IOException | | IOException | ||
| No | | No | ||
|- | |- | ||
− | | | + | | ICEResource |
| setContents() | | setContents() | ||
| IOException, NullPointerException | | IOException, NullPointerException | ||
Line 502: | Line 508: | ||
{| class="wikitable" | {| class="wikitable" | ||
− | !colspan="4" | | + | !colspan="4" | ICEItem |
|- | |- | ||
! Class | ! Class | ||
Line 525: | Line 531: | ||
|} | |} | ||
− | = References = | + | == References == |
http://weblogs.java.net/blog/johnsmart/archive/2009/09/27/testing-exceptions-junit-47 | 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 | http://kentbeck.github.com/junit/javadoc/4.10/org/junit/rules/ExpectedException.html |
Latest revision as of 08:16, 9 July 2015
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 ICE 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 ICE. Below is a list of the operations that throw and/or catch exceptions within ICE'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 |
ICEFormEditor | addPages() | PartInitException | Yes | No |
ICEMatrixComponentSectionPart | modify() | NumberFormatException | No | No |
ICEGeometryPage | 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? |
BasicAuthSecuredContext | failedAuthorization() | IOException | Yes | No |
BasicAuthSecuredContext | getResource() | MalformedURLException | No | Yes |
BasicAuthSecuredContext | handleSecurity() | LoginException | Yes | Yes |
ICECore | start() | ServletException, NamespaceException, IOException | All yes | All no |
ICECore | setLocation() | CoreException | Yes | Yes |
ICECore | loadDefaultAreaItems() | IOException, CoreException | All yes | Yes, No |
SimpleLogin | login() | IOException, UnsupportedLoginException | All yes | All yes |
ICEDataStructures | ||||
---|---|---|---|---|
Class | Method | Exception | Prints a stack trace? | Handles error? |
DataComponent, Entry, Form, MasterDetailsComponent | loadFromXML() | NullPointerException, JAXBException, IOException | All yes | All yes |
MasterDetailsPair, MatrixComponent, TableComponent | loadFromXML() | NullPointerException, JAXBException, IOException | All yes | All yes |
ComplexShape, GeometryComponent, PrimitiveShape | loadFromXML() | NullPointerException, JAXBException, IOException | All yes | All yes |
Transformation, ICEObject, ICEResource | loadFromXML() | NullPointerException, JAXBException, IOException | All yes | All yes |
Entry | setValue() | NumberFormatException | No | Yes |
AbstractShape | getProperty() | IndexOutOfBoundsException | No | Yes |
ICEObject | persistToXML() | NullPointerException, JAXBException, IOException | Yes | No |
ICEResource | setContents() | NullPointerException | No | Yes |
ICEItem | ||||
---|---|---|---|---|
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.
ICEClient | |||
---|---|---|---|
Class | Method | Exception | Prints a stack trace? |
EntryComposite | EntryComposite() | RuntimeException | No |
ICEDataComponentSectionPart | ICEDataComponentSectionPart() | RuntimeException | No |
ICEFormEditor | Init() | RuntimeException | No |
ICEMatrixComponentSectionPart | ICEMatrixComponentSectionPart() | RuntimeException | No |
ICESectionPage | ICESectionPage() | RuntimeException | No |
ICETableComponentSectionPart | ICETableComponentSectionPart() | RuntimeException | No |
ShapeTransient | read() | IOException | No |
ShapeTransient | write() | IOException | No |
Tube | read() | IOException | No |
Tube | write() | IOException | No |
ICECore | |||
---|---|---|---|
Class | Method | Exception | 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 |
ICECoreIApplication | start() | Exception | No |
ICEDataStructures | |||
---|---|---|---|
Class | Method | Exception | Prints a stack trace? |
Form | addComponent() | RuntimeException | No |
PainfullySimpleEntry | loadFromPSFBlock() | IOException | No |
PainfullySimpleForm | loadComponents() | IOException | No |
PainfullySimpleForm | loadEntries() | IOException | No |
ICEJAXBManipulator | read() | JAXBException, IOException | No |
ICEJAXBManipulator | write() | JAXBException, IOException | No |
ICEResource | ICEResource() | IOException | No |
ICEResource | setContents() | IOException, NullPointerException | No |
ICEItem | |||
---|---|---|---|
Class | Method | Exception | 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