Week 11: Lab 7 - Introductory Programming in Java Skip navigation Introductory Programming in Java ANU College of Engineering & Computer Science Search query Search ANU web, staff & maps Search COMP6700 Lectures Labs Assignments menu Search query Search ANU web, staff & maps Search Search COMP6700 labs Week 01: Welcome Week 02: Lab 1 Week 03: Lab 2 and HW 1 Week 04: Lab 3 and HW 2 Week 05: Drop-in Lab, HW 3 Week 06: Lab 4 and HW 4 Week 07: Mid-sem Exam Week 08: Free (Anzac Day) Week 09: Lab 5 and HW 5 Week 10: Lab 6 and HW 6 Week 11: Lab 7 and HW 7 Week 12: Lab 8 and HW 8 related sites Wattle Piazza Week 11: Lab 7 Test-Driven Development Objectives This lab provides further practice with test-driven development, using a simple implementation of the list abstract data type. 0. Get the Code All code for this exercise is contained in an IntelliJ workspace in Course GitLab repository. Before you start working on this lab, make sure you update your Git repository to the latest version of the upstream code. Using the command line (Terminal application on Mac/Linux, or Git-Bash on Windows) in the directory of your local comp6700-2017 repository, execute the following commands: git pull git@gitlab.cecs.anu.edu.au:comp6700/comp6700-2017.git master
git checkout -b u1234567/comp6700-2017-master FETCH_HEAD
(as usual, don’t forget to replace the "u1234567" part in the git URL address with your actual university ID). Review the changes if required; then merge the branch and fix any conflicts that come up: git checkout master
git merge --no-ff u1234567/comp6700-2017-master
You can then open the IntelliJ workspace using File -> Open… and select the lab7 directory in your local Git repository. 1. Understand the Code Your starting point is the BookList interface, as introduced in lecture A1. This interface defines an abstract data type that is very similar to the Java generic type java.util.List, however, it only operatates on instances of the Book class. public class Book implements Comparable {
//...
}
public interface BookList extends Iterable {
public void addFirst(Book newBook);
public boolean add(Book newBook);
//public boolean remove(Book book); // not yet defined
public void insert(Book newBook, int position);
public Book get(int position);
public boolean isEmpty();
//public boolean contains(Book book); // not yet defined
public int size();
public String toString();
public Iterator iterator();
}
In addition to BookList, there is a concrete implementation of the list ADT using a linked list, called BookListWithLL. Two of the methods on BookList are commented out; you will uncomment them and implement these methods in BookListWithLL later in the lab. Most important of all, there is a test class TestBookList, which already contains a number of unit tests for the BookListWithLL implementation. As well as running the existing tests, you will create additional tests for new functionality. In IntelliJ, run all four tests on TestBookList; they should all pass. Read the test code so you understand how it is testing each of the methods on BookListWithLL. 2. Add a New Test for Existing Code The method BookList.insert(...) has already been implemented, but is not tested. Create a new unit test TestBookList.testInsert() to ensure that the insert method is correctly implemented. When designing your unit test, carefully consider how insert changes the state of the list, for example, the position of the books that were already in the list. Think about the pre-conditions, post-conditions and class invariants that should be true for the correct operation of the method. A pre-condition is a condition that must be true about the state of the class or the parameters to the method before the method is run. Often it is not meaningful to directly test a pre-condition, but identifying the pre-conditions can help determine what should not be tested, e.g. if a pre-condition for a method is that a given parameter should not be null, then it does not make sense to test for correct operation of the method in the case that the parameter is null. A post-condition is a condition that must be true after running the code in the method. The assertions you write in your unit tests will most commonly check post-conditions, i.e. myObject.someMethod();
assert (/*post-condition for someMethod() */);
A class invariant is a condition that must always be true for a correctly constructed instance of the class. Unit tests also often include assertions to check class invariants, because (obviously) a class invariant must still be true after running the code in any method of that class. 3. Add a New Test for Yet-To-Be-Written Code The method BookList.contains(...) has not yet been defined. (It is commented out in the interface definition.) Uncomment this method and write a skeleton implementation in BookListWithLL, for example: public boolean contains(Book book) {
return false;
}
Now write a new unit test, TestBookList.testContains(), to test your new method. Your new test should fail, because the skeleton code is not a correct implementation of the method. (This is the red phase of the ‘red-green-refactor’ cycle of test-driven development). 4. Write New Code to Make the Test Pass Replace the skeleton code of BookListWithLL.contains(...) with a complete implementation, to make TestBookList.testContains() pass. (This is the green phase of TDD). 5. Refactor There are three pieces of code in BookListWithLL which all perform the same basic function: stepping through the list from the beginning until the node at a particular position is reached. Look at the methods add(...), insert(...) and get(...) - you should notice that a portion of the code is essentially the same between these three methods. Refactor the class to extract this code into a new private method that returns the node at a given position, and replace these three pieces of replicated code with calls to the new private method. Ensure that all unit tests pass both before and after your changes to the code. (This is the refactor phase of TDD). 6. … and Repeat (Optional) The remove() method is also not defined or implemented. Uncomment the BookList.remove() method, create a skeleton in BookListWithLL and create a new unit test. Then write a complete implementation of BookList.remove() so that your test passes. Updated: 15 May 2017/ Responsible Officer: Head of School/ Page Contact: Alexei Khorev Contact ANU Copyright Disclaimer Privacy Freedom of Information +61 2 6125 5111 The Australian National University, Canberra CRICOS Provider : 00120C ABN : 52 234 063 906 You appear to be using Internet Explorer 7, or have compatibility view turned on. Your browser is not supported by ANU web styles. » Learn how to fix this » Ignore this warning in future