1 / 25

Unit Testing

Unit Testing. Testing – A Methodology. For small problems, you write code, test it at the terminal, turn it in, never to see it again. Large systems have a long lifetime. Sitting-at-terminal-type testing is inappropriate for large systems that evolve over time.

milek
Download Presentation

Unit Testing

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Unit Testing

  2. Testing – A Methodology • For small problems, you write code, test it at the terminal, turn it in, never to see it again. • Large systems have a long lifetime. • Sitting-at-terminal-type testing is inappropriate for large systems that evolve over time. • You must have a testing methodology that permanently captures the test cases and can be rerun at will. • Fortunately, serious developers have built frameworks for unit testing: • JUnit is for Java. • CppUnit for C++.

  3. JUnit – The Philosopy • Never throw a test away. • Make every thought a test. • Instead of a print statement or a debugger expression, write it as a test instead. • No test is too hard to encode. • Anything is better than testing at a terminal. • Once tests run, keep them running. • Write a few lines of code, then write a few tests. • When you can't think up any more tests, you're done.

  4. How JUnit Works class Money { private int fAmount; private String fCurrency; public Money(int amount, String currency) { fAmount= amount; fCurrency= currency; } public int amount() { return fAmount; } public String currency() { return fCurrency; } }

  5. Add Monies • public Money add(Money m) {    • return new Money(amount()+m.amount(), currency()); • } • Now what? Write More Code? • No, write some tests.

  6. A Simple Test Case public class MoneyTest extends TestCase { //… public void testSimpleAdd() { Money m12CHF= new Money(12, "CHF"); // (1) Money m14CHF= new Money(14, "CHF"); Money expected= new Money(26, "CHF"); Money result= m12CHF.add(m14CHF); // (2) Assert.assertTrue(expected.equals(result)); // (3) } }

  7. Need to override equals public boolean equals(Object anObject) { if (anObject instanceof Money) { Money aMoney= (Money)anObject; return aMoney.currency().equals(currency()) && amount() == aMoney.amount(); } return false; }

  8. Now more "equals" tests public void testEquals() { Money m12CHF= new Money(12, "CHF"); Money m14CHF= new Money(14, "CHF"); Assert.assertTrue(!m12CHF.equals(null)); Assert.assertEquals(m12CHF, m12CHF); Assert.assertEquals(m12CHF, new Money(12, "CHF")); // (1) Assert.assertTrue(!m12CHF.equals(m14CHF)); }

  9. Now a little refactoring… public class MoneyTest extends TestCase { private Money f12CHF; private Money f14CHF; protected void setUp() { f12CHF= new Money(12, "CHF"); f14CHF= new Money(14, "CHF"); } // We can rewrite the two test case methods, removing the common setup code: public void testEquals() { Assert.assertTrue(!f12CHF.equals(null)); Assert.assertEquals(f12CHF, f12CHF); Assert.assertEquals(f12CHF, new Money(12, "CHF")); Assert.assertTrue(!f12CHF.equals(f14CHF)); } public void testSimpleAdd() { Money expected= new Money(26, "CHF"); Money result= f12CHF.add(f14CHF); Assert.assertTrue(expected.equals(result)); } }

  10. Just Two More Steps • define how to run an individual test case, • define how to run a test suite. Let's concentrate on the test suite

  11. A Test Suite public static Test suite() { TestSuite suite= new TestSuite(); suite.addTest(new MoneyTest("testEquals")); suite.addTest(new MoneyTest("testSimpleAdd")); return suite; } or you can do the following: public static Test suite() {    return new TestSuite(MoneyTest.class); }

  12. And then to run it… • for the batch TestRunner type:   java junit.textui.TestRunner junit.samples.MoneyTest • for the graphical TestRunner type:   java junit.awtui.TestRunner junit.samples.MoneyTest • for the Swing based graphical TestRunner type:   java junit.swingui.TestRunner junit.samples.MoneyTest

  13. How About Testing Agents? • Send it a message. • Are the state variables set correctly on message reception? • Does the scheduler pick the right actions, if any, to execute? • Do the actions do the right things? • Do they update their state correctly; • Do they send the right messages out.

  14. Checking Message Reception To test the “I’m hungry(customer)” message: • waitingCustomers list is not null. • customer is in the list. • customer is at the end of the list (if you expect a FIFO discipline). • Make sure the semaphore is full.

  15. Controlling the Scheduler • The scheduler’s “automatic” mode interferes with our testing. • Can we turn off the scheduler and call it ourselves from the testing code? • Yes! • Call stopThread() • Make respondToStateChange() public

  16. Our Testing Code So Far Customer c = new Customer(“John”); Waiter w = new Waiter(“Bill”) Host h = new Host(); h.stopThread(); h.msgI’mHungry(c); //now comes code to test the variables Assert.assertTrue(waitingCustomers NEQ NIL)); //other tests … respondToStateChange(); //calls the scheduler

  17. Does The Right Action Fire? • If there are tables empty, you want the waiter assignment action to fire. • If the tables are full you want to make sure that nothing happens. • You have to set up several experiments to check out ALL the possibilities. • Let’s look at the case where tables are free and we expect the waiter assignment action to fire.

  18. Does The Right Action Fire? • The first line action code is a Print • The Junit discussion, they said whenever you have a print statement in your code, you should consider writing a test. • Put the string into a public data structure, such as an array of strings, which can be tested. • Assume your action outputs the string “Assigning waiter Bill to sit customer John at table 1.” • Then, you can write a test: Assert.assertTrue(output[0].equals(“Assigning waiter Bill to sit customer John at table 1”));

  19. Testing the Rest of an Action • Testing state changes will involve techniques we’ve already explored. • What about testing whether the agent sends the right messages to other agents? • That’s not so easy. Mock Objects to the rescue.

  20. Mock Objects • Mock Objects are simulation versions of those that your component/agent uses in doing its work. • With parallel development, the real versions of those objects may not exist. • You must checkout your objects as best you can in preparation for integration.

  21. Testing the Sent Message • Testing to make sure the message that this Host action composes is compliant with the Waiter’s messaging interface. • Mock objects are fake implementations of objects, but have the same interface as the real objects. • Their purpose is to SIMULATE the real objects strictly for testing.

  22. Mock Object Message Handler • It outputs a string that describes the message and its parameters. That string is going to be what you test against. • It then does WHATEVER you need it to do in order to advance your simulation and testing. • Remember it is pure simulation. • It might simply send a message back to your agent. • It might send an error message back. • It might start a timer and send a message back later. You design it.

  23. The Mock Waiter • It needs to output what’s in the message, e.g. “Waiter Bill receives message to seat customer John at table 1.” [You will verify this output in your test code.] • The real waiter would set some variables, seat the customer, take his order, etc. When the customer is done, the waiter informs the Host. • All we care about is the message back to Host. • The mock Waiter can send the message; or • Your testing code can send it (after testing that it received the right message).

  24. The Mock Agents Environment • The real agent should not care whether it is running in the real or test environment. • The mock agents must have the same class names as the real agents. • The Ant environment must store mock objects “near” the real agent and the unit test suites. • Don’t forget, if the interface of an agent changes, the mock agents, and the tests need to be fixed.

More Related