Test UI with simple JUnit Test

Contains useful source code for specific use cases.

Test UI with simple JUnit Test

Postby Development@SIB » Wed Aug 17, 2016 2:51 pm

Sometimes you want a JUnit test case for a specific UI feature. If you need an application frame for your test, you could use following implementation:

A simple Test Launcher:

Syntax: [ Download ] [ Hide ]
/*
 * Copyright 2016 SIB Visions GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 *
 * History
 *
 * 11.08.2016 - [JR] - creation
 */

package javax.rad.application;

import javax.rad.ui.IComponent;
import javax.rad.ui.container.IDesktopPanel;
import javax.rad.util.IRunnable;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;

import com.sibvisions.rad.application.Application;
import com.sibvisions.rad.ui.swing.impl.SwingApplication;

/**
 * The <code>SimpleTestLauncher</code> starts a {@link SwingApplication} and shows
 * a specific content in the application pane.
 *
 * @author René Jahn
 */

public class SimpleTestLauncher
{
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Initialization
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   
    /**
     * Creates a new instance of <code>SimpleTestLauncher</code>.
     *
     * @param pComponent the component to show
     */

    public SimpleTestLauncher(final IComponent pComponent)
    {
        final SwingApplication app = new SwingApplication();
       
        app.startup(SimpleTestApplication.class.getName(), null, null);
        app.setSystemExitOnDispose(false);
        app.eventWindowClosed().addListener(new IRunnable()
        {
            public void run()
            {
                synchronized (SimpleTestLauncher.this)
                {
                    SimpleTestLauncher.this.notify();
                }
            }
        });
       
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                IDesktopPanel desktop = ((Application)app.getApplication()).getDesktopPane();
                desktop.removeAll();
                desktop.add(pComponent);
               
                //because test was created before LaF was set!
                SwingUtilities.updateComponentTreeUI((JComponent)pComponent.getResource());
            }
        });
       
        synchronized(this)
        {
            try
            {
                wait();
            }
            catch (InterruptedException ie)
            {
                //ignore
            }
        }
    }

}   // SimpleTestLauncher

This class wrapps application creation, because we need to set the UI component after the application was started!

The second class is our Application:

Syntax: [ Download ] [ Hide ]
/*
 * Copyright 2016 SIB Visions GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 *
 * History
 *
 * 11.08.2016 - [JR] - creation
 */

package javax.rad.application;

import javax.rad.application.genui.UILauncher;
import javax.rad.remote.IConnection;

import com.sibvisions.rad.application.Application;

/**
 * The <code>SimpleTestApplication</code> is an always connected application
 * implementation, for test cases.
 *
 * @author René Jahn
 */

public class SimpleTestApplication extends Application
{
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Initialization
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Creates a new instance of <code>SimpleTestApplication</code>.
     *
     * @param pLauncher the launcher
     */

    public SimpleTestApplication(UILauncher pLauncher)
    {
        super(pLauncher);
    }
   
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Overwritten methods
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @Override
    protected String getApplicationName()
    {
        return "Test Application";
    }

    @Override
    protected IConnection createConnection() throws Exception
    {
        return null;
    }
   
    @Override
    public void notifyVisible()
    {
    }
   
    @Override
    protected void afterLogin()
    {
    }

}   // SimpleTestApplication

The application removes login screen and you can use it without manual tasks.

Finally, our JUnit test case:

Syntax: [ Download ] [ Hide ]
/*
 * Copyright 2016 SIB Visions GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 *
 *
 * History
 *
 * 11.08.2016 - [JR] - creation
 */

package com.sibvisions.forum;

import javax.rad.application.SimpleTestLauncher;
import javax.rad.genui.UIFactoryManager;
import javax.rad.genui.container.UIPanel;
import javax.rad.genui.layout.UIBorderLayout;
import javax.rad.model.reference.ReferenceDefinition;

import org.junit.BeforeClass;
import org.junit.Test;

import com.sibvisions.apps.components.NavigationTable;
import com.sibvisions.rad.persist.StorageDataBook;
import com.sibvisions.rad.persist.jdbc.DBAccess;
import com.sibvisions.rad.persist.jdbc.DBStorage;
import com.sibvisions.rad.ui.swing.impl.SwingFactory;

public class TestActivity extends UIPanel
{
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Initialization
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Initializes the unit test.
     *
     * @throws Exception if initialization fails
     */

    @BeforeClass
    public static void beforeClass()
    {
        UIFactoryManager.getFactoryInstance(SwingFactory.class);
    }
   
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Test methods
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Tests application start with a custom UI.
     *
     * @throws Exception if app start fails
     */

    @Test
    public void testStartApplication() throws Exception
    {
        DBAccess dba = DBAccess.getDBAccess("jdbc:oracle:thin:@localhost:1521:XE",
                                            "username", "password");
        dba.open();
       
        DBStorage dbsContract = new DBStorage();
        dbsContract.setWritebackTable("CONTRACT");
        dbsContract.setDBAccess(dba);
        dbsContract.open();
       
        DBStorage dbsActivity = new DBStorage();
        dbsActivity.setWritebackTable("ACTIVITY");
        dbsActivity.setDBAccess(dba);
        dbsActivity.open();
       
        StorageDataBook sdbContract = new StorageDataBook(dbsContract);
        sdbContract.open();
        sdbContract.fetchAll();
        sdbContract.setSelectedRow(0);
       
        StorageDataBook sdbActivity = new StorageDataBook(sdbContract, dbsActivity);
        sdbActivity.setMasterReference(new ReferenceDefinition(new String[] {"CONT_ID"},
                                       sdbContract,
                                       new String[] {"ID"}));
        sdbActivity.open();
       
        setLayout(new UIBorderLayout());
       
        NavigationTable nav = new NavigationTable();
        nav.setDataBook(sdbActivity);
       
        add(nav);
       
        new SimpleTestLauncher(this);
    }

}   // TestActivity

The result:

testapp.png
testapp.png (34.92 KiB) Viewed 615 times


The database model (Oracle):

contract_activity.png
contract_activity.png (33.89 KiB) Viewed 600 times


The database objects (Oracle):

Syntax: [ Download ] [ Hide ]
CREATE TABLE CONTRACT
(
  id    NUMBER(16) NOT NULL,
  title VARCHAR2(1000),
  state NUMBER(1)
)
;
comment ON COLUMN CONTRACT.id
  IS 'PK';
comment ON COLUMN CONTRACT.title
  IS 'Contract title';
comment ON COLUMN CONTRACT.state
  IS 'Contract state';
ALTER TABLE CONTRACT
  ADD constraint CONT_PK PRIMARY KEY (ID);

CREATE TABLE ACTIVITY
(
  id                  NUMBER(16) NOT NULL,
  cont_id             NUMBER(16),
  name                VARCHAR2(1000),
  cost                NUMBER(10,2),
  valid_from          DATE,
  valid_to            DATE,
  responsible_user_id NUMBER(16),
  validated           CHAR(1) DEFAULT 'Y'
)
;
comment ON COLUMN ACTIVITY.id
  IS 'PK';
comment ON COLUMN ACTIVITY.cont_id
  IS 'Contract FK';
comment ON COLUMN ACTIVITY.name
  IS 'Activity name';
comment ON COLUMN ACTIVITY.cost
  IS 'Activity costs';
comment ON COLUMN ACTIVITY.valid_from
  IS 'Valid from';
comment ON COLUMN ACTIVITY.valid_to
  IS 'Valid to';
comment ON COLUMN ACTIVITY.responsible_user_id
  IS 'Responsible User FK';
comment ON COLUMN ACTIVITY.validated
  IS 'Whether the activity is valid';
ALTER TABLE ACTIVITY
  ADD constraint ACTI_PK PRIMARY KEY (ID);
ALTER TABLE ACTIVITY
  ADD constraint ACTI_CONT_FK FOREIGN KEY (CONT_ID)
  REFERENCES CONTRACT (ID);
ALTER TABLE ACTIVITY
  ADD constraint ACTI_RESP_USER_FK FOREIGN KEY (RESPONSIBLE_USER_ID)
  REFERENCES USERS (ID);


CREATE OR REPLACE TRIGGER TR_ACTIVITY_BR_IU
  before INSERT OR UPDATE ON activity  
  FOR each row
begin

  IF (:new.validated = 'N') then
   
    IF (:new.valid_from IS NULL) then
      raise_application_error(-20000, 'Valid from can''t be null!');
    end IF;
 
  end IF;
 
end TR_ACTIVITY_BR_IU;
/

CREATE OR REPLACE TRIGGER TR_CONTRACT_BR_IU
  before INSERT OR UPDATE ON contract  
  FOR each row
begin

  IF (:new.state = 4) then
     
    UPDATE activity
       SET validated = 'N'
     WHERE cont_id = id
       AND validated = 'Y';
       
  end IF;    
 
end TR_CONTRACT_BR_IU;
/


ALTER TABLE CONTRACT disable ALL triggers;
ALTER TABLE ACTIVITY disable ALL triggers;
ALTER TABLE ACTIVITY disable constraint ACTI_CONT_FK;
ALTER TABLE ACTIVITY disable constraint ACTI_RESP_USER_FK;
INSERT INTO CONTRACT (id, title, state)
VALUES (1, 'Air', 1);
commit;
INSERT INTO ACTIVITY (id, cont_id, name, cost, valid_from, valid_to, responsible_user_id, validated)
VALUES (1, 1, 'Part 1', .2, NULL, NULL, NULL, 'Y');
commit;
ALTER TABLE ACTIVITY enable constraint ACTI_CONT_FK;
ALTER TABLE ACTIVITY enable constraint ACTI_RESP_USER_FK;
ALTER TABLE CONTRACT enable ALL triggers;
ALTER TABLE ACTIVITY enable ALL triggers;
User avatar
Development@SIB
 
Posts: 311
Joined: Mon Sep 28, 2009 1:54 pm

Return to Code snippets