For assignment A1, you wrote a Java class,
Organism
and a JUnit test class OrganismTester
. The purpose was to:
In this assignment, you will add fields and methods to your correct solution to A1, testing as you program. We expect you to continue to use what you learned in doing A1. We expect you to continue to include the class invariant and javadoc specifications of all methods. We expect you to program and test in an incremental fashion. In addition, this assignment has the following new learning objectives:
But there will be no iterative feedback on this assignment. You now know our guidelines and how we grade, so there should be no need for iterative feedback. We will deduct points where our guidelines are not followed and for errors in your program. Your test cases will also be graded.
You may do this assignment with one other person. If you do this, both of you must visit the CMS and do what has to be done in order to group yourselves. One person will invite the other using CMS, and the other will then respond using CMS. Do this well before you submit the assignment. You create a mess for yourselves and for us when you submit and then realize that you have not yet grouped.
If you need help, please SEE SOMEONE IMMEDIATELY —a course instructor, a TA, a consultant. Do not wait. A little in-person help can do wonders. See the Staff page on the course homepage, www.cs.cornell.edu/courses/cs1110, for contact information.
For the purpose of this assignment, you may not use if-statements or loops, and you can use conditional expressions only in function toString.
Read the whole assignment before starting. Start with your answer to assignment a1, which should be correct. Add more components to Organism
and test methods by adding more tests to OrganismTester
as indicated below. This incremental development/testing will
help you complete this programming task quickly and
efficiently. If we detect that you did not develop it
this way, we may ask you to start from scratch and do a different assignment.
Whenever you write a method (see below), look through the class invariant and convince yourself that class invariant still holds when the method terminates. This habit will help you catch or prevent bugs
Step 1: Add another constructor. Add a constructor with the specification given below. After adding it, start a new testing procedure in OrganismTester
and add tests to it that ensure that all fields are properly set by the new constructor. Add tests to ensure that parameter eater's number of victims and amount of mercury are properly maintained. Hint: Rely on previously written methods; don't reprogram something you already programmed.
Constructor | Description (and suggested javadoc specification) |
---|---|
Organism(int lev, int m, String nn, Organism eater) |
Constructor: a new Organism at food-chain level lev containing m units of methylmercury; its nickname is nn. This new Organism has not eaten any Organism and is immediately eaten by eater. Precondition: nn has at least 1 character, lev is non-negative, m is non-negative, and eater is not null. |
Step 2: Add a toString function. As you know, a parameterless toString function produces a String representation of the object in which it appears. Write function toString in class Organism. The String that it returns must obey the following requirements exactly, down to the number of spaces and punctuation.
The general format of the output is indicated by the following two examples, but read a-d below for exceptions:
Organism (nickname tasty), level 1, mercury content 4, 0 victims, eaten by jaws.
Organism level 2, mercury content 2, 1 victim.
where
In function toString, (but nowhere else), you may use conditional expressions; you may not use if-statements. The general form of a conditional expression is
(boolean-expression ? expression1 : expression2)(the parentheses are not needed but are generally included). It is evaluated as follows: if boolean-expression evaluates to true, the value of the conditional epression is the value of expression1; otherwise, it is the value of expression2. An example usage is this: (x > 0 ? x : -x), which evaluates to the absolute value of x.
Your test case(s) for toString must test every part of toString. Your function toString is probably more complex than the previous methods you have written, so your testing will probably need to be more elaborate. You need to test that everything is correct for important different combinations of inputs —think about what kinds of situations would call for significantly different outputs of toString, and test whether your toString indeed produces such outputs.
It is a good practice to write function toString before writing elaborate methods, because toString can be quite helpful for debugging.
Step 3: Add comparison functions. Start a procedure in OrganismTester that will test the three functions described in the table below. Then deal with the three functions one at a time: write test cases for it, write the function, and test it. The second and third functions must be static. In writing these, you may not use the if-statement or the conditional expression; you must rely on boolean expressions.
function | Description (and suggested javadoc specification) | return type |
---|---|---|
isHigherThan(Organism org) | = "org is not null and this organism is at a higher level than org." | boolean |
isHigherThan(Organism org1, Organism org2) |
= "org1 is not null and org2 is not null and org1 is at a higher level than org2." | boolean |
eatenBySame(Organism org1, Organism org2) |
= "org1 and org2 are not null and were eaten by the same Organism." | boolean |
Note that whether org is null or not makes a difference in the output; org == null is not a precondition. The specification of the first function is equivalent to: if org is not null and this organism is at a higher level than org, return true; otherwise, return false.
Here is a principle to keep in mind: If an argument of a call can be null, then one should have a test case for it. Keep this in mind when constructing your test cases.
The body of the second isHigherThan function is best written in terms of a call on the first one; write it that way.
Step 4. Add a static variable and test its use. We want your program to keep track of the number of organisms that are created. To do this, add a private static int variable that will contain the number of organisms created and add a static getter method getNumberOfOrganisms that will return the number of organisms created. Then, change your program so that whenever an Organism is created, the static variable is incremented by 1, thus helping to ensure that your program is maintaining the class invariant.
Finally, add test cases in OrganismTester to make sure that the static variable is properly maintained. You will encounter problems if you assume that the field has a particular value at any point during testing, because you don't know the order in which testing methods are called. Therefore, to test it, you should test the change in the static field, as follows: (1) save the value of the field in a local variable, (2) do something to create a new Organism, and (3) test whether the static field increased by 1 --the saved value will help.
Do the following: