JUnit 4 Testing Framework - Peter's notes, slightly adapted In order to use JUnit 4 you have to visit the http://www.junit.org/ website and download the file junit-4.10.jar that contains the Java class files for the framework (the framework is itself written in Java of course). Put the junit-4.10.jar file into the same directory all your code is in (similar to what we did for checkstyle). A ".jar" file is really just a ".zip" archive with a specific structure that allows us to add more classes to the Java class library we already have. There are detailed, operating-system specific installation instructions on the http://www.junit.org/ website, but I wanted to show you a way of using the ".jar" that will work on all systems. To do this, copy the junit-4.10.jar file into whatever directory you develop your code in. Once you have test cases, you need to start the Java compiler and the Java Virtual Machine in a way that includes the new classes from the framework, we'll get to that below. So why use a testing framework like JUnit 4 instead of writing the a "main" method with the test code in it? For one thing, JUnit allows you to modularize your tests better. It's not uncommon for large software projects to have just as much testing code as actual program code, and so the principles you use to make regular code easier to read (splitting things into methods and classes, etc.) should also apply to test code. Also, JUnit allows you to run all your test cases every time, it doesn't stop at the first failing test case like "assert" does. This way you can get feedback about multiple failed tests all at once. Finally, lots of companies expect graduates to have some experience with testing frameworks, so why not pick it up now? Note that testing is not just for software developers anymore, increasingly people working with software developers but who are themselves not software developers will be asked to contribute to testing a certain application being developed by their company. So it's a really useful skill to have on your list. So how do we write a test case for JUnit 4? As opposed to earlier versions of JUnit, JUnit 4 uses Java's annotation mechanism which allows us to "mark" certain methods as test cases. See http://docs.oracle.com/javase/tutorial/java/javaOO/annotations.html for details on the general mechanism. For JUnit 4 we import the "Test" annotation from the framework by saying import org.junit.Test; and then write our test methods using that annotation: @Test public void testThisAndThat() { ... } Any method "tagged" with the "@Test" annotation will be run by JUnit 4 as a separate test case. You can have as many of these as you want, and you should write a separate method for each test case. (If you put multiple test cases in one method, JUnit cannot tell you exactly which one failed!) There are many more annotations you can use. For example, the "@Before" and "@After" annotations mark methods that should run before and after each individual test case. Similarly, the "@BeforeClass" and "@AfterClass" annotations mark methods that should run once before or once after all test cases. Finally, you can use the "@Test" annotation to check for a particular exception that you expect. Recall that you not only want to test the "good" uses of your data structures, but you also want to make sure that the "bad" uses trigger the correct exception. Here is an example of several of these annotations to write a few test cases for the Array abstraction: import org.junit.Test; import org.junit.BeforeClass; import static org.junit.Assert.assertEquals; public class TestSimpleArray { static Array shortArray; @BeforeClass public static void setupArray() throws InvalidLengthException { shortArray = new SimpleArray(10, "Bla"); } @Test public void newArrayLengthGood() throws InvalidLengthException { assertEquals("Length inconsistent", 10, shortArray.length()); } @Test public void newArrayInitialized() throws InvalidLengthException, InvalidIndexException { for (int i = 0; i < shortArray.length(); i++) { assertEquals("Bla", shortArray.get(i)); } } @Test(expected=InvalidIndexException.class) public void invalidIndexDetected() throws InvalidIndexException { shortArray.set(shortArray.length(), "Paul"); } } As you can see we also imported one of the many "assertion methods" from the JUnit framework. You can find all of those in the JUnit documentation on the http://www.junit.org/ website, but assertEquals is the most commonly used one. Note that this set of test cases is far from complete, but it shows most of the features you'll need to write your test code from here on out. Compiling and running the JUnit test cases is a bit of a hassle. Let me first say that for most IDEs there is a way to integrate JUnit with the development environment so that the following command line stunts are not necessary. In particular, Eclipse has a mechanism for working with JUnit testing that you should explore. If you prefer the command line, here's how we compile the test cases: javac -cp junit-4.10.jar:. -Xlint:all TestArray.java The "-cp" option sets the "class path" for the Java compiler, meaning where it looks to find classes that you import in your code. By default the Java compiler looks in the system class library (the stuff that came with Java when you installed it) and in the current directory. We want it to look into the ".jar" file as well, so we have to specify a new class path. However, we also want the compiler to look into the current directory where all our code lives, so we specify "." as a second class path after the ":" symbol. Now you know all the dirty secrets about how this works, so you can forget them again and just use the line as given. :-D To run the test cases, we need to use something called a "test runner" from the JUnit framework. Here's how we do it from the command line: java -cp junit-4.10.jar:. org.junit.runner.JUnitCore TestArray So what we're doing here is we run "org.junit.Runner.JUnitCore" as our main program, and we supply "TestArray" which is the class that our test cases are in as an argument to that main program. Voila, that runs our tests and tells us how many passed and how many failed. Note: if you are doing this via command-line on a windows machine, you must use a ';' instead of a ':' to separate the paths: javac -cp junit-4.10.jar;. -Xlint:all TestArray.java java -cp junit-4.10.jar;. org.junit.runner.JUnitCore TestArray If you're using Eclipse, doing JUnit testing is even easier. You can import a test file into your project, or create a test file. Then select that file, and choose Run As JUnit Test. This FAQ is a pretty good resource for understanding JUnit: http://junit.sourceforge.net/doc/faq/faq.htm And from here on out, when we say "write test cases" as part of an assignment, we mean "write JUnit 4 test cases" as described here.