Program 0

Learning to Use Eclipse, Course Libraries, JUnit, and Checkmate

Fundamental Data Structures
ICS-23
(NOT GRADED)


Introduction This "programming assignment" is designed to ensure that you know how to use -at least in a cookbook way- Eclipse (for editing, running, and debugging Java programs, after installing course libraries/Jar files), JUnit (and Driver programs, for testing and locating errors), and Checkmate for submitting programs for grading.

You will start this programming assignment similarly to others this quarter.

  • First you will download and unzip an Eclipse Start Project Folder.

  • Second, you will start Eclipse, create a Java project (using a downloaded project folder, as the existing source) and then install three Jar libraries/files for use in the programming assignment.

  • Third, you will use a Driver program and JUnit to test code that I have provided in the start project folder. For all later assignments, I will not be providing as much code as I do in this assignment, because the focus of this assignment is using tools, not writing code; the focus of the later assignments is writing code using the tools that you are learning in this assignment. There is actually just one error in this code, and this write-up will detail where it is and how to fix it.

  • Fourth, when you have fixed the program, you will submit its .java file using the Checkmate submission system.
I encourage you to work on this assignment in pairs, with someone in your lab section. This quarter you can work in pairs on all the programming assignments. Normally, when you work in a pair, only one student should submit the assignment, which should contain both students' names appearing in the comments at the top of each submitted .java file. But for this assignment, I want each student to submit the program using the Checkmate submission system, so I'll know that every student knows how to use it.

You may want to print this document and carefully read it, marking any parts that contain important information (for review before you turn in the file); you might want to save the copy you marked-up. This is the first quarter that I am using this document, so please report any problems (even just typos) to me. I expect you to read this entire document and perform the operations it describes.


Download and Unzip Download (onto your desktop) and unzip the following Eclipse Start Project Folder. If you have any problems ask one of the staff for help. Information about unzipping on labs machines is available via the Handouts (General) link on the webpage; there, click the Windows/ Operating System and Eclipse IDE link. Or, see the Unzipping Files link in the Tutorial on the Windows Operating System and Eclipse IDE. This document includes lots of useful information about using Windows, Eclipse, and Checkmate.

The resulting unzipped folder has a deeply nested folder (via the folders edu, uci, ics, pattis, ics23, and finally collections) that contains just the two files LinearArrayQueue.java and TestQueue.java. These files will both be discussed in detail later in this assignment.


Start Eclipse,
Create a Project, and
Install the Libraries
Next you need to start Eclipse and create a Java project using the project folder you just downloaded as the existing source. See the Start/Stop and Existing Sources links in the Tutorial on the Windows Operating System and Eclipse IDE. For uniformity, use the name Program0 for your project's name. The project file that you create will show syntax/compilation errors, until you correctly install the Jar libraries/files, discussed below.

For this programming assignment (and most of the others this quarter), you need to install the libraries contained in the introlib.jar, junit4-7.jar, and collections.jar files. Information about installing Jar libraries is available via the Online Resources link in the left-hand index of the course webpage; there, click the View: Using Jar Libraries in Eclipse link. Or, read this entire document by clicking Using Jar Libraries in Eclipse.

Read the document just mentioned. It shows you how to install these three libraries correctly. Two (introlib.jar and junit-4.7.jar) must be installed using one method; the other (collections.jar) must be installed using another method. In the material below, I will assume that you have successfully installed all three of these libraries correctly, so do it now.

The LinearArrayQueue.java filein this project contains almost correct code that implements the behavior of a queue. You will be implementing lots of (abstract) data types, like this one, during the quarter. A queue is a simple FIFO data type, adhering to the First-in First-out order property. Queues add values to their rear and remove values from their front, so these are the two "hot spots" that must be efficiently accessed in any data structures that implements a queue.

We can implement queues efficiently by using either an array or linked list data structure. The queue implementation in this programming assignment, LinearArrayQueue, declares the required instance variables and needed methods using an array data structure. Using a linear array is conceptually simple to understand and program, but it has a slower-than-necessary remove operation (when compared with using a circular array data structure, which we will discuss later in lecture). When all the necessary libraries are installed, this class compiles and runs, but results in a few execution/run-time errors, which we will see via the Driver and the JUnit tests discussed below.


Run the Driver Each data type that we will discuss this quarter has a "driver" program that allows us to "drive it": to call (test) each of its methods and observe the results. The Driver for queues is in the class named DriverForOrderedCollection, which is the collections library. To run this Driver program, we must first find it:
  • Click the + in front of project's name, the icon named Program0; the + should change to a - with two icons indented underneath it.

  • Click the + in front of icon named ReferencedLibraries; the + should change to a - with one icon indented underneath it.

  • Click the + in front of the icon named collecitons.jar; the + should change to a - with two icons indented underneath it.

  • Click the + in front of the icon named edu.uci.ics.pattis.ics23.collections; the + should change to a - with many icons indented underneath it.

  • Right-click the icon and/or name DriverForOrderCollection.class; hover over Run As and click Java Application
The result of these commands is illustrated below.

  The program should now start running in the Console tab at the bottom of Eclipse. Answer the first prompt by just pressing the Enter/Return key (it has the same effect as if you typed the default value that appears in the parentheses); then answer the second prompt by typing the number in brackets that precede LinearArrayQueue (which should be option 4). The console window will display the following menu of options that you can use to call/test each queue method.

  Note that this Driver tests a queue that stores String values. You must enter a single letter to test any Mutator (Command) or Accessor (Query) method. Of special note is the t command, which test the toString method by printing the value it returns.

It prints a String that starts with the name of the class (here LinearArrayQueue) and its interesting state in brackets. First, it always shows two numbers separated by a slash: the first is the number of values in (the size of) the queue; the second is the length of the array storing the queue (which should always be at least as big as the size). If the size of the queue isn't zero, the toString method shows that many indexes in the array, illustrating the index and value of each. Then testing this queue implementation, the user can call toString to observe the effect of calling a mutator.

Issue the t command and the Driver should print the following

  which describes a queue implemented by this class. It currently stores 0 values in an array whose length is 1 (the array currently has the capacity to store just one value).

Then issue the s, e, and p commands to query the state of the object. The Driver should print the following

  The peek command, which returns the first value (the Driver prints this value) in a queue cannot work correctly on an empty queue. Notice what is printed instead: the thrown exception (NoSuchElementException) and the sequence of calls that led to it being thrown; if you click on the link to LinearArrayQueue.java:106 Eclipse will load the file containing this class and highlight the line that threw the exception. Thus, the Driver just ignores this command and we can continue driving the LinearArrayQueue class.

Next issue the a command and add/enqueue test1 when prompted. This method returns whether or not the entered value was added to the queue (for queues, which can contain duplicate values, it always returns true; for sets, which cannot contain duplicate values, this method returns false if the added value is already in the set). Then issue the t command and note the result: toString = LinearArrayQueue[1/1:[0]=test1] which describes a queue implemented by this class, currently storing 1 values in an array whose length is 1; the index 0 stores that value: test1.

Next issue the a command again and add/enqueue test2 when prompted. Then issue the t command and note the result: toString = LinearArrayQueue[2/2:[0]=test1,[1]=test2] which describes a queue implemented by this class, currently storing 2 values in an array whose length is 2 (the length of the array storing the queue was automatically doubled in size to accommodate another value); the index 0 stores that value test1 and the index 1 stores that value test2. Order is important in queues: the earlier a value is added/enqueued, the earlier it appears in the array.

  Next issue the r command which should remove/dequeue the value at the front of the queue. It correctly prints remove = test1. But then issue the t command and note the result is still toString = LinearArrayQueue[2/2:[0]=test2,[1]=test2].

  This result is incorrect because test2 now appears in BOTH array locations (it was shifted one to the left, but still appears at the end of the array). In fact, if you issue the r command again, it prints remove = test2 and likewise the t command will still print both test2 values in the queue. If you issue the x command (which is void and returns -and the Driver prints- no result), the queue will be emptied; notice that the t command will print toString = LinearArrayQueue[0/2:] which now describes a queue implemented by this class, currently storing 0 values in an array whose length is 2 (the length of the array is not reduced).

  So, using this Driver, we can call/test all the methods in the LinearArrayQueue class, looking for incorrect behavior. Often we call the toString method to determine the effect of a mutator operation, so it is critical to implement the toString method correctly.

When we learn how to use the Debugger, we will also see how to add breakpoints to our methods and step through them while observing how they change the state of objects to help us debug any errors that we find. Using the Driver with the Debugger is illustrated in a later section of this document. For now, continue to explore the other commands in this Driver, and DO NOT fix the error in remove.

If you ever find your program in an infinite loop, you can terminate the program manually by clicking the Red Square on the top of the console window (the leftmost icon). Then you can click the Xx icon (two to the right of the Red Square) to clear out the console.

You can try out these commands by adding a value into the queue and then issuing the f command: it repeatedly removes values from the queue (printing each value that it removes) until the queue is empty (called "flushing" the queue). But, because of the error in the remove method, this action results in an infinite loop (because no values are correctly removed, so the queue never becomes empty). So click the Red Square and Xx to reset the code. To rerun the Driver, click the white right-pointing triangle in the green circle at the top of the main/big window (under and in between the Search and Project menus).

Finally, if you want to see the code for the DriverForOrderedCollection classes, double click the icon named DriverForOrderCollection.class. Eclipse will put this code in a Read-Only editor window, because this code comes from a library you cannot change. If you want to see the code for the LinearArrayQueue classes, click the + in front of the icon named edu.uci.ics.pattis.ics23.collection (the one right under Program0 and then double-click the icon named LinearArrayQueue.java, which you can examine and change in an editor window.


Run the JUnit Test Each data type that we will discuss this quarter also has a JUnit test. While a Driver for a class is Java code that allows us to manually test it, a JUnit test for a class is Java code that automatically tests the class. It produces graphical output to show clearly which tests passed and which tests failed; and for the failed tests, it produces more detailed information about how the test failed. When the code is corrected, it is very easy to rerun automatically all the tests and observe the changes (hopefully more/all test are passed now).

To run a JUnit test program, we must first find it: But first, click the - in front of Referenced Libraries; the - should change to a + and all the icons underneath it should be elided.

  • Click the + in front of project's name, the icon named Program0; the + should change to a - and three icons should appear, indented underneath Program0.

  • Click the + in front of the icon named edu.uci.ics.pattis.ics.collections; the + should change to a - and two icons should appear, indented underneath Program0.

  • Right-click the icon and/or name TestQueue.java; hover over Run As and click JUnit Test.
The result of these commands is illustrated below.

  You can examine the code in this class by double-clicking the icon and/or name TestQueue.java. Each interface has its own JUnit test, reflecting the semantics (meaning) of what the methods in a class implementing the interface do. It is good to be able to read and understand this code (and you will get more experience doing so during the quarter) because it can be useful to add debugging code to it: typically printing the state of variables at the time a test/assertion failed. Mostly JUnit code intersperses calls to the methods of the class being tested with assertions about what the results of those method-calls should be: a test method fails when any assertions in it fail.

If you have not already done so, follow the instructions described above to start running the JUnit test in the Console tab at the bottom of Eclipse. Answer the first prompt by just pressing the Enter/Return key (it is as if you typed the default value that appears in the parentheses); then answer the second prompt by typing the number in brackets that precede LinearArrayQueue (which should be option 2); finally, answer the last prompt by also just pressing the Enter/Return key (it is as if you typed the default value that appears in the parentheses).

A tab labelled JUnit will obscure the tab labelled Package Explorer in the leftmost window in Eclipse. In fact, the JUnit tab will split in half, with the bottom pane labelled Failure Trace. The large scale speed tests take some time to complete, but even so, very quickly all the tests will appear, some marked with a green check (passed) and some marked with a Blue S (failed). The green progress bar changes to red because not all tests were passed; above the progress bar it shows 14 tests run and 7 tests failed (we'll discuss the 0 test errors below: errors and failures are indicate two different problems with the code being tested). The result of running the JUnit test is illustrated below.

  It is possible that incorrect code will result in an infinite loop in a JUnit test; you will see that test as active, with the tests after it neither marked Green nor Blue. In such a case, you would have to manually stop the program as described above (clicking the Red Square in the Console window). In the graphic above, the Red Square is greyed-out, because the JUnit test has already terminated.

You have a choice of either commenting out the @Test annotation at the beginning of the problematic test (so JUnit won't run this test) or keeping the test and immediately debugging the code that is causing it to loop infinitely. If you choose the former, remember to reactivate the test eventually.

To investigate a failed test further, we can click on any of the test names labelled with the Blue X; for now, click on remove (second from the bottom). By doing so, information appears in the bottom pane explaining the failure in more detail. To read this information, you will probably need to widen the leftmost window, containing the JUnit tab.

  The first line in the Failure Trace pane tells us that there was a problem regarding the length of the arrays: the actual length of the array representing the queue was 5 when it should have been 4 Double clicking the next line in the Failure Trace pane shows us the line in the TestQueue program that discovered the problem: the failed assertion is on line 109. (there were originally 5 values in the queue, but after executing the remove method on this line there should be 4). This relates to the same problem discovered in the Driver: the remove method does not actually remove the value from the queue, so instead of a correct size of 4, it is one bigger.

To see this problem more clearly, put the statement

   System.out.println("When testing "+testing+", Queue before move is " + q);
right before the first assertEquals in the testRemove method (the one that is succeeding) and put a similar statement right after that assertEquals -before the assertArrayEquals that is failing. Run the JUnit test and notice that this code executes a few times, but the queues are always the same before and after calling q.remove(). That is why the asserArrayEquals fails.

  By placing output statements in a JUnit test, we can more closely examine information about the state of the queue that is failing the test.

In fact, all the test failures relate to this single bug: remember that sometimes fixing one bug will cause many failed tests to pass. As stated above, this "bug" is in the remove method in the LinearArrayQueue class (see lines 82-83). Restore the code objectCount-- (uncomment it) to fix the error.

  Then rerun this JUnit test.

Again you will see all the tests as they execute, with the "large scale" tests taking a bit longer than the others. Because now all tests pass, instead of showing all the individual test, JUnit shows just one icon for the entire test (labelled edu.uci.ics.pattis.ics23.collections.TestQueue). We can click the + in front of its icon to disclose the individual tests.

Notice also that at the top of the JUnit tab a green progress bar lengthens as each new test is performed, and spans the entire window when all tests are completed. It ultimately displays Runs 14/14, meaning it has completed all fourteen of the fourteen tests. It also displays 0 Errors and 0 Failures; in JUnit Errors are distinct from Failures.

  • An error occurs when the testing code throws an exception unexpectedly and cannot finish.

  • A failure occurs when some assertion is not met; the Failure Trace pane shows the first failure (and only the first failure) in each test.
Both errors and failures indicate that the code is incorrect and should be fixed. Of course, we must be careful because it is possible that an assertion is incorrect: e.g., an assertion asserts the size of the queue is some number but based on the add/remove methods called in the JUnit test it should be some other number. While you should mostly believe the JUnit tests I distribute, there is always the possibility that I have made a mistake. If you look closely at a JUnit test and don't understand why some failing assertion should be true, please contact me to resolve the problem

It is possible to redo just one test. A scenario in which this option is useful is when a few tests are failing, but it takes a long time to pass other tests which JUnit runs first. In such a case, we might want to bypass the long tests and concentrate on just the one test that is failing. To do so, ensure that the icon labelled edu.uci.ics.pattis.ics23.collections.TestQueue) is disclosed and then right-click one test and select Run. JUnit will run just that one test.

Again remember that if you comment-out the @Test annotation at the beginning of any test method, JUnit won't run this test. This is another way to avoid running long tests that the code is currently passing. But remember to uncomment such test methods for a final test of your code, before submitting it.


Debug the Code in the Driver In this section we will examine how to use the Eclipse Debugger along with the Driver program to explore the code that implements the LinearArrayQueue class. In actual assignments, when you write classes that may contain bugs, the skills illustrated here will be very useful for locating and correcting errors.

First read and follow the directions in the Debugger Tutorial to learn about the Debugger.

Specifically, you should learn how to set breakpoints, how to single step over (execute) lines of code, and how to observe the values of variables. Becoming familiar with the Debugger now will help you immeasurably later in the quarter; for every hour you play with the Debugger now, I estimate you will save 3 hours later in the during the quarter, by being able to use the Debugger skillfully to correct your code.

After you have read the Debugger Tutorial, perform the actions below.

Run the DriverForOrderedCollection program (not the JUnit test) as described above. Immediately stop this program and clear the Console (click the Red Square and Xx buttons). Then start the Debugger perspective (click Debug) and rerun this program in the Debugger (click the green bug icon). Set unconditional breakpoints on the first line of code in the add and remove methods (lines 64 and 76 respectively). Start running the program by clicking the right-pointing green arrow (after the Debug tab in the upper-left window).

On some machnines, Eclipse will display a tab URL ClassLoader.class with the line

  throw new ClassNotFoundException(name);
highlighted in green. If your machine displays this tab, follow the directions below; if not, skip this next section -down to where it says You will be prompted in the console window...


Click in "Breakpoints" tab in the upper-rightmost window: there, click the box that shows a check before the classNotFoundException: caught and uncaught and the check should disappear.

  Then click the right-pointing green arrow (to the right of the Debug tab in the upper-left window) again.


You will be prompted in the console window for the basic information needed to start the Driver. Issue the a command and the String test1.

At that point the Debugger should stop at line 64, highlighted by a green line (this line is about to be executed). If we disclose the this variable in the Variables tab it should display the following information

  Notice that the modCount and objectCount instance variables are both 0, the one element in the q array stores null (refernce to no String). Notice also that the parameter variable e refers to the String "test1".

Now, step over/execute each of the statements in this method, watching how each statement changes the instance variables in the disclosed this. When the last line (return statement) is about to be executed, the Variables tab should display the following information.

  At this point click the right-pointing green arrow again and issue the a command and the String test2. Now, step over/execute each of the statements in this method, watching how each statement changes the instance variables in the disclosed this. When the last line (return statement) is about to be executed, the the Variables tab should display the following information.

  Note the new values for modCount, objectCount, and q (whose length has been doubled to 2).

At this point click the right-pointing green arrow again and issue the r command. The Debugger should stop at line 76, highlighted by a green line (this line is about to be executed). The Variables tab it should display the following information

  Now, step over/execute each of the statements in this method, watching how each statement changes the instance variables in the disclosed this. When the last line (return statement) is about to be executed, the the Variables tab should display the following information.

  Note that the answer to be returned is test1. Although "test2" is stored queue[0] and queue[1], the fact that objectCount stores 1 indicates queue currently stores only one value that will ever be examined. We could have put the line
  q[objectCount-1] = null;
directly after the for loop to store null into q[1], but as in the clear method, we have chosen to omit this unnecessary code.

In summary, it is important to know how to use the basics of the Debugger: to set breakpoints, to single step over/execute code, and to observe the values of variables (possible using disclosure to see "inside" an object). When we used the Debugger with the Driver program, we can carefully watch how our code works -or more importantly, watch how it fails to work to be able to debug it.


Submit the Program for Grading via Checkmate After you have fixed the code and verified that it works correctly via the Driver and the JUnit tester, you should practice submitting the code for grading via Checkmate. Remember that although this assignment is not graded, you should submit it so that I will know that you know how to submit code correctly.

Information about using Checkmate is available via the Handouts (General) link on the webpage; there, click the Windows/ Operating System and Eclipse IDE link. Or, see the Submitting Work link at the bottom of the Tutorial on the Windows Operating System and Eclipse IDE.


Final Words Finally, after you are done submitting your code you should backup/save the entire project on a USB device (even if you are using your own computer, you should still backup your work). Probably it is best to zip the project folder first (which makes it smaller and also speeds up copying -which depends as much on how many files you copy as on the size of the files). If you are on a lab machine, you can also backup/save this folder on your Unix file space.

Information about using your Unix storage is available via the Handouts (General) link on the webpage; there, click the Windows/ Operating System and Eclipse IDE link. Or, see the File Storage link in the Tutorial on the Windows Operating System and Eclipse IDE.

Practice doing everything in this lab over and again, until you are familiar with all these skills and can do them without reading the directions. You will save yourself much time during the quarter (when time is really important) if you spend some time now (when things aren't so rushed) mastering the material in the "programming assignment".