Home‎ > ‎Testing‎ > ‎

Widgets & Units


Unit Building

All the things in life that I build rely on one premise, build in units and test those units. One the things that I enjoy about GWT is it's widget system, because it does this job well. So, I'm going to show you the way I like build units here. There are quite a few ways to unitize GWT applications and I won't cover all of them here. 

Decoupled Dependent Widgets

I think GWT excels at building the smallest widget first were compositing them together can formulate more complex widget until you can call it a full blown application. I see a widget being able to stand on its own and that includes unit testing against it. Making building blocks like this is simple, easy, abstract-able and quick to build a sustainable application. 

Does MVP Fit In

Yes. To my understanding, MVP is another way to unitize the application building with the premise its easier for testing. Although, I think it uses far more classes and interfaces to build a unit. I've found I can build a widget with UiBinder and test it just like it were a presenter in MVP. Maybe, building independent widgets is more like Flow Synchronization pattern and less like MVP. Regardless which pattern or road you use, building units and testing those units is critical to building a healthy application. 

I think, In the end, it really doesn't matter unless you build a independent useful component that is testable and useable for an application. 

Testing

GWTTestCase makes it really easy to test your widget or unit. I can even test computed style and all the things mocked up in an ui. The only thing I can't test is event logic. Yet, I can mock some events and assert my expectations for most of the logic, which mitigates most of the challenges I could have with a unit down the road. That which you can't do, will have to be done with something Selenium.

Example

I built a simple basic example. I start with a PersonPresenter and add an email list which adds email items. I built this to explain my point with building a unit a widget and testing that unit a widget.

Some of the example Classes

        EmailList --- EmailListTest
            EmailItem --- EmailItemTest
     

Widget and Its Test Case Example Below

public class EmailItem extends Composite {
 
  interface EmailItemUiBinder extends UiBinder<Widget, EmailItem> {}
 
  private static EmailItemUiBinder uiBinder = GWT.create(EmailItemUiBinder.class);
 
  @UiField
  TextBox tbEmail;
 
  @UiField
  HTML htmlEmail;
  @UiField PushButton bEdit;
 
  private EmailData emailData;
 
  private EmailWidgetsState state;

  public EmailItem() {
    initWidget(uiBinder.createAndBindUi(this));
   
    setState(EmailWidgetsState.VIEW);
  }

  public void setEmailData(EmailData emailData) {
    this.emailData = emailData;
  }
 
  public void draw() {
    drawEmail();
  }
 
  /**
   * set widget state to edit or view
   * @param state
   */
  public void setState(EmailWidgetsState state) {
    this.state = state;
    if (state == EmailWidgetsState.VIEW) {
      displayView();
    } else if (state == EmailWidgetsState.EDIT) {
      displayEdit();
    }
  }
 
  /**
   * change back in forth between states
   */
  public void setState() {
    if (state == EmailWidgetsState.VIEW) {
      setState(EmailWidgetsState.EDIT);
    } else if (state == EmailWidgetsState.EDIT) {
      setState(EmailWidgetsState.VIEW);
    }
  }
 
  public EmailWidgetsState getState() {
    return state;
  }

  private void displayView() {
    tbEmail.setVisible(false);
    htmlEmail.setVisible(true);
  }

  private void displayEdit() {
    tbEmail.setVisible(true);
    htmlEmail.setVisible(false);
  }

  private void drawEmail() {
    String s = "";
    if (emailData != null && emailData.getEmail() != null) {
      s = emailData.getEmail();
    }
    drawEmailTextBox(s);
    drawEmailHtml(s);
  }
 
  private void drawEmailTextBox(String value) {
    tbEmail.setValue(value);
  }

  private void drawEmailHtml(String value) {
    SafeHtml html = SimpleHtmlSanitizer.sanitizeHtml(value);
    htmlEmail.setHTML(html);
  }

  @UiHandler("tbEmail")
  void onTbEmailChange(ChangeEvent event) {
    String value = tbEmail.getValue();
    drawEmailHtml(value);
  }

  public EmailData getEmailData() {
    return emailData;
  }
 
  public boolean isEmailHtmlVisible() {
    return htmlEmail.isVisible();
  }
 
  public boolean isEmailTextBoxVisible() {
    return tbEmail.isVisible();
  }
 
  @UiHandler("bEdit")
  void onBEditClick(ClickEvent event) {
    setState();
  }
}

Lets Apply Testing to that item:

public class EmailItemTest extends GWTTestCase {

  @Override
  public String getModuleName() {
    return "org.gonevertical.unittesting.DemoUnitTesting";
  }
 
  public void testWorks() {
    assertEquals(true, true);
  }

  public void testSetEmailData() {
    EmailData left = new EmailData();
    left.setEmail("test@g.com");
   
    EmailItem widget = new EmailItem();
    RootPanel.get().add(widget);
   
    widget.setEmailData(left);
    widget.getEmailData();
    EmailData right = widget.getEmailData();
    assertEquals(left.getEmail(), right.getEmail());
  }
 
  public void testDrawState() {
    EmailItem widget = new EmailItem();
    RootPanel.get().add(widget);
   
    EmailWidgetsState right = widget.getState();
    assertEquals(EmailWidgetsState.VIEW, right);
   
    widget.setState();
    assertEquals(EmailWidgetsState.EDIT, widget.getState());
    widget.setState();
    assertEquals(EmailWidgetsState.VIEW, widget.getState());
    widget.setState();
    assertEquals(EmailWidgetsState.EDIT, widget.getState());
  }
 
  public void testDrawView() {
    EmailData left = new EmailData();
    left.setEmail("test@g.com");
   
    EmailItem widget = new EmailItem();
    RootPanel.get().add(widget);

    widget.draw();
   
    assertEquals(true, widget.isEmailHtmlVisible());
    assertEquals(false, widget.isEmailTextBoxVisible());
  }
 
  public void testDrawEdit() {
    EmailData left = new EmailData();
    left.setEmail("test@g.com");
   
    EmailItem widget = new EmailItem();
    RootPanel.get().add(widget);

    widget.setState(EmailWidgetsState.EDIT);
    widget.draw();
   
    assertEquals(false, widget.isEmailHtmlVisible());
    assertEquals(true, widget.isEmailTextBoxVisible());
  }
 
}





Comments