01: HamSpam

Estimated reading time: 15 minutes
Estimated time to complete: 60 minutes (plus debugging time, if needed)
Prerequisites: Lab 02
Starter code: hamspam-student.zip
Collaboration: not permitted

Computer science is the study of the theory computation and its applications. In this course, we will weight the scales toward application. Two important parts of applying the theory of computation are knowing how to make a computer do what you want (programming) and checking that it’s doing what you want (testing). This assignment consists of a textual description of a “toy problem”, provides starter code to solve that problem, and asks you to solve the problem (and test that your solution is correct).

Overview

In this assignment, you’ll learn to download and set up starter code that we provide, a skill which you’ll need for almost every future programming assignment in this course. You’ll use that code to complete an implementation of the Ham and Spam counting game. Along the way, you’ll start to learn about unit testing, a repeatable, automatable way to detect bugs (and not incidentally, a way for us to test your submissions). Finally, you’ll learn to export and submit an entire Eclipse project to the autograder.

Goals

  • Import an Eclipse project into the Eclipse IDE.
  • Execute code within Eclipse.
  • Run tests within Eclipse.
  • Write code within Eclipse.
  • Export a project from Eclipse and submit it to the autograder.

Some reminders

  1. Start this (and future) assignment(s) early.

  2. This is the first programming assignment. Unlike the labs, where collaboration may be permitted, programming assignments generally do not permit collaboration. At the top of each assignment or lab, the collaboration policy is clearly stated.

    When collaboration is not permitted, copying partial or whole solutions, obtained from other students or elsewhere, is academic dishonesty, as is showing your code to other students or looking at other students’ code.

    Remember, you can use the course Piazza site to quickly (and anonymously, if you like) get help from both the course staff and your classmates. When using Piazza, don’t copy/paste large chunks of code into your question. Instead, do the same thing you should do if asking a classmate for help: ask your question by describing the problem you’re having, or use a small synthetic example that illustrates your difficulty. If you must include a large chunk of your code to ask your question on Piazza, mark it as a “private” question, and only the course staff will be able to see it.

  3. Do not expect partial credit if you submit a program that does not compile. Any compilation errors in your project will cause the autograder to fail, and you will receive a zero for your submission.

  4. This is a new, experimental course. We do our best to exhaustively check the assignments and autograder. But, if you think something is wrong with the autograder or assignment (as opposed to your submission), contact the course staff immediately. Capture a screenshot of the error, and export a copy of your assignment in the state that triggers the error. Providing these to us will help us immensely in narrowing down the problem.

  5. Late submissions will not be accepted. Excuses with documentation may permit you to submit an assignment late on a case-by-case basis, consistent with the University’s Academic Regulations and otherwise at my discretion.

Downloading and importing the starter code

Download and save (but do not decompress) the provided archive file containing the starter code. Note that in this and future labs, the starter code is linked to at the top of the assignment.

Open Eclipse. Depending upon how you left things after the previous labs, you might see either the welcome screen, or the standard eclipse workspace. Close the welcome screen if it’s open, and you should see something like the following:

Hello World redux

You can close the “Cheat Sheet” on the right by clicking the “X” next to the words “Cheat Sheet”. Then choose “Import…” from the “File” menu. A window will come up so you can choose how to import. Select “General” and within that, “Existing Projects into Workspace” (It may seem strange, but do not choose “Projects from Folder or Archive”) Then click “Next”.

import

Choose the button for “Select archive file:” and locate the file you downloaded above. Then click “Finish”.

select file

You should see a hamspam-student Java project in the Package Explorer window on the left. Click on the triangles to reveal the content of this directory and the src, support, and test directories within it.

expanded

Finally, we’re going to make the support directory read-only. The folder contains support code that we encourage you to use (and which must be used to pass certain tests), but you must not change or add anything in this folder. (In this and future assignments, if you change or add files in this directory, you might find that your program runs fine on your machine but that the autograder will not compile it successfully.)

To help ensure that you do not change anything in support, we suggest that you set the folder to be read-only. You can do this by right-clicking on it in the Package Explorer, choosing “Properties” from the menu, choosing “Resource” from the list on the left of the pop-up “Properties” window, unchecking the “Permissions” checkbox for “Owner-Write”, and clicking the “OK” button. A dialog box will show with the title “Confirm recursive changes”, and you should click on the “Yes” button.

permissions

You should see three Java source files among the directories: HamSpam.java, HamCommander.java, and HamSpamTest.java. You can open them by double-clicking on them. Do so, and take a look through each of them. You’ll quickly note they involve a game about “Ham”, “Spam”, and numbers, and that Eclipse has detected two errors.

On Ham and Spam

“Ham and Spam” is a children’s counting game. Before it is played, the players agree on a ham number and a spam number. Both are integers greater than one, and they cannot be the same number. The players then take turns saying the hamspam value for each successive integer, starting at one. Usually, the hamspam value is just the number. But:

  • If the number they are supposed to say is divisible by the ham number and not the spam number they say “ham” instead of the number.
  • If the number they are supposed to say is divisible by the spam number and not the ham number they say “spam” instead of the number.
  • If the number they are supposed to say is divisible by both the spam number and the ham number they say “hamspam” instead of the number.

For example, if the ham number is three, and the spam number is four, then the first twelve hamspam values are:
1, 2, ham, spam, 5, ham, 7, spam, ham, 10, 11, hamspam

For this assignment, you are going to modify the HamSpam class provided to produce the correct value or values for a game of “Ham and Spam”.

Using Eclipse

Let’s walk through using Eclipse to identify and fix errors, run code, and run unit tests.

Finding and fixing compilation errors. You can see that Eclipse has noted that “The blank final field hamNumber may not have been initialized,” as displayed in the Errors list at the bottom and as shown by the red underlines in the source for HamSpam.java.

In other words, the instance variable hamNumber is declared (private final int hamNumber) but never set to a value if the class is instantiated. Your lazy instructor didn’t even provide you with code that compiles!

Fix the error by modifying the constructor of HamSpam to set the instance variable hamNumber to the appropriate argument of the constructor. (A reminder: when a local variable, such as the argument to the constructor, has the same name as an instance variable, you can disambiguate the instance variable by including the this. qualifier. In other words, you can write this.hamNumber = hamNumber; to set the instance variable to the argument passed to the constructor.)

Running programs. Once you’ve eliminated errors, you can run the program. But you’ll note there’s no main method in HamSpam.java. Instead, open HamCommander.java (which does have a main method), then click the green play button in the top row of the Eclipse window (it looks like a white triangle inside of a green circle), or choose “Run” from the Run menu. A console will appear in the bottom of the Eclipse window. Follow along, pressing Enter after each number you enter, to see the (sometimes incorrect) results of the current implementation of Ham and Spam.

Running tests. Next, choose HamSpamTest.java in the Package Explorer and run it using the play button or the menu, as above. When you do, the package explorer on the left will switch to a JUnit pane, which will show the testing output. JUnit is a standard unit-testing library for Java that we’ll be using extensively in this course.

You should see a total of fourteen tests: four tests that pass (with small green checkmarks), and ten tests that fail (with small blue Xs). Familiarize yourself with the testing interface: hover over the buttons to see what they do (notably, one toggles showing only failed tests), and double-click on a test to jump to it. For example, if you select testHamOrSpamGetValue, you should see the following under Failure Trace:

org.junit.ComparisonFailure: getValue returns incorrect value
expected:<[hamspam]> but was:<[12]>
at hamspam.HamSpamTest.testHamAndSpamGetValue(HamSpamTest.java:41)

You may have to resize the JUnit pane to see the full message.

JUnit tests work by checking that the expected result of a method call equals the actual result. The failed test indicates that one (or more) methods in the starter code aren’t returning correct values. Examine the test; you can double-click on at hamspam.HamSpamTest.testHamAndSpamGetValue(HamSpamTest.java:41) (or just the test itself, as noted above) to jump to the test in the source pane. Here, you can see that the test case expects the result of hamspamThreeFour.getValue(12) to be the string "hamspam", but as the output in the Failure Trace indicates, it produced the string "12" instead.

Diagnosing and fixing problems. Go to the declaration of getValue(); you can do so by right-clicking on it and selecting “Open Declaration”, or by double-clicking on HamSpam.java in the Package Explorer and scrolling to it.

Your goal should be to correct the implementation of the getValue() method. The correct solution is not merely to make the function return “hamspam” when n == 12. Instead, you should revise the code so that the function will return the correct string for any n.

There is at least one thing to fix. The getValue() method currently checks for equality against numbers, not divisibility. You can use the modulus (remainder) operator (%) to check for divisibility. It divides one number by another and returns the remainder. For example, if you wanted to print out whether the value of a variable n was divisible by three, you could write:

1
2
3
4
5
if ((n % 3) == 0) {
  System.out.println(n + " is divisible by 3");
else {
  System.out.println(n + " is not divisible by 3");
}

When we autograde your program, we will test both getValue() and getValues() with other ham and spam numbers to make sure each works properly. Our test cases will obey the constraints described in this assignment (for example, the ham number and spam number will always be greater than one, and never be equal to one another), but are otherwise unconstrained.

In this assignment, we’ve given you all the test cases. But in future assignments, there are test cases we are going to use that you won’t be able to examine for yourself. You will have to think about the problem and make sure you’re not missing any details or corner cases if you want to pass them. (We’ll teach you to write tests soon, but there’s no magic: copy/paste and edit an existing test to get 90% of the way there.)

You can also use the HamCommander class for interactive testing. But as you’ll see, just being able to press the “Play” button and run a bunch of tests quickly and repeatedly is much more convenient, especially as programs grow more complex.

Submitting the assignment

When you have completed the changes to your code, you should export an archive file containing the entire Java project. To do this, click on the “hamspam-student” project in the package explorer. Then choose “Export…” from the “File” menu. In the window that appears, under “General” choose “Archive File”.

export archive

Then choose “Next” and enter a destination for the output file. Be sure that the “hamspam-student” project is selected, and that all Java source files in src files are included (the easiest way to do this is to click “Select All”).

save export

Save the exported file with a .zip extension (any name is fine). Then log into Gradescope, select the HamSpam assignment, and submit the file for grading, just as you did for Homework 01. You’ll see the contents of the .zip file in the upload window after you select it:

upload

If you uploaded a not-fully-correct submission, you might see something like the following:

autograded

Compilation errors will be provided by the autograder, but the exact details of the tests we run on your code are deliberately not provided. For this assignment, the tests you have locally and the tests run on Gradescope are the same, but this won’t always be the case. You must read assignments carefully – if your submission is not passing a test, it is almost certainly because your submission doesn’t match the requirements of the assignment.

Remember, you can resubmit the assignment as many times as you want, until the deadline. If it turns out you missed something and your code doesn’t pass 100% of the tests, you can keep working until it does.