Software Testing Preparatory Activity 1: Getting started with Eclipse and JUnit (JUnit 4)

The purpose of this activity is to start to get comfortable with the Eclipse/Java/JUnit tools on DICE (or whichever alternative tools that you choose to work with).

A brief note on JUnit 3 and JUnit 4

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 use, and it may be interesting for you to know the basics of its operation. The system used in the practical was developed in Java 1.4. However you can work around this.

If you want to know about JUnit3, this is the JUnit 3 version of this activity.

Source code

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 TriangleTestJ4 unit test:

JUnit 4 source for st.TrianglTestJ4:
package st;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

public class TrianglTestJ4 {

  private Triangle t;

  @Before
  public void setUp() throws Exception {
    t = new Triangle(3, 4, 5);
  }

  @Test public void scaleneOk() {
    assertTrue(t.isScalene());
  }

}

And finally the AllTestsJ4 test suite:

Source for st.AllTestsJ4:
package st;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@Suite.SuiteClasses({
  st.TriangleTestJ4.class,
})
public class AllTestsJ4 {
  // Everything's done by the annotations above.
}

Activities

The activities here are partly to remind you of some relevant bits of Java and JUnit that should be useful later in the course, so please do read any online tutorials on Java/JUnit that you think will help.

  1. Add tests: Think of a series of test inputs for isScalene(), and the results that you'd expect for them, then create the appropriate tests (if you're at a loss, use the answer sheet from Lecture 1's quiz). As 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:
    @Test public void testIsEquilateral() {
      Triangle t = new Triangle(4, 5, 6);
      // (4, 5, 6) isn't equilateral, so expect a false return.
      assertFalse("(4, 5, 6) unexpectedly equilateral!", t.isEquilateral());
      t = new Triangle(1, 1, 1);
      // (1, 1, 1) is equilateral, so expect a true return.
      assertTrue("(1, 1, 1) unexpectedly not equilateral!", t.isEquilateral());
      …
    }
    

    Notice that the strings above (“(4, 5, 6) unexpectedly equilateral!” etc.) are messages that are printed if the test fails, so you put them in to help yourself understand what's happening if tests start to fail. The messages only need to say as much as you think would be useful.

  2. Add a Triangle.toString() method: If you add a toString method to Triangle, that'll help with debug messages (this tutorial on Java's toString() method might be of use).
  3. Fix the implementation: A thorough set of tests will quickly show that isScalene() is incorrect. Fix it.
  4. Enhance the implementation: 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() implementation and remove some of your test cases.
  5. Test the enhancements: 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:
    @Test(expected = st.BadTriangleException.class)
    public void noBadTriangles() throws BadTriangleException {
      // Should cause an exception:
      t = new Triangle(0, 0, 0);
    }
    

    … the expected = st.BadTriangleException.class above tells JUnit 4 to expect this method to throw an exception.

    Implement a set of tests for the Triangle constructor.

Solutions

Follow this link for some ideas for solutions to this activity.


Version 1.1, 2015/01/20 10:30:50


Home : Teaching : Courses : St : 2014-15 

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