Please try to attend the tutorials once they start. Attending tutorials is certainly a higher priority than attending lectures.
The purpose of this tutorial is to ensure that you are comfortable with the Eclipse/Java/JUnit tools on DICE (or whichever alternative tools that you choose to work with).
If you're not already familiar with the Eclipse development environment, you might like to work through this video tutorial showing how to create a new Eclipse project and start writing JUnit tests first.
There are two versions of JUnit around, 3 and 4. JUnit 4 is more modern, and so generally to be preferred. However, JUnit 4 requires language features introduced in Java 1.5, so the more backward-compatible JUnit 3 is still in widespread use, and it may be interesting for you to know the basics of its operation. Also, of particular note to those of you who prefer not to use the Eclipse environment, the version of Ant installed on DICE, 1.6.5, is incompatible with JUnit 4. Consequently if you want to use Ant to run your builds from the command line you'll need to write any tests you create for this course using JUnit 3 or come up with some other kind of personal workaround.
So unless you have strong personal reasons for doing otherwise, I'd recommend that you do any Java work you need to do for the course in Eclipse, and write your tests in JUnit 4: it's slightly easier, and requires less typing.
Note that this is the JUnit 3 version of this tutorial — the JUnit 4 version is here!
Recall the Triangle source code we looked at in class — first the badly-implemented Triangle class itself:
Source for st.Triangle : |
---|
package st; public class Triangle { private int p; // Longest edge private int q; private int r; public Triangle(int s1, int s2, int s3) { // Ensure that p is the largest of the three. if(s1 > s2) { q = s2; if(s1 > s3) { p = s1; r = s3; } else { p = s3; r = s1; } } else { q = s1; if(s2 > s3) { p = s2; r = s3; } else { p = s3; r = s2; } } } public boolean isScalene() { return p > 0 && q > 0 && r > 0 && p < q + r && (q < r || q > r); } public boolean isEquilateral() { return p == q && q == r; } } |
Then the TriangleTestJ3 unit test:
JUnit 3 source for st.TriangleTestJ3 : |
---|
package st; import junit.framework.TestCase; public class TriangleTestJ3 extends TestCase { private Triangle t; public void setUp() { t = new Triangle(3, 4, 5); } public void testTriangle() { fail("Not yet implemented"); } public void testIsScalene() { assertTrue("t not scalene!?!", t.isScalene()); } public void testIsEquilateral() { assertFalse("t unexpectedly equilateral!", t.isEquilateral()); } } |
And finally the AllTestsJ3 test suite:
Source for st.AllTestsJ3 : |
---|
package st; import junit.framework.Test; import junit.framework.TestSuite; public class AllTestsJ3 { public static Test suite() { TestSuite suite = new TestSuite("Test for st"); //$JUnit-BEGIN$ suite.addTestSuite(TriangleTestJ3.class); //$JUnit-END$ return suite; } } |
Think of a series of test inputs and the results that you'd expect
for them, then create the appropriate tests. As I explained in class,
the test fixture mechanism is clumsy for instantiating and testing a lot
of objects, so you might prefer to get rid of the private Triangle
t;
and setUp()
, and do something like this:
Testing lots of Triangles: |
---|
public void testIsEquilateral() { Triangle t = new Triangle(4, 5, 6); assertFalse("(4, 5, 6) unexpectedly equilateral!", t.isEquilateral()); t = new Triangle(1, 1, 1); assertTrue("(1, 1, 1) unexpectedly not equilateral!", t.isEquilateral()); … } |
You could also add a toString()
method to
Triangle
in order to help with debug messages (this
tutorial on Java's toString()
method might be of use).
These tests will quickly show that isScalene()
is
incorrect. Fix it.
It's really an error to allow construction of bad triangles, so it
makes sense to test these bad inputs in the constructor and throw an
exception of some kind for non-triangle parameters. Do this, including
adding a BadTriangleException
to your implementation. You
may need to add some throws
clauses to your code. You may
also find that after making these enhancements, you can simplify the
isScalene()
test.
As demonstrated in class, you can test that error conditions are detected and exceptions get thrown correctly too:
Testing to see that exceptions are thrown: |
---|
public void testTriangle() { try { // Some code which should cause an exception: Triangle q = new Triangle(0, 0, 0); // If we get here then the code didn't cause an exception, // and so the test has failed. fail("Exception not thrown: bad triangle accepted!!!"); } catch(ParticularExceptionWeAreTestingFor e) { // If we get here then the exception was thrown correctly. // We do nothing, and let successful execution continue. } … } |
Implement a set of tests for the Triangle
constructor.
Version 1.2, 2010/01/21 19:01:21
Informatics Forum, 10 Crichton Street, Edinburgh, EH8 9AB, Scotland, UK
Tel: +44 131 651 5661, Fax: +44 131 651 1426, E-mail: school-office@inf.ed.ac.uk Please contact our webadmin with any comments or corrections. Logging and Cookies Unless explicitly stated otherwise, all material is copyright © The University of Edinburgh |