Goals
The goals of this assignment are as follows:
- Develop a unit testing plan for testing Java classes that you will
implement. The specifications for the Java classes are given to you.
- Implement a test driver using the JUnit framework.
- Execute the tests using JUnit.
Getting started
Read the notes on Testing and JUnit;
Test
Infected; and the
JUnit
Cookbook.
These examples are mostly based on JUnit 3.8, which
may not work with JUnit 4.11 on our lab machines.
JUnit details can be obtained from
www.junit.org.
JUnit is already
integrated with Eclipse, thereby providing several advantages. Environment
variables are set up "automagically". Test execution is tied to the Eclipse
debugger, so you can view what went wrong. Test driver skeletons are
generated; you just need to fill in the test cases.
Tasks
Certain games use a rectangular grid for the world, and allow the world
to "wrap" from top to bottom and from left to right. Conceptually,
this makes a doughnut-shaped world: if you keep going "North" you eventually
wrap back around to where you were, and if you keep going "East" you similarly
wrap back around. Note that going North is the +y direction, and going
East is the +x direction.
We're going to implement a couple of classes to
hide the details of the representation from client code.
-
Implement class World, which represents an n*m grid of Objects, where the
coordinates wrap as described above. Note that these Objects refer to instances
of the class java.lang.Object.
-
give it a constructor that takes n and m, where n gives the number of locations
possible in the West-East direction, and m gives the number of locations
possible in the South-North direction.
-
give it a second constructor that takes just n, meaning an n*n grid.
Use the "this" form to implement it in terms of the first constructor
-
give it a method get(int x, int y) which returns the object at x, y in
the grid, without wrapping. Declare this method protected rather
than public. Don't check x and y for being within range, just index
the underlying array
-
this use of protected allows other classes in the same package (like Coordinate)
to call the entry point, but not classes outside of the package
-
similarly, give it a protected method put(int x, int y, Object o) to place
the Object o in the grid. Declare this method protected rather
than public. Don't check x and y for being within range, just index
the underlying array. Do not wrap.
-
give it a method get(Coordinate c) which returns the object at c, implemented
in terms of the get() method in the Coordinate class.
-
give it a method put(Coordinate c, Object o) which puts the object o at the
x,y position indicated by Coordinate c.
-
give it a simple toString method that returns something like "World(n,
m)".
For example: "World(5, 6)" when the dimensions are given as 5, 6.
-
do not implement equals or hashCode
-
Implement class Coordinate, which represents an x,y position in a particular
2D world (where x and y are ints). The x,y in a Coordinate must always
be valid, i.e. in the 0..n-1, 0..m-1 space
-
give it a constructor that takes a World, x, and y. This constructor
must handle wrapping
-
give it a method get() which returns the object at the specified Coordinate
in the World this Coordinate is using
-
give it a method put(Object o), which replaces the Object in the grid with
the Object o provided as the argument.
-
give it a method equals(). Two Coordinates are equal
if they represent the same location in exactly the same World object.
You must compare the Worlds for identity using ==
-
give it a method hashCode(), which returns the sum of values of x and y and the
hashcode of its
World object.
-
give it methods north(), south(), east(), and west() that return the adjacent Co
ordinate
in those particular directions. North is the +y direction, East is
the +x direction, etc. These methods must handle wrapping
-
give it a method toString() that returns something like
"Coordinate(x, y) in World(n, m)" For example, "Coordinate(2, 3) in World(5, 6)"
Any object can be stored in the grid. For testing purposes, feel free
to choose something that is simple to compare with the expected object
returned by a get method. You can use instances of Integer or String,
for example.
Here is an example test case. We will use test cases like this to test your code.
public void testStoreWorld() {
World world = new World(10, 15);
Coordinate coordinate = new Coordinate(world, -25, -40);
Object object = new Object();
coordinate.put(object);
assertEquals("Not getting same object of World(10, 15) put using Coordinate(world, -25, -40) and get using world.get(5, 5) ", object, world.get(5, 5));
}
Note that any integer value is possible, including negative values. If there
is no object put into a location, you should return null. Make sure you
implement the equals method properly since otherwise you may lose a lot of
points.
Deliverables and submission
All the classes that you write must be in a package called cs314.a2. The classes are as follows:
- WorldTest.java: Contains tests for the class, World
- World.java: Contains the implementation of World
- CoordinateTest.java: Contains tests for the class, Coordinate
- Coordinate.java: Contains the implementation of Coordinate
- TestAll.java: Defines the test suite for all the unit tests of this
homework.
- overview.txt: a very short overview paper, providing
information that is not readily available from reading
the code, things that gave you trouble, assumptions made, etc. This paper
should be plain ASCII text.
Submit a single jar file, called a2.jar, using Assignment Submission
in RamCT that contains the above files in the correct directory structure
as described in the next paragraph. Click here for a
sample jar file that contains the correct structure. Here are some instructions
on how to create jar files.
The folder (or directory) hierarchy must be cs314/a2. The Java source files must be present in the cs314/a2 folder of the hierarchy. When you create the jar file, build it from the top of the directory hierarchy. The submitted file must correctly unpack the .java files into a subdirectory cs314/a2. Since the grader will use a script to run your tests it is required you to strickly follow the given file format. The grader will first run your classes with our test cases and then run your testcases with our faulty code. Points will be awarded for test cases that fail due to our faults.
Note:
- It's extremely important to submit your work using the specified form.
If your work does not meet that form, you will receive no credit for the
assignment. This may seem harsh. However, the grader will have a relatively
large number of assignments to grade. Guessing how to unpack and compile
individual assignments can take a lot of time, and is an unfair burden on
the GTA.
- Make sure that you submit .java files, not .class files.
- Make sure that you submit all of your test code in addition to the implementation of World and Coordinate.
- Be certain that all of your code is within a package, as described in the
instructions.
- Confirm that you have indeed clicked Submit, not just uploaded
the assignment to RamCT.
Grading criteria
- Functionality of World and Coordinate (implement methods correctly): 24 points
- Functionality of WorldTest and CoordinateTest class: 24 points
- Functionality of TestAll class: 2 points
Up to 5 points may be deducted for not following the packaging structure or
names used for the classes and the methods of each class.