This post is mainly aimed at students taking a course in (imperative and) object-oriented programming methodology at Uppsala University. But the content covered isn't specific to that course, just the examples. Please send any errata over to me and you'll get a gold star!
I see you want to start writing tests for your code, great choice! Hopefully you haven't been putting of this step for too long (if you did that's okay as well, just be extra attentive writing your tests).
There are multiple ways of getting Java to find the files necessary to write JUnit tests. To make this guide as general as possible we'll download JUnit to a folder close to your project repo.
Danger! Before you start running these commands, take a look through them and make sure they aren't spoopy. You generally shouldn't trust strangers on the internet!
Next step is to actually create a few tests. If you remember working with CUnit in phase 1 you'll be in for a pleasant surprise! JUnit handles a lot of the busywork managing testsuites by using Java annotations before the tests. An example of a Java annotation is
@Override that you've used before. Anyways, let's get back on track.
At this point you should have a few packages in your symbolic calculator, such as
parser. You can choose to add your tests to them, or you can create a new package. This affects what you can and cannot access in your classes. For example, if you haven't specified access level modifiers to your attributes you can still access them if you're in the same package. We're going with the second route, I'll leave it to you to think about the reason why.
So! Let's create a new class for a few AST tests. I'll leave it to you to populate them with actual test-code.
Okay, now over to the last step. Now we want to modify the
makefile that you should've created so that it finds JUnit. This step will depend a bit on how it looks right now, but most importantly you need to add the correct
-cp flag to
javac when you're compiling and running the tests. I've seen issues where it (semi-)silently fails if the wrong path is added, so really make sure it's correct!
# This is not a good makefile, it doesn't define # dependencies so it always recompiles. You can # probably sneak it by the TA's, but they'd be # impressed if you actually write a good # makefile during the Java phase! compile_tests: javac -cp .:lib/hamcrest-core.jar:lib/junit.jar *.java run_tests: compile_tests java -cp .:classes:lib/hamcrest-core.jar:lib/junit.jar org.junit.runner.JUnitCore org.ioopm.calculator.tests.ASTTests
-cp flag? It tells Java where to find all the necessary classes. When compiling and running, it needs to find JUnit and Hamcrest, when running them we also need to point it to the classes folder where all the .class files go.
That's it! Now you should have working tests! You can spice things up a bit by adding a method with the annotation
@Before that will run before each test. Super useful to instantiate objects you need in every test (such as
These are the most common issues I've seen people struggling with when setting up JUnit the last couple of years.
assertEquals(double, double) is deprecated
Remember Computer Architecture? Floating point precision is a common problem, and comparing to float values can be dangerous. There's a new method that takes a 3rd argument - delta. It specifies the maximum difference between the two floats. Use that, or use your
toString() method and compare the strings instead.
Test is not an annotation / it is a class/method
The assignment throws a small curveball! The file Test.java containing some system level tests has the same name as the annotation
@Test. Try renaming the file and the class to something more descriptive and it should fix the issue.
 BTW! This is a perfect time to look into the achievement about access modifiers. I'd recommend starting in the Java documentation.