LIFT

LIFT was written to make GUI Unit Testing quick and easy. It was written with introductory programming students in mind, but can be used by anyone using Java and Swing to create graphical user interfaces. LIFT does three main things for the programmer:

  • Provides a simple, type safe way to retrieve GUI object references.

  • Provides a simple means of simulating mouse and keyboard interactions.

  • Transparently deals with thread synchronization issues inherent to GUI programming.

Lift is compatible with with both JUnit 3 and JUnit 4 style tests. For JUnit 4 style tests, JUnit 4.8.2 or later is required. The latest JUnit is available at the JUnit website.

For more information, see the following:

In general, testing GUIs using LIFT is a three step process:

  1. Retrieve references to any components needed for the test using getComponent().

  2. Simulate user activity by using LIFT methods (click(component), keyString(component, string), etc)

  3. Make assertions about the program state to ensure that it behaved as expected.

A Simple Example

Suppose you have a program that lets the user enter a fahrenheit temperature and displays the equivalent celsius temperature after clicking a "Convert" button. Here is how you would write a test case for such a program using LIFT:

public void testTempConverter()
{
    // This test will use the text field the user enters the temperature into.
    // There is only one text field in the program so the type is all we need
    // to pass into getComponent()
    JTextField entryField = getComponent(JTextField.class);

    // We also need the label that will store the result.
    // There are 2 labels in program so we look for the one that starts with the value 0.
    JLabel result = getComponent(JLabel.class, where.textIs("0.0"));

    // Lastly we'll need a reference to the convert button so we can click it.
    // Like the entry field, there is only one button so we only need to specify the type.
    JButton convertButton = getComponent(JButton.class);

    // For the actual test we will convert 212 degrees fahrenheit.
    // Use a LIFT method to enter the value into the text field.
    keyString(entryField, "212");
    // Use a LIFT method to click on the button.
    click(convertButton);

    // Make sure the result label was updated to 100.0.
    assertEquals("Conversion incorrect", "100.0", result.getText());
} 

In this test, the first few lines retrieve the components needed for the test. LIFT methods are then used to simulate a user entering the value 212 and clicking on the convert button. Finally, the result label is inspected to make sure it updated with the correct value. Because the entry field and the button were the only components of those types in the program, getComponent() only needed to know the type to retrieve them. For components that are not the only instance of a particular type of component, more specificity is needed, such as when retrieving the result label in the above example. In this case, we use the textIs() filter to look for a JLabel with the specified text. Components can also be identified using other attributes such as name, location, size, parent (in the UI hierarchy), or status (enabled, focus). These attributes can then be combined using boolean operators to be even more specific.

For example, the following call to getComponent() would return a disabled "Next" button:

getComponent(JButton.class, where.textIs("Next").and.enabledIs(false))

In practice, we found that the easiest way for students to test their GUIs was to use the setName() method to give a unique name to any components they knew they would need to reference in a test. Then in their tests they can use the nameIs() filter to quickly retrieve a reference to the component. This technique ended up being so useful we added an overloaded version of getComponent() to take advantage of this. If a student declares a component like this in their implementation:

JButton cancel = new JButton("Cancel");
cancel.setName("cancelButton"); 

Then they can then retrieve the component like this in a test:

JButton c = getComponent(JButton.class, "cancelButton");

The full source for this example: Application Test Class JUnit 4 Test Class.

Testing with other Graphics Libraries

LIFT started out as a testing framework for the objectdraw teaching library. It was then adapted for the ACM Java Task Force library, before finally being adapted for use with any Swing application. Legacy support for both objectdraw and ACM JTF remains however, and may be useful in the classroom.

Objectdraw Example

This example shows how to create and test a simple program using objectdraw and LIFT.

public void begin()
{
    // create two rectangles
    r = new FilledRect(20, 20, 20, 20, canvas);     
    r.setColor(Color.red);
    r2 = new FilledRect(60, 60, 40, 40, canvas);
    r2.setColor(Color.blue);
}

// a portion of the code to control dragging one of the boxes
public void onMouseDrag( Location point )
{
    if (dragging)
    {
        r.moveTo(point);
    }
} 

...

// And some tests
public void testExample()
{
    // Finding an rectangle based on its color
    FilledRect r = getDrawable(FilledRect.class, where.colorIs(Color.red));
    assertTrue(r.getHeight() == 20);

    // Drag one of the boxes
    ode.onMousePress(new Location(25, 25));
    ode.onMouseDrag(new Location(60, 60));
    ode.onMouseRelease(new Location(70, 70));            

    // Make sure it moved correctly
    assertTrue(r.getLocation().equals(new Location(70, 70)));
} 

The full source for this example: Application Test Class JUnit 4 Test Class.

ACM JTF Example

The same example, now written using ACM JTF.

public void run()
{
    // Create and add two GRects
    r1 = new GRect(20, 20, 20, 20);
    r1.setColor(Color.red);
    add(r1);
    r2 = new GRect(60, 60, 40, 40);
    r2.setColor(Color.blue);
    add(r2);
}

// a portion of the code to control dragging one of the boxes
public void mousePressed(GPoint p)
{
    if (r1.contains(p))
    {
        dragging = true;
    }
}

... 

// And some tests 
public void testExample()
{
    // Finding an object based on its color
    GRect r = getGObject(GRect.class, where.colorIs(Color.red));
    assertTrue(r.getHeight() == 20);

    // Find an object based on its location
    GRect r2 = getGObject(GRect.class, where.locationIs(60, 60));
    assertTrue(r2.getColor() == Color.blue);

    // Drag one of the boxes
    jtfe.mousePressed(new GPoint(25, 25));
    jtfe.mouseDragged(new GPoint(60, 60));
    jtfe.mouseReleased(new GPoint(70, 70));

    // Make sure it moved correctly
    assertTrue(r.getLocation().equals(new GPoint(70, 70)));
}

The full source for this example: Application Test Class JUnit 4 Test Class.

Downloading the Library

LIFT is included as part of the "Student Library", a jar file available from our SourceforgeProject:

http://sourceforge.net/projects/web-cat/files/Student%20Library/

LIFT (and the whole student library) is available for use under the terms of the LGPL v3.

The javadoc for the student library is available at http://courses.cs.vt.edu/~cs1114/api.

Syndicate content

There are no visible status updates.