24.1. Chat Room FixturesWe now look at the fixtures underlying the tables in Section 6.1 on p. 39. These fixtures are similar to the ones given in Section 22.2 on p. 190 and Section 23.1 on p. 195, except that they are organized to reference the same system under test. It is useful to understand the steps that are carried out when a sequence of tables is used. We look at the first six tables of the second example test in Section 6.1, shown again in Figure 24.1. Figure 24.1. TestConnectAndDisconnect
When it is run by Fit, the first Fit table in Figure 24.1 creates an ActionFixture object, shown as af1 to the left in Figure 24.2. The first action of the first table is a start, which creates the actor, shown as the ChatServer2 object in Figure 24.2. Figure 24.2. Fit Runs the First Table
Class ChatServer2 is shown in Listing 24.1.[1] Its constructor is called when the actor object is created, which in turn creates the system under testan object of class ChatRoomas shown at the bottom of Figure 24.2.
The constructor of ChatServer2 saves a reference to the system under test in the static variable CHAT. Subsequent actions through the fixture ChatServer2, in tables 2 and 4, both act through this static variable (from af2 and af3) on the single system under test,[2] as shown in Figure 24.3.
Figure 24.3. Fit Runs the Tables
When it runs the third table in Figure 24.1, Fit creates ol1, a fixture object of class OccupantList2, as shown under the third table in Figure 24.3. This object checks that the rows in the table match the elements in the collection supplied by the RowFixture fixture class OccupantList2. The object accesses the system under test via the public static variable CHAT of class ChatServer2. Much the same happens when Fit runs the fifth table, as shown in Figure 24.3. Listing 24.1. ChatServer2.javapublic class ChatServer2 extends fit.Fixture { public static chat.ChatRoom CHAT; private String userName = ""; private String roomName = ""; public ChatServer2() { CHAT = new ChatRoom(); } public void user(String userName) { this.userName = userName; } public void connect() { CHAT.connectUser(userName); } public void room(String roomName) { this.roomName = roomName; } public void newRoom() { roomCreatedOK = CHAT.userCreatesRoom(userName, roomName); } public void enterRoom() { roomEnteredOK = CHAT.userEntersRoom(userName,roomName); } public int occupantCount() { return CHAT.occupants(roomName); } public void disconnect() { CHAT.disconnectUser(userName); } } The code for OccupantList2, shown in Listing 24.2, provides a collection of class Occupancy2, as shown in Listing 24.3. The collection comes from the current system under test, which is accessed through the static variable CHAT of class ChatServer2.[3]
Questions & Answers
Note A static variable of a class is shared by all instancesobjectsof that class. The variable can be accessed directly in any of the code of the class. If the variable is public, it can also be accessed from outside the class. For example, class OccupantList2 in Listing 24.2 accesses the static variable CHAT in class ChatServer2 through the expression ChatServer2.CHAT. Listing 24.2. OccupantList2.javapublic class OccupantList2 extends fit.RowFixture { public Object[] query() throws Exception { List occupancies = new ArrayList(); for (Iterator it = ChatServer2.CHAT.getRooms(); it.hasNext(); ) { Room room = (Room)it.next(); collectOccupants(occupancies,room); } return occupancies.toArray(); } public Class getTargetClass() { return Occupancy2.class; } private void collectOccupants(List occupancies, Room room) { for (Iterator it = room.users(); it.hasNext(); ) { User user = (User)it.next(); Occupancy2 occupant = new Occupancy2(room.getName(), user.getName()); occupancies.add(occupant); } } } Listing 24.3. Occupancy2.javapublic class Occupancy2 { public String room, user; public Occupancy2(String room, String user) { this.room = room; this.user = user; } } |