Next revision | Previous revisionLast revisionBoth sides next revision |
student:junit:v4 [2018/08/10 14:20] – created bernstdh | student:junit:v4 [2018/08/14 10:57] – bernstdh |
---|
| |
| |
===== JUnit Basics ===== | ===== JUnit v4 Basics ===== |
| |
| |
| |
| |
JUnit is an open-source testing framework. It provides a way to write, organize, and run repeatable test. | JUnit is an open-source testing framework. It provides a way to write, organize, and run repeatable test. This page provides a brief introduction to v4. Information is also available about |
| [[student:junit:v5 | version 5 (Jupiter) ]]. |
| |
| |
| |
| |
For each class you want to test, you must create a file named //ClassName//Test.java where //ClassName// denotes the name of the class being tested. So, for example, if you want to test the class named ''%%Atom%%'' you must create a file named ''%%AtomTest.java%%''. | For each class you want to test, you must create a file. It is common to use naming system //ClassName//Test.java where //ClassName// denotes the name of the class being tested. So, for example, if you want to test the class named ''%%Atom%%'' you would create a file named ''%%AtomTest.java%%''. |
| |
| |
The //ClassName//Test.java file must begin with the following line: | The //ClassName//Test.java file must begin with the following line: |
| |
<code> | <code java> |
import static org.junit.Assert.*; | import static org.junit.Assert.*; |
| |
and must include a class declaration of the following form: | and must include a class declaration of the following form: |
| |
<code> | ''public class //ClassName//Test'' |
public class //ClassName//Test | |
</code> | |
| |
So, continuing with the example above, ''%%AtomTest.java%%'' would initially contain the following: | So, continuing with the example above, ''%%AtomTest.java%%'' would initially contain the following: |
| |
<code> | <code java> |
import static org.junit.Assert.*; | import static org.junit.Assert.*; |
| |
import org.junit.Before; | |
import org.junit.Test; | import org.junit.Test; |
| |
(Note: The ''%%import static%%'' allows you to refer to static members in the ''%%org.junit.Assert%%'' package without having to include the class name.) | (Note: The ''%%import static%%'' allows you to refer to static members in the ''%%org.junit.Assert%%'' package without having to include the class name.) |
| |
The file //ClassName//Test.java contains methods that can be used to test the class defined in //ClassName//.java. Each such method is preceeded by an ''%%@Test%%'' annotation. (Note: An annotation provides information about a program but is not part of the program. Annotations have no effect on the operation of the program. Instead, they are used to provide information to tools that might use the program as input.) | The file //ClassName//Test.java contains methods that can be used to test the class defined in //ClassName//.java. Each such method is preceded by an ''%%@Test%%'' annotation. (Note: An annotation provides information about a program but is not part of the program. Annotations have no effect on the operation of the program. Instead, they are used to provide information to tools that might use the program as input.) |
| |
So, still continuing with the example above, if the ''%%Atom%%'' class contains a ''%%public int getAtomicNumber()%%'' method, then ''%%AtomTest.java%%'' might include the following method: | So, still continuing with the example above, if the ''%%Atom%%'' class contains a ''%%public int getAtomicNumber()%%'' method, then ''%%AtomTest.java%%'' might include the following method: |
| |
<code> | <code java> |
/** | /** |
* Unit tests for the getAtomicNumber() method | * Unit tests for the getAtomicNumber() method |
The body of the methods in the //ClassName//Test.java must contain the test cases for the corresponding methods in the //ClassName// class. These test cases often involve some "setup" code and a call to the ''%%Assert.assertEquals()%%'' method. So, for example, the ''%%getAtomicNumber%%'' method in the ''%%Atom%%'' class is supposed to return the atomic number of the calling ''%%Atom%%'' object. To partially test this method one might implement the ''%%testGetAtomicNumber()%%'' method in the ''%%AtomTest%%'' class as follows: | The body of the methods in the //ClassName//Test.java must contain the test cases for the corresponding methods in the //ClassName// class. These test cases often involve some "setup" code and a call to the ''%%Assert.assertEquals()%%'' method. So, for example, the ''%%getAtomicNumber%%'' method in the ''%%Atom%%'' class is supposed to return the atomic number of the calling ''%%Atom%%'' object. To partially test this method one might implement the ''%%testGetAtomicNumber()%%'' method in the ''%%AtomTest%%'' class as follows: |
| |
<code> | <code java> |
/** | /** |
* Unit tests for the getAtomicNumber() method | * Unit tests for the getAtomicNumber() method |
In the "setup" portion, this method creates an ''%%Atom%%'' objects (for oxygen). It then calls the ''%%Assert.assertEquals()%%'' method to tell jUnit to do some testing. This particular version of the ''%%Assert.assertEquals()%%'' method is passed three parameters and has the following syntax: | In the "setup" portion, this method creates an ''%%Atom%%'' objects (for oxygen). It then calls the ''%%Assert.assertEquals()%%'' method to tell jUnit to do some testing. This particular version of the ''%%Assert.assertEquals()%%'' method is passed three parameters and has the following syntax: |
| |
Assert.assertEquals(//Description//, //ExpectedValue//, //ActualValue//); | ''Assert.assertEquals(//Description//, //ExpectedValue//, //ActualValue//);'' |
| |
The //Description// is a human-readable ''%%String%%'' that provides information that enables the tester to understand the test in the event that the code fails the test. (Note that the tester will also be provided with the name of the test method so it isn't necessary to include information about the method being tested in the description if the test method is named well.) The //ExpectedValue// contains the correct value (i.e., the value that the tester expects if the method named //MethodName// in //ClassName// is working correctly. The //ActualValue// contains the value that was actually generated by the method named //MethodName// in //ClassName//. | The //Description// is a human-readable ''%%String%%'' that provides information that enables the tester to understand the test in the event that the code fails the test. (Note that the tester will also be provided with the name of the test method so it isn't necessary to include information about the method being tested in the description if the test method is named well.) The //ExpectedValue// contains the correct value (i.e., the value that the tester expects if the method named //MethodName// in //ClassName// is working correctly. The //ActualValue// contains the value that was actually generated by the method named //MethodName// in //ClassName//. |
As another example, suppose the ''%%Atom%%'' class contains a ''%%public boolean equals(Atom other)%%'' method, then ''%%AtomTest.java%%'' might implement the following method: | As another example, suppose the ''%%Atom%%'' class contains a ''%%public boolean equals(Atom other)%%'' method, then ''%%AtomTest.java%%'' might implement the following method: |
| |
<code> | <code java> |
/** | /** |
* Unit tests for the equals(Atom) method | * Unit tests for the equals(Atom) method |
The ''%%equals()%%'' method in the ''%%Atom%%'' class is supposed to compare the calling ''%%Atom%%'' object with the given ''%%Atom%%'' object and return ''%%true%%'' if the two have the same attributes and ''%%false%%'' otherwise. To partially test the ''%%equals()%%'' method, one might implement the ''%%testEquals()%%'' method in the ''%%AtomTest%%'' class as follows: | The ''%%equals()%%'' method in the ''%%Atom%%'' class is supposed to compare the calling ''%%Atom%%'' object with the given ''%%Atom%%'' object and return ''%%true%%'' if the two have the same attributes and ''%%false%%'' otherwise. To partially test the ''%%equals()%%'' method, one might implement the ''%%testEquals()%%'' method in the ''%%AtomTest%%'' class as follows: |
| |
<code> | <code java> |
/** | /** |
* Unit tests for the equals(Atom) method | * Unit tests for the equals(Atom) method |
When using ''%%Assert.assertEquals()%%'' to compare floating point numbers (e.g., ''%%double%%'' values), one must remember that the ''%%==%%'' operator must be used with care because of the less-than-perfect precision of operations on ''%%double%%'' values. In JUnit, the implication of this is that one should check to see if ''%%double%%'' values are within a tolerance value of each other. Hence, when comparing ''%%double%%'' values one should use the following: | When using ''%%Assert.assertEquals()%%'' to compare floating point numbers (e.g., ''%%double%%'' values), one must remember that the ''%%==%%'' operator must be used with care because of the less-than-perfect precision of operations on ''%%double%%'' values. In JUnit, the implication of this is that one should check to see if ''%%double%%'' values are within a tolerance value of each other. Hence, when comparing ''%%double%%'' values one should use the following: |
| |
Assert.assertEquals(//Description//, //ExpectedValue//, //ActualValue//, //tolerance//); | ''Assert.assertEquals(//Description//, //ExpectedValue//, //ActualValue//, //tolerance//);'' |
| |
| |
| |
| |
<code> | <code java> |
@Test(expected = IllegalArgumentException.class) | @Test(expected = IllegalArgumentException.class) |
public void testConstructor_IllegalArguments() | public void testConstructor_IllegalArguments() |
Using these methods, it would be better to write the test of the ''%%equals()%%'' method above as follows. | Using these methods, it would be better to write the test of the ''%%equals()%%'' method above as follows. |
| |
<code> | <code java> |
/** | /** |
* Unit tests for the equals(Atom) method | * Unit tests for the equals(Atom) method |
You can set the ''%%CLASSPATH%%'' as follows: | You can set the ''%%CLASSPATH%%'' as follows: |
| |
| <code bash> |
export CLASSPATH=.://directory//junit.jar://directory//hamcrest-core.jar:$CLASSPATH | export CLASSPATH=.://directory//junit.jar://directory//hamcrest-core.jar:$CLASSPATH |
| </code> |
| |
where //directory// denotes the name of the directory/folder that contains the files ''%%junit.jar%%'' and ''%%hamcrest-core.jar%%''. | where //directory// denotes the name of the directory/folder that contains the files ''%%junit.jar%%'' and ''%%hamcrest-core.jar%%''. |
For example, assuming that the two ''%%.jar%%'' fiels are in the current working directory, you can set the ''%%CLASSPATH%%'' as follows: | For example, assuming that the two ''%%.jar%%'' fiels are in the current working directory, you can set the ''%%CLASSPATH%%'' as follows: |
| |
| <code bash> |
export CLASSPATH=.:junit.jar:hamcrest-core.jar:$CLASSPATH | export CLASSPATH=.:junit.jar:hamcrest-core.jar:$CLASSPATH |
| </code> |
| |
After you have set the ''%%CLASSPATH%%'' you can compile your classes (including the test classes) and the usual way, and run a JUnit test as follows: | After you have set the ''%%CLASSPATH%%'' you can compile your classes (including the test classes) and the usual way, and run a JUnit test as follows: |
| |
| <code bash> |
java org.junit.runner.JUnitCore //ClassName//Test | java org.junit.runner.JUnitCore //ClassName//Test |
| </code> |
where //ClassName// is the name of the class being tested. For example, to run ''%%AtomTest%%'': | where //ClassName// is the name of the class being tested. For example, to run ''%%AtomTest%%'': |
| |
To compile: | To compile: |
| |
javac -cp .:junit.jar //ClassName//Test.java | ''javac -cp .:junit.jar //ClassName//Test.java'' |
| |
where //Name// represents tha name of the class being tested (and can contain wildcards like *). | where //Name// represents tha name of the class being tested (and can contain wildcards like *). |
To run: | To run: |
| |
java -cp .:junit.jar:hamcrest-core.jarorg.junit.runner.JUnitCore //ClassName//Test | ''java -cp .:junit.jar:hamcrest-core.jarorg.junit.runner.JUnitCore //ClassName//Test'' |
| |
where //Name// represents the name of the class being tested. | where //Name// represents the name of the class being tested. |
For example, to compile and run ''%%AtomTest%%'': | For example, to compile and run ''%%AtomTest%%'': |
| |
<code> | <code bash> |
javac -cp .:junit.jar AtomTest.java | javac -cp .:junit.jar AtomTest.java |
java -cp .:junit.jar hamcrest-core.jarorg.junit.runner.JUnitCore AtomTest | java -cp .:junit.jar hamcrest-core.jarorg.junit.runner.JUnitCore AtomTest |
| |
| |
=== Using JUnit with the CMD Shell === | === Using JUnit with the MS-Windows CMD Shell === |
| |
| |
You can set the ''%%CLASSPATH%%'' as follows: | You can set the ''%%CLASSPATH%%'' as follows: |
| |
| ''set CLASSPATH=.;//directory//junit.jar;//directory//hamcrest.jar;%CLASSPATH%'' |
set CLASSPATH=.;//directory//junit.jar;//directory//hamcrest.jar;%CLASSPATH% | |
| |
where //directory// denotes the name of the directory/folder that contains the files ''%%junit.jar%%'' and ''%%hamcrest-core.jar%%''. | where //directory// denotes the name of the directory/folder that contains the files ''%%junit.jar%%'' and ''%%hamcrest-core.jar%%''. |
To compile: | To compile: |
| |
javac -cp .;junit.jar //ClassName//Test.java | ''javac -cp .;junit.jar //ClassName//Test.java'' |
| |
where //Name// represents tha name of the class being tested (and can contain wildcards like *). | where //Name// represents tha name of the class being tested (and can contain wildcards like *). |