A Student User Interface


In this section, you will write a very simple console-based user interface (UI). The UI will allow an end user of the student information system to create student objects. You will prompt the user with a simple menu that either drives the addition of a new student or allows the user to terminate (exit) the application.


There are many ways to approach development of a user interface through TDD. The following test, implemented in the class StudentUITest, presents one solution. I have broken the listing into three parts for clarity. The first part shows the core test method, testCreateStudent.

 package sis.ui; import junit.framework.*; import java.io.*; import java.util.*; import sis.studentinfo.*; public class StudentUITest extends TestCase {    static private final String name = "Leo Xerces Schmoo";    public void testCreateStudent() throws IOException {       StringBuffer expectedOutput = new StringBuffer();       StringBuffer input = new StringBuffer();       setup(expectedOutput, input);       byte[] buffer = input.toString().getBytes();       InputStream inputStream = new ByteArrayInputStream(buffer);       BufferedReader reader =          new BufferedReader(new InputStreamReader(inputStream));       OutputStream outputStream = new ByteArrayOutputStream();       BufferedWriter writer =          new BufferedWriter(new OutputStreamWriter(outputStream));       StudentUI ui = new StudentUI(reader, writer);       ui.run();       assertEquals(          expectedOutput.toString(),          outputStream.toString());       assertStudents(ui.getAddedStudents());    }    private String line(String input) {       return String.format("%s%n", input);    }    ... } 

The test creates two StringBuffers. One will hold expected outputwhat the console application displaysand the other will hold the input that a user (the test, in this case) types in. The setup method explicitly populates each of these:

 private void setup(StringBuffer expectedOutput, StringBuffer input) {    expectedOutput.append(StudentUI.MENU);    input.append(line(StudentUI.ADD_OPTION));    expectedOutput.append(StudentUI.NAME_PROMPT);    input.append(line(name));    expectedOutput.append(line(StudentUI.ADDED_MESSAGE));    expectedOutput.append(StudentUI.MENU);    input.append(line(StudentUI.QUIT_OPTION)); } 

The setup method can be viewed as presenting a script to which the system must adhere. The buffer appends are intertwined to emulate the interaction between system output and user input. This natural flow should aid you in understanding the script. First, the user interface presents the user with a menu:

 expectedOutput.append(StudentUI.MENU); 

The user responds to the menu by first typing the option to add a student, then pressing enter.

 input.append(line(StudentUI.ADD_OPTION)); 

The line method is a utility method that appends an end-of-line string to an input string. The remainder of the setUp method represents the expected sequence of events between the system presenting some text (expectedOutput.append) and the user entering a response (input.append).

The code in testCreateStudent creates an InputStream by wrapping a Byte-ArrayInputStream around the bytes from the input StringBuffer. It then creates an InputStreamReader, wrapped with a BufferedReader, to convert incoming bytes to characters.

Similarly, the test creates and wraps a ByteArrayOutputStream with an OutputStreamWriter that will convert characters to bytes. A BufferedWriter wraps the OutputStreamWriter.

You pass these two streams, reader and writer, to the constructor of Student-UI after setup executes. The UI is told to run and should continually present a menu of options until the user chooses to quit.

After the UI completes processing, an assertion verifies that the application produced correct output. The assertion compares the contents of the ByteArrayOutputStream to the contents of the expectedOutput StringBuffer.

Finally, the test calls assertStudents to ensure that the list of students created and stored in the UI instance is as expected.

 private void assertStudents(List<Student> students) {    assertEquals(1, students.size());    Student student = students.get(0);    assertEquals(name, student.getName()); } 

To verify the example user "script" coded in the setup method, assertStudents must ensure that the StudentUI object added only one student and that this student's data (its name) is as expected.

The entire StudentUI implementation appears below. To build this class test-first and very incrementally, you should start with an even simpler set of unit tests. First, ensure that the menu is presented and that the user can immediately quit the application. Then add functionality to support adding students. Start with assertions against the user interface flow, then add the assertion to ensure that a student object was created. A more complete test than this would ensure that multiple students could be created.

 package sis.ui; import java.io.*; import java.util.*; import sis.studentinfo.*; public class StudentUI {    static final String MENU = "(A)dd or (Q)uit?";    static final String ADD_OPTION = "A";    static final String QUIT_OPTION = "Q";    static final String NAME_PROMPT = "Name: ";    static final String ADDED_MESSAGE = "Added";    private BufferedReader reader;    private BufferedWriter writer;    private List<Student> students = new ArrayList<Student>();    public StudentUI(BufferedReader reader, BufferedWriter writer) {       this.reader = reader;       this.writer = writer;    }    public void run() throws IOException {       String line;       do {          write(MENU);          line = reader.readLine();          if (line.equals(ADD_OPTION))             addStudent();       } while (!line.equals(QUIT_OPTION));    }    List<Student> getAddedStudents() {       return students;    }    private void addStudent() throws IOException {       write(NAME_PROMPT);       String name = reader.readLine();       students.add(new Student(name));       writeln(ADDED_MESSAGE);    }    private void write(String line) throws IOException {       writer.write(line, 0, line.length());       writer.flush();    }    private void writeln (String line) throws IOException {       write(line);       writer.newLine();       writer.flush();    } } 



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net