/** * */ package restaurant.test; import static org.junit.Assert.*; import java.awt.Color; import java.util.Collections; import java.util.LinkedList; import java.util.List; import junit.framework.TestCase; import org.junit.Before; import org.junit.Test; import restaurant.CookAgent; import restaurant.WaiterAgent; import restaurant.interfaces.*; import restaurant.layoutGUI.Food; import restaurant.test.Mock.MockCook; import restaurant.test.Mock.MockCustomer; import restaurant.test.Mock.MockHost; /** * This is a set of tests for the normal Waiter interaction cycle. This suite * tests all of the waiter messages, with a single customer. Note, this does not * test multiple customers. These are contained in the * WaiterAgentTestsWithTwoCustomers.
*
* Note that the unit of test in this file is the individual message. We call * the appropriate functions to get the WaiterAgent ready to accept and process * a particular message and then make assert statements surrounding that * message. This breaks testing this one interaction up into 5 different test * methods. You could also integrate all of this into one large test method. We * do this when testing a WaiterAgent with multiple customers. Both styles are * valid and which one is best depends on the goal of your particular tests.
* This set of tests is invaluable when first writing your WaiterAgent. It will * validate that your waiter implements the messaging contract described in the * interaction diagram. In building an agent system, I would actually write * these unit tests before writing the WaiterAgent itself. This practice is * called Test Driven Development (TDD). * * @author Sean Turner * */ public class WaiterAgentTestsWithOneCustomer extends TestCase { /** * This is the WaiterAgent to be tested. */ public WaiterAgent waiter; /** * Test method for * {@link restaurant.WaiterAgent#msgSitCustomerAtTable(restaurant.CustomerAgent, int)} * . * * This method creates a WaiterAgent and a MockCustomer. The waiter is * messaged that the customer needs to be seated. The waiter's scheduler is * then called. The customer should receive msgFollowMeToTable after the * scheduler is called. */ @Test public void testMsgSitCustomerAtTable() { // Create a WaiterAgent WaiterAgent waiter = new WaiterAgent("Waiter1", null, null, null); // Create a MockCustomer MockCustomer customer = new MockCustomer("Customer1"); // Message the waiter to sit the customer at table 3 waiter.msgSitCustomerAtTable(customer, 3); // This will check that you're not messaging the customer in the // waiter's message reception. assertEquals( "Mock Customer should have an empty event log before the Waiter's scheduler is called. Instead, the mock customer's event log reads: " + customer.log.toString(), 0, customer.log.size()); // Call the waiter's scheduler waiter.pickAndExecuteAnAction(); // Now, make asserts to make sure that the scheduler did what it was // supposed to. assertTrue( "Mock customer should have received message to go to table. Event log: " + customer.log.toString(), customer.log .containsString("Received message msgFollowMeToTable")); assertEquals( "Only 1 message should have been sent to the customer. Event log: " + customer.log.toString(), 1, customer.log.size()); assertTrue("Message should be sent from " + waiter.toString(), customer.log.getLastLoggedEvent().getMessage().contains( waiter.toString())); } /** * Test method for * {@link restaurant.WaiterAgent#msgImReadyToOrder(restaurant.CustomerAgent)} * . Tests that once a customer messages he is ready to order and the * waiter's scheduler is called, the waiter messages the customer to ask * msgWhatWouldYouLike. */ @Test public void testMsgImReadyToOrder() { WaiterAgent waiter = new WaiterAgent("Waiter1", null, null, null); MockCustomer customer = new MockCustomer("Customer1"); waiter.msgSitCustomerAtTable(customer, 3); assertEquals( "Mock Customer should have an empty event log before the Waiter's scheduler is called. Instead, the mock customer's event log reads: " + customer.log.toString(), 0, customer.log.size()); waiter.pickAndExecuteAnAction(); waiter.msgImReadyToOrder(customer); assertFalse( "Mock customer should not have received msgWhatIsYourOrder before scheduler call.", customer.log.containsString("msgWhatWouldYouLike")); waiter.pickAndExecuteAnAction(); assertTrue("Mock customer should have received msgWhatIsYourOrder.", customer.log.containsString("msgWhatWouldYouLike")); } /** * Test method for * {@link restaurant.WaiterAgent#msgHereIsMyChoice(restaurant.CustomerAgent, java.lang.String)} * . */ @Test public void testMsgHereIsMyChoice() { WaiterAgent waiter = new WaiterAgent("Waiter1", null, null, null); MockCook cook = new MockCook("Cook1"); waiter.setCook(cook); MockCustomer customer = new MockCustomer("Customer1"); waiter.msgSitCustomerAtTable(customer, 3); waiter.pickAndExecuteAnAction(); waiter.msgImReadyToOrder(customer); waiter.pickAndExecuteAnAction(); waiter.msgHereIsMyChoice(customer, "Salad"); assertEquals( "Cook's log should be empty before waiter scheduler called. Instead, it is " + cook.log.toString(), 0, cook.log.size()); waiter.pickAndExecuteAnAction(); assertTrue("Cook should have received message to cook order.", cook.log .containsString("msgHereIsAnOrder")); assertTrue("Order should be for table 3", cook.log.getLastLoggedEvent() .getMessage().contains("3")); assertTrue("Order should be for salad.", cook.log.getLastLoggedEvent() .getMessage().contains("Salad")); } /** * Test method for * {@link restaurant.WaiterAgent#msgOrderIsReady(int, restaurant.layoutGUI.Food)} * . */ @Test public void testMsgOrderIsReady() { WaiterAgent waiter = new WaiterAgent("Waiter1", null, null, null); MockCook cook = new MockCook("Cook1"); waiter.setCook(cook); MockCustomer customer = new MockCustomer("Customer1"); waiter.msgSitCustomerAtTable(customer, 3); waiter.pickAndExecuteAnAction(); waiter.msgImReadyToOrder(customer); waiter.pickAndExecuteAnAction(); waiter.msgHereIsMyChoice(customer, "Salad"); waiter.pickAndExecuteAnAction(); waiter.msgOrderIsReady(3, new Food("Salad", Color.BLUE, null)); assertFalse(customer.log.containsString("msgHereIsYourFood")); waiter.pickAndExecuteAnAction(); assertTrue("Waiter should deliver food to customer.", customer.log .containsString("msgHereIsYourFood")); } /** * Test method for * {@link restaurant.WaiterAgent#msgDoneEatingAndLeaving(restaurant.CustomerAgent)} * . */ @Test public void testMsgDoneEatingAndLeaving() { WaiterAgent waiter = new WaiterAgent("Waiter1", null, null, null); MockCook cook = new MockCook("Cook1"); MockHost host = new MockHost("Host"); waiter.setCook(cook); waiter.setHost(host); MockCustomer customer = new MockCustomer("Customer1"); waiter.msgSitCustomerAtTable(customer, 3); waiter.pickAndExecuteAnAction(); waiter.msgImReadyToOrder(customer); waiter.pickAndExecuteAnAction(); waiter.msgHereIsMyChoice(customer, "Salad"); waiter.pickAndExecuteAnAction(); waiter.msgOrderIsReady(3, new Food("Salad", Color.BLUE, null)); waiter.pickAndExecuteAnAction(); waiter.msgDoneEatingAndLeaving(customer); assertEquals( "Host log should be empty before scheduler is called. Instead, log reads " + host.log.toString(), 0, host.log.size()); waiter.pickAndExecuteAnAction(); // It takes a while for the waiter to actually clear the table. Because // this action happens on a separate thread, we need to wait for this // thread to complete its action before we return. However, it is // possible that there is an error in the waiter code that would never // actually clear the table. We want to write a test that will wait a // short time for the table to be cleared, and fail if the test doesn't // complete in that period of time. int timer = 0; int timeout = 1000 * 7; while (timer < timeout && !host.log.containsString("table 3 is free")) { try { Thread.sleep(50); } catch (InterruptedException e) { } timer += 50; } assertTrue("Host should have been messaged that table is free.", host.log.containsString("table 3 is free")); } }