CS3340:   Intro OOP and Design

 

JUnit - a JavaBased Unit Testing Framework

  • Java based unit testing framework can use with any IDE.

  • http://junit.org/
  • junit.jar - package for JUnit

Eclipse and JUnit The STEPS

We will highlight the use of JUnit inside of Eclipse.

  1. Create a Project and make sure you add JUnit library to it in the Eclipse IDE

  2. Create some (at least basic) Project Class(es) Create some basic project class code ---it doesnt have to be complete but, at a beginning state with methods (maybe that initally do nothing) and some class variables. You can start unit testing on this basic code and add more code to it doing unit testing right away.

  3. For Each Class Create a TestCase class
    1. Right-click on the class to be tested
    2. Select New...JUnit Test Case
    3. Example Class - Dog, name the test class DogTest
    4. Select Finish -- creates your DogTest class, possibly with some boilerplate in it.
  4. NOTE: JUnit 3: that the create class extends the JUnit TestCase class and inherits a number of useful methods as described below in process
    NOTE: JUnit 4: you use annotations instead of extending a class and statically include methods for assertions

  5. For Each TestCase class - fill in the code for the logic for each test case method (see Process below)


JUnit Testing Code Development Process

  • Example DogTest class For JUnit 3: this extends JUnit's TestCase class But, for JUnit 4: you get annotations in front of methods.

  • For every method in the Dog (project code class), write a method in DogTest called testMethodName().
    • (JUnit simply looks for methods beginning with lowercase "test", and figures they must be test methods.)
    • For example, if the class being tested has a foo() method, then we might write a testFoo() method that calls foo() 5 different ways to see that it returns the right thing.
  • METHODS from JUnit TestCase class to help with testing "assertions:
    • assertsXXXX methods - come with JUnit to help test if results are what you expect.
    • assertsEqual, assertsTrue, and more!!!
      • assertEquals( desired-result, method-call );
        - Works for primitives, and uses .equals() for objects
      • assertTrue( expr-that-should-be-true );
    • This is a list of the different types of assertion statements that are used to test your code. Any Java data type or object can be used in the statement. These assertions are taken from the JUnit API.
      • assertEquals(expected, actual)
      • assertEquals(message, expected, actual)
      • assertEquals(expected, actual, delta) - used on doubles or floats, where delta is the difference in precision
      • assertEquals(message, expected, actual, delta) - used on doubles or floats, where delta is the difference in precision
      • assertFalse(condition)
      • assertFalse(message, condition)
      • assertNotNull(object)
      • assertNotNull(message, object)
      • assertNotSame(expected, actual)
      • assertNotSame(message, expected, actual)
      • assertNull(object)
      • assertNull(message, object)
      • assertSame(expected, actual)
      • assertSame(message, expected, actual)
      • assertTrue(condition)
      • assertTrue(message, condition)
      • fail()
      • fail(message)
      • failNotEquals(message, expected, actual)
      • failNotSame(message, expected, actual)
      • failSame(message)
    • use these in your testMethodName() methods to compare results.

 

JUnit 4 Annotations

@Test public void method() Annotation @Test identifies that this method is a test method.
@Before public void method() Will perform the method() before each test. This method can prepare the test environment, e.g. read input data, initialize the class)
@After public void method() Test method must start with test
@BeforeClass public void method() Will perform the method before the start of all tests. This can be used to perform time intensive activities for example be used to connect to a database
@AfterClass public void method() Will perform the method after all tests have finished. This can be used to perform clean-up activities for example be used to disconnect to a database
@Ignore Will ignore the test method, e.g. useful if the underlying code has been changed and the test has not yet been adapted or if the runtime of this test is just to long to be included.
@Test(expected=IllegalArgumentException.class) Tests if the method throws the named exception
@Test(timeout=100) Fails if the method takes longer then 100 milliseconds

 

Running JUnit

  • Select the test class (i.e. DogTest), right click, select Run JUnit Test OR RunAs -> JUnit Test Case
  • Click on the JUnit tab in the left pane to see the results

OR

  • click on the package on the left. Then running JUnit Tests will run all of the tests.

Example Running a set of methods in a TestCase clas called DogTest (see code below in Example 2)

test case running in eclipse

 

 

Understanding when a JUnit test has "failed"

  • double click a line in the "failures" list to go to the test method that failed.
  • The stack trace at the lower left shows the call sequence. If there was an assert failure, it shows the expected and actual values. Double click it to get details of the expected and actual values.
  • The data and variables are not live -- the JUnit report is of what happened in the past
  • To see the data live, put a breakpoint in the work code, and select Debug... to run the unit test in the debugger where you can look at the values as it runs.

Here we introduce a failure in our testing method to cause it to fail (use fail method from TestCase class)

failure of a test case in JUnit

 

Example 1 - with BOTH JUnit 4 and 3 test cases

Dog Class - project code

/**
   * 
   */
/**
   * @author grewe
   *
   */
   public class Dog {
   /**
   * represents dog's name
   */
   String Name;
   
   /**
   * represents dog's breed
   */
   String Breed;
   
   /**
   * represents age
   */
   float Age;
 /**
   * constructor sets Name, breed, age
   */
   Dog(String n, String b, float a){
   super();
   this.Name = n;
   this.Breed = b;
   this.Age = a;
   }
   /**
   * @param args
   */
   public static void main(String[] args) {
   // TODO Auto-generated method stub
   Dog d = new Dog("Jack", "pug", (float)3.0);
   System.out.println("Dog is " + d.getInfo());
 }
   
   /**
   * @return Name
   */
   String getName() {
   return this.Name;
   }
   
   /**
   * @param Name
   */
   void setName(String n){
   this.Name = n;
   }
 /**
   * @return Breed
   */
   String getBreed() {
   return this.Breed;
   }
   
   /**
   * @return Dog's info
   */
   String getInfo(){
   String s = "Name: " + this.Name + " \nBreed: " + this.Breed + " \nAge: " + this.Age;
   return s;
   }
 }



DogTest - TestCase class - WITH JUnit 4

Currently ONLY created the method testDog , need to complete the other methods i.e. testGetName to test the Dog's getName mehtod!!!!

import static org.junit.Assert.*;
import org.junit.Test;
/**
   * 
   */
/**
   * @author grewe
   *
   */
   public class DogTest4 {
 /**
   * Test method for {@link Dog#Dog(java.lang.String, java.lang.String, float)}.
   */
   @Test
   public void testDog() {
   Dog d = new Dog("Fido","jack russel", (float)5.0);
   String s = d.getInfo();
   System.out.println("Test Case Results!!!\n\n" + s);
   assertEquals("Fido",d.getName());
   //fail("Not yet implemented");
   }
 /**
   * Test method for {@link Dog#main(java.lang.String[])}.
   */
   @Test
   public void testMain() {
   fail("Not yet implemented");
   }
 /**
   * Test method for {@link Dog#getName()}.
   */
   @Test
   public void testGetName() {
   fail("Not yet implemented");
   }
 /**
   * Test method for {@link Dog#setName(java.lang.String)}.
   */
   @Test
   public void testSetName() {
   fail("Not yet implemented");
   }
 /**
   * Test method for {@link Dog#getBreed()}.
   */
   @Test
   public void testGetBreed() {
   fail("Not yet implemented");
   }
 /**
   * Test method for {@link Dog#getInfo()}.
   */
   @Test
   public void testGetInfo() {
   fail("Not yet implemented");
   }
}
 

DogTest - TestCase class - WITH JUnit 3

Currently ONLY created the method testDog , need to complete the other methods i.e. testGetName to
test the Dog's getName mehtod!!!!
import junit.framework.TestCase;
 
public class DogTest extends TestCase {
 public void testDog() {
   Dog d = new Dog("Fido","jack russel", (float)5.0);
   String s = d.getInfo();
   System.out.println("Test Case Results!!!\n\n" + s);
   assertEquals("Fido",d.getName());
   }
 public void testMain() {
   //fail("Not yet implemented");
   }
 public void testGetName() {
   //fail("Not yet implemented");
   }
 public void testSetName() {
   //fail("Not yet implemented");
   }
 public void testGetBreed() {
   //fail("Not yet implemented");
   }
 public void testGetInfo() {
   //fail("Not yet implemented");
   }
}
 

Example 2 - JUnit 3

Email class --- the project code

import java.util.*;
   /*
   * Emails Class -- unit testing example.
   * Encapsulates some text with email addresses in it.
   * getUsers() returns a list of the usernames from the text.
   */
   public class Emails {
     private String text;
     // Sets up a new Emails obj with the given text
     public Emails(String text) {
        this.text = text;
     }
    
     // Returns a list of the usernames found in the text.
     // We'll say that a username is one or more letters, digits,
     // or dots to the left of a @.
     public List<String> getUsers() {
        int pos = 0;
        List<String> users = new ArrayList<String>();
        while (true) {
           int at = text.indexOf('@', pos);
           if (at == -1) break;
           // Look backwards from at
           int back = at - 1;
           while (back >= 0 &&
                  (Character.isLetterOrDigit(text.charAt(back)) ||
                  text.charAt(back)=='.')) {
              back--;
            }
   
           // Now back is before start of username
           String user = text.substring(back + 1, at);
           if (user.length() > 0) users.add(user);
           // Advance pos for next time
           pos = at + 1;
         }
         return users;
   }


Testing class EmailTest

note- here the test methods have names for Basic, Hard in them to indicate difficulty

  
   import junit.framework.TestCase;
   import java.util.*;
   /*
   EmailsTest -- unit tests for the Emails class.
   */
   public class EmailsTest extends TestCase {
       // Basic use
       public void testUsersBasic() {
         Emails emails = new Emails("foo bart@cs.edu xyz marge@ms.com baz");
         assertEquals(Arrays.asList("bart", "marge"), emails.getUsers() );
         // Note: Arrays.asList(...) is a handy way to make list literal.
         // Also note that .equals() works for collections, so the above works.
        }
   
      // Weird chars -- push on what chars are allowed
      public void testUsersChars() {
         Emails emails = new Emails("fo f.ast@cs.edu bar&a.2.c@ms.com ");
         assertEquals(Arrays.asList("f.ast", "a.2.c"), emails.getUsers());
      }
      
     // Hard cases -- push on unusual, edge cases
     public void testUsersHard() {
        Emails emails = new Emails("x y@cs 3@ @z@");
        assertEquals(Arrays.asList("y", "3", "z"), emails.getUsers());
        // No emails
        emails = new Emails("no emails here!");
        assertEquals(Collections.emptyList(), emails.getUsers());
        // All @, all the time!
        emails = new Emails("@@@");
        assertEquals(Collections.emptyList(), emails.getUsers());
        // Empty string
        emails = new Emails("");
        assertEquals(Collections.emptyList(), emails.getUsers());
       }
   } 



  
 
© Lynne Grewe