Refresh Pack 6.0.2.0 added some new plugins to the Eclipse-based WebSphere MQ Explorer. One of these is the “Tests plug-in”. The idea of the Tests plugin is to use the Eclipse ‘Problems View’ to display feedback about your WMQ configuration.

The “Tests plug-in” can itself be extended with user-written tests. This allows you to customize the WMQ Explorer so that it displays messages in response to any situation that you are interested in.

In this post, I’ll give a bit of background to the Tests plug-in, and walkthrough the steps involved in adding a new Test to the WMQ Explorer.

Background

The “Tests plug-in” began life as Healthcheck – a SupportPac that I wrote a couple of years ago. As a fairly new addition to WebSphere MQ, my aim was to get Explorer to check for all of the sorts of configuration mistakes that I made when I started.

Healthcheck proved quite popular, so it was adopted by the Explorer Development team who ‘productised’ it for inclusion with the main product. And they did a great job – the interface in the Tests plug-in is a big improvement on my original approach.

One of the things that I spent some time on with the original was keeping the interface open, and providing extension points so that users could add their own tests to WMQ Explorer. But it was apparently more tricky to add new Tests than I thought, and in the first few months after the release of the SupportPac, I received several emails asking for more information about this. As a result, I wrote a guide which got published in developerWorks: “Writing Java tests for your WebSphere MQ environment to use in MQ Explorer”. However, the changes to Tests plug-in as a part of the productising means that the information in the article needs updating.

This post is an updated version of the original developerWorks article, updated to reflect the structure of the new Tests plug-in.


Introduction

This post shows you how to write a plug-in to perform checks on a WebSphere MQ environment, using as an example a plug-in that verifies that all objects conform to a corporate naming standard.

The plug-in will be written using a combination of Java and XML, and will implement checks that can be launched from the WebSphere MQ Explorer GUI. Results will be displayed in the Eclipse Problems View, from where they can categorised as Errors, Warnings, or Information.

WebSphere MQ Healthcheck
WebSphere MQ Explorer GUI, showing the usage of the Problems View to display results of tests and checks

Prerequisites

This post assumes that you have WebSphere MQ Explorer installed on either Linux or Windows. It also assumes that you want to use the Eclipse workbench provided with WebSphere MQ Explorer. By default, the full workbench functionality of the Eclipse platform is disabled by WebSphere MQ Explorer. To enable the workbench, select Windows => Preferences => WebSphere MQ Explorer, select Startup in an Eclipse workbench, and then restart WebSphere MQ Explorer.

WebSphere MQ Explorer Preferences dialog, showing the setting to run the full Eclipse workbench

WebSphere MQ Explorer Preferences dialog, showing the setting to run the full Eclipse workbench

Using the WebSphere MQ Explorer Tests plug-in to implement this check reduces the development effort that would otherwise be required to produce such a Test. Benefits include:

  • Integration with the WebSphere MQ Explorer and Eclipse GUI — GUI controls to run your new check are automatically included within the GUI; results found by your check are displayed in the Problems View and managed for you; any documentation you provide is displayed and launched as appropriate; and so on.
  • Basic threading model — You can run your new check in the background while using the WebSphere MQ Explorer GUI, and in parallel with other tests, without considering threading implications in your code

All that you need to do yourself is code the logic to check for problems, and describe how any potential issues that you find should be phrased.

Preparing the plug-in development environment

Eclipse Plug-in Development perspective

WebSphere MQ Explorer comes with the Eclipse Java IDE, which can be used to develop plug-ins. To switch to the Eclipse Plug-in Development Environment (PDE), select Window => Open Perspective => Other. The PDE gives you an overview of your development environment, an editor in which to edit Java and XML files, and a number of other useful views. For more information about the PDE, see eclipse.org.

Creating a new project

Create a new Plug-in Project for your code. Right-click in the Package Explorer by the newly added projects, and select New => Plug-in Project. For the purposes of this example, name the new project com.wordpress.hursleyonwmq.healthcheck

Once created, open the automatically-generated plugin.xml for your new plug-in. Use the Dependencies tab to add the following plug-ins as dependencies for the new plug-in. These are a combination of some of the core Eclipse GUI plug-ins, and some of the projects used by WebSphere MQ:

  • org.eclipse.ui
  • org.eclipse.core.runtime
  • com.ibm.mq.explorer.ui
  • com.ibm.mq.explorer.tests
  • org.eclipse.core.resources
  • com.ibm.mq.runtime
  • com.ibm.mq.internal.pcf

Dependencies in the plugin.xml

Creating a new test

Each test needs:

  1. An entry in the plug-in’s XML to provide the WebSphere MQ Explorer GUI with information to display for the test
  2. A Java class that carries out the test

Define a new test in XML

Test category

Open the plugin.xml for your plug-in. Use the Extensions tab to add the com.ibm.mq.explorer.tests.TestCategorys to your project.

Right-click on the TestCategorys extension, and add a new Category entry that will define your test category:


New extension in plugin.xml

With the category item selected, enter the following information:

  • id — a unique identifier for this category of tests
  • name — a user-friendly name to display in the GUI when representing this category of checks
  • description — a short description of the category to display in the GUI

plugin.xml extension
plugin.xml extension

Test Set

Right-click on the Category extension created previously, and add a new testset entry:
Test set extension
plugin.xml extension

With the test set item selected, enter the following information:

  • id — a unique identifier for this test set
  • name — a user-friendly name to display in the GUI when representing this set of tests
  • description — a short description of the test set to display in the GUI

plugin.xml extension
plugin.xml extension

Test

A new test extension can now be added for each check you want to write. This can be done in a similar way to adding Test Categories:

Adding a new test

With the test item selected, enter the following information:

  • name — a user-friendly name to display in the GUI when representing this check
  • class — the fully-qualified name of the Java class you will write in the next step
  • id — a unique identifier for this test (for example, the fully-qualified name of the Java class entered above)
  • description — a short description of the test to display in the GUI
  • testset — the id of the test category created previously
  • testsubset — the id of the test set created previously
  • furtherinfo — the location of an HTML page with more detailed information about this test and the results that it created. The GUI can display additional documentation to explain the results that they return, and provide guidance on what should be done to resolve the problem. Documentation should be provided in HTML, and can be identified as either:
    • internal to the plug-in — Stored in the plug-in project providing the test itself. The location should be defined in the XML relative to the plugin.xml file itself; for example, doc/TestDoc.html.
    • external to the plug-in — Stored on a Web server, allowing maintenance of the documentation separately from the test itself. Specify the location using a complete URL beginning with http://.

For example, enter the following to define a test that will verify naming conventions for your MQ environment:
Adding a new test

Click on the plugin.xml tab and look at the XML source. It should look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin
   id="com.wordpress.hursleyonwmq.healthcheck"
   name="Hursley Blog Tests Plug-in"
   version="1.0.0"
   provider-name="Dale Lane"
   class="com.wordpress.hursleyonwmq.healthcheck.HealthcheckPlugin">

   <runtime>
      <library name="hursleyblogtests.jar">
         <export name="*"/>
      </library>
   </runtime>

   <requires>
      <import plugin="org.eclipse.ui"/>
      <import plugin="org.eclipse.core.runtime"/>
      <import plugin="com.ibm.mq.explorer.ui"/>
      <import plugin="com.ibm.mq.explorer.tests"/>
      <import plugin="org.eclipse.core.resources"/>
      <import plugin="com.ibm.mq.runtime"/>
      <import plugin="com.ibm.mq.internal.pcf"/>
   </requires>
   <extension
         point="com.ibm.mq.explorer.tests.TestCategorys">
      <Category
            description="Example test category for Dale's blog post"
            name="Dale's Test Category"
            id="com.wordpress.hursleyonwmq.healthcheck.Category1">
         <testset
               description="This will appear beneath the category"
               name="My First Test Set"
               id="com.wordpress.hursleyonwmq.healthcheck.testset1"/>
      </Category>
   </extension>
   <extension
         point="com.ibm.mq.explorer.tests.Tests">
      <test
            testsubset="com.wordpress.hursleyonwmq.healthcheck.testset1"
            class="com.wordpress.hursleyonwmq.healthcheck.NamingConventionTest"
            description="Test that checks queue names against a set of naming conventions"
            testset="com.wordpress.hursleyonwmq.healthcheck.Category1"
            name="Naming conventions"
            id="com.wordpress.hursleyonwmq.healthcheck.naming"/>
   </extension>
</plugin>

The test XML is an interface defined in the Healthcheck plug-in, which enables the Tests plug-in to correctly find and load tests from multiple plug-ins. For more information about plug-in architecture, see this Eclipse article.

Prepare the new test in Java

Create a new Java class from the Package Explorer, being sure to give it a name and package that is consistent with the location identified in the class attribute of the XML defined previously. The class should extend com.ibm.mq.explorer.tests.WMQTest.

The Problems View will continue to display any existing WebSphere MQ Tests plug-in problems, alongside problems with your Java source. You can filter these out using the Problems View filter.

For the moment, do the minimum to get your Java class to compile, which is to create an empty class.

package com.wordpress.hursleyonwmq.healthcheck;

import com.ibm.mq.explorer.tests.WMQTest;

/**
 * Empty test class - enough to compile.
 *
 * @author Dale Lane
 */
public class NamingConventionTest extends WMQTest {

}

We will return to the detailed implementation shortly.

Prepare the documentation for the new test

Write the documentation that you want displayed in the GUI with the test. The documentation should be written in HTML and saved at the location specified in the plugin.xml file. As described previously, this could be local (inside this plugin, such as in a doc folder) or remote (on a Web server).

Deploy the test

From the Package Explorer, right-click on your project and select Export. Click Deployable plug-ins and fragments. In the Export dialog that opens, click Deploy as a directory structure and set the destination directory to the location of the WebSphere MQ Explorer installation. The default installation locations are C:\\Program Files\\IBM\\WebSphere MQ\\eclipse on Windows and /opt/mqm/eclipse/plugins/ on Linux.

Restart Eclipse. After reopening, return to the WebSphere MQ Explorer perspective using the Windows menu. Your new test should appear in the Tests configuration list, as specified in the plugin.xml.

If you included HTML documentation, it is important that the HTML files are included in the build of your plug-in. Add your HTML files to the build list by opening the build.properties file and selecting your documentation in the Binary Build list:

Build configuration

Once you have confirmed that the structure of your plug-in is working correctly, return to the PDE to provide the implementation for your test.

After any change to the Java code, you must repeat the previous deploy step to retest. Alternatively, during development, you can launch a test instance of Eclipse using Run As => Run-time Workbench, which lets you make and test changes without closing your development environment. You can then carry out the deploy step outlined above after your changes are complete.

Implement the new test in Java

Initial attempt

We will build up our test gradually, annotating the example source code with more detailed explanatory notes below. Our first attempt returns static data, and demonstrates the basic elements of the WMQTest interface:

package com.wordpress.hursleyonwmq.healthcheck;

import java.util.ArrayList;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;

import com.ibm.mq.explorer.tests.WMQTest;
import com.ibm.mq.explorer.tests.internal.actions.WMQTestEngine;
import com.ibm.mq.explorer.tests.internal.objects.WMQTestResult;
import com.ibm.mq.explorer.ui.extensions.MQExtObject;
import com.ibm.mq.explorer.ui.extensions.TreeNode;

/**
 * A sample skeleton implementation of a test.
 * 
 * @author Dale Lane
 */
public class NamingConventionTest extends WMQTest {

    // notice that no constructor is required

    /**
     * Starts the test.
     * 
     * @param callback
     *            handle to the test engine running the test
     * @param guimonitor
     *            a handle to the object monitoring the test, provided to allow
     *            the test to periodically check if the user has tried to cancel
     *            the test running and provide additional user feedback
     * @param contextObjects
     *            context MQExtObjects passed to the test engine
     * @param treenode
     *            the treenodeid used to launch the tests
     */
    public void runTest(WMQTestEngine callback, IProgressMonitor guimonitor,
            MQExtObject[] contextObjects, TreeNode treenode) {

        // Start with the default implementation. this will store a handle
        // to the test engine that will be needed when we want to submit
        // any results at the end of the test
        super.runTest(callback, guimonitor, contextObjects, treenode);

        // initialise the progress bar part of the GUI (10 stages)
        String myName = getTestName();
        guimonitor.beginTask(myName, 10);

        // prepare space to store any results we might want to return
        ArrayList testResults = new ArrayList();

        // generate nine meaningless test results
        for (int i = 0; i < 9; i++) {

            // if the test has been cancelled, we break out of the
            //      for loop to return asap
            if (isCancelled())
                break;

            try {
                // wait here for two seconds to simulate lengthy test processing
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // unexpected exception
                Status internal_error = new Status(IStatus.ERROR,
                                                   "com.wordpress.hursleyonwmq.healthcheck", 0,
                                                   "Unexpected exception encountered while "
                                                   + "waiting for test to return", e);
                HealthcheckPlugin.getDefault().getLog().log(internal_error);
            }

            // create a fake result and add it to the list
            WMQTestResult nxtResult = new WMQTestResult(IMarker.SEVERITY_INFO,
                                                        "Blah blah result " + i + " here", 
                                                        "MyObjectName",
                                                        getTestSubCategory());
            testResults.add(nxtResult);

            // increment progress monitor
            guimonitor.worked(1);
        }

        // return any results that this test has generated
        WMQTestResult[] finalresults = 
            (WMQTestResult[]) testResults.toArray(new WMQTestResult[testResults.size()]);
        testComplete(finalresults);

        // complete progress monitor
        guimonitor.done();
    }
}

Try using this example code to modify your own test object, and redeploy it to test. You should be able to run your test, and see the fake results it generates displayed in the Eclipse Problems View.

You can run the test by choosing it from the Run Tests dialog:

Run Tests
Run Tests dialog

WMQ-aware attempt

We will now add WebSphere MQ-specific code to the test object, allowing it to verify the names of queue objects.

This article is not intended as a tutorial for writing WebSphere MQ applications in Java. For more information about the Java API, see the manual Using Java. It can show you how to modify this example to access objects other than queues, and attributes other than the object names. However, the basic approach to writing code that integrates with the Explorer GUI remains the same.

Here is the test updated to make checks on queue names:

package com.wordpress.hursleyonwmq.healthcheck;

import java.io.IOException;
import java.util.ArrayList;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;

import com.ibm.mq.MQException;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.explorer.tests.PreferenceStoreManager;
import com.ibm.mq.explorer.tests.WMQTest;
import com.ibm.mq.explorer.tests.internal.actions.WMQTestEngine;
import com.ibm.mq.explorer.tests.internal.objects.WMQTestResult;
import com.ibm.mq.explorer.ui.extensions.MQExtObject;
import com.ibm.mq.explorer.ui.extensions.MQQmgrExtObject;
import com.ibm.mq.explorer.ui.extensions.TreeNode;
import com.ibm.mq.pcf.CMQC;
import com.ibm.mq.pcf.CMQCFC;
import com.ibm.mq.pcf.PCFMessage;
import com.ibm.mq.pcf.PCFMessageAgent;

/**
 * A sample test used to check Queue Names against naming conventions. Queue
 * names are checked if they begin with any of a set range of prefixes, defined
 * in this class. Any names which do not start with one of the prefixes are
 * output in an error.
 * 
 * @author Dale Lane
 */
public class NamingConventionTest extends WMQTest {

    /**
     * Maintain a count of how many queue managers we are waiting for replies
     * from.
     */
    private static int numberOfQmgrs = 0;

    /** Stores the accepted queue name prefixes. */
    private static final String[] ACCEPTED_Q_PREFIXES = { "SALES_",
                                                          "MARKETING_", 
                                                          "SHIPPING_", 
                                                          "INCOMING_", 
                                                          "OUTGOING_" };

    /** Stores the user preference for whether system queues should be included. */
    boolean includeSystemObjs = false;

    /**
     * Starts the test.
     * 
     * @param callback
     *            handle to the test engine running the test
     * @param guimonitor
     *            a handle to the object monitoring the test, provided to allow
     *            the test to periodically check if the user has tried to cancel
     *            the test running and provide additional user feedback
     * @param contextObjects
     *            context MQExtObjects passed to the test engine
     * @param treenode
     *            the treenodeid used to launch the tests
     */
    public void runTest(WMQTestEngine callback, 
                        IProgressMonitor guimonitor,
                        MQExtObject[] contextObjects, 
                        TreeNode treenode) {

        // start with the default implementation. this will store a handle
        //  to the test engine that will be needed when we want to submit
        //  any results at the end of the test
        super.runTest(callback, guimonitor, contextObjects, treenode);

        // prepare space to store any results we might want to return
        ArrayList testResults = new ArrayList();

        // get from Preferences whether we should include system queues
        includeSystemObjs = PreferenceStoreManager.getIncludeSysObjsPreference();

        // get a list of queue managers from the Explorer
        ArrayList allQmgrs = new ArrayList();

        for (int k = 0; k < contextObjects.length; k++) {
            if (contextObjects[k] instanceof MQQmgrExtObject) {
                // Object is a queue manager, add to list
                allQmgrs.add(contextObjects[k]);
            }
        }

        // how many queue managers are there?
        numberOfQmgrs = allQmgrs.size();

        // use the number of queue managers as a guide to track progress
        guimonitor.beginTask(getTestName(), numberOfQmgrs);

        // for each queue manager, submit a query
        for (int i = 0; i < numberOfQmgrs; i++) {

            // get next queue manager
            MQQmgrExtObject nextQueueManager = (MQQmgrExtObject) allQmgrs.get(i);

            // only submit queries to connected queue managers
            if (nextQueueManager.isConnected()) {

                // get the name of the queue manager, for use in GUI
                String qmgrName = nextQueueManager.getName();

                // get a handle to a Java object representing the queue manager
                MQQueueManager qmgr = nextQueueManager.getMQQueueManager();

                try {
                    // get a PCF message agent to handle sending PCF inquiry to
                    PCFMessageAgent agent = new PCFMessageAgent(qmgr);

                    // use PCF to submit an 'inquire queue names' query
                    PCFMessage response = submitQueueNamesQuery(qmgrName, agent);

                    // did we get a response to the query?
                    if (response != null) {
                        // get the queue names out of the reply
                        String[] qnames = (String[]) response
                                .getParameterValue(CMQCFC.MQCACF_Q_NAMES);

                        // check each name
                        for (int j = 0; j < qnames.length; j++) {
                            boolean qnameOkay = checkQueueName(qnames[j]);

                            if (!qnameOkay) {
                                // if a problem was found with the name, we
                                // generate an error message, and add it to 
                                // the collection to be returned
                                testResults.add(generateTestResult(qnames[j],
                                                                   qmgrName));
                            }
                        }
                    }
                } 
                catch (MQException e) {
                    // record error details
                    Status internal_error = new Status(IStatus.ERROR,
                                                       "com.wordpress.hursleyonwmq.healthcheck",
                                                       0,
                                                       "Error encountered while getting PCFMessageAgent to "
                                                       + qmgrName,
                                                       e);
                    HealthcheckPlugin.getDefault().getLog().log(internal_error);
                }
            }

            // finished examining a queue manager
            guimonitor.worked(1);
        }

        // return any results that this test has generated
        WMQTestResult[] finalresults = (WMQTestResult[]) testResults
                .toArray(new WMQTestResult[testResults.size()]);
        testComplete(finalresults);
    }
 
    /**
     * Used internally to submit a INQUIRE_Q_NAMES query using PCF to the given
     * queue manager.
     * 
     * @param qmgrName
     *            name of the queue manager to submit the query to
     * @param agent
     * @return the PCF response from the queue manger
     */
    private PCFMessage submitQueueNamesQuery(String qmgrName,
                                             PCFMessageAgent agent) {

        // build the pcf message
        PCFMessage inquireQNames = new PCFMessage(CMQCFC.MQCMD_INQUIRE_Q_NAMES);
        inquireQNames.addParameter(CMQC.MQCA_Q_NAME, "*"); 

        try {
            // send the message
            PCFMessage[] responseMsgs = agent.send(inquireQNames);

            // check if results received successfully
            if (responseMsgs[0].getCompCode() == 0) {
                return responseMsgs[0];
            }
        } 
        catch (IOException e) {
            // record error details
            Status internal_error = new Status(IStatus.ERROR,
                                               "com.wordpress.hursleyonwmq.healthcheck",
                                               0,
                                               "Error encountered while sending INQUIRE_Q_NAMES PCF to "
                                               + qmgrName,
                                               e);
            HealthcheckPlugin.getDefault().getLog().log(internal_error);
        } catch (MQException e) {
            // record error details
            Status internal_error = new Status(IStatus.ERROR,
                                               "com.ibm.mq.explorer.healthcheck.coretests",
                                               0,
                                               "Error encountered while sending INQUIRE_Q_NAMES PCF to "
                                               + qmgrName,
                                               e);
            HealthcheckPlugin.getDefault().getLog().log(internal_error);
        }

        // for some reason, we don't have a response, so return null
        return null;
    }
 
    /**
     * Used internally to check the given queue name against the collection of
     * acceptable prefixes.
     * <p>
     * 
     * @param queueName
     *            queue name to check
     * @return <code>true</code> if the queue name is okay, <code>false</code>
     *         otherwise
     */
    private boolean checkQueueName(String queueName) {

        // if this is a system object (i.e. it has a name which begins with
        //   "SYSTEM.") we check the
        if ((queueName.startsWith("SYSTEM.")) || (queueName.startsWith("AMQ."))) { 
            if (!includeSystemObjs) {
                // user has requested that we do not include system
                //  objects in the test, so we return true to
                //  avoid any problems being reported for this queue
                return true;
            }
        }

        // PCF response will white-pad the queue name, so we trim it now
        queueName = queueName.trim();

        // check the queue name against each of the acceptable prefixes
        //  in turn, returning true immediately if it is
        for (int i = 0; i < ACCEPTED_Q_PREFIXES.length; i++) {
            if (queueName.startsWith(ACCEPTED_Q_PREFIXES[i]))
                return true;
        }

        // we have checked against all accepted prefixes, without
        //  finding a match
        return false;
    }
 
    /**
     * Used internally to generate a test result for the given queue name.
     * 
     * @param queueName
     *            queue name which doesn't meet requirements
     * @param qmgrName
     *            name of queue manager which hosts the queue
     * @return the generated test result
     */
    private WMQTestResult generateTestResult(String queueName, String qmgrName) {
        String res = "Queue (" + queueName.trim() + ") does not begin with a known prefix"; 

        return new WMQTestResult(IMarker.SEVERITY_ERROR, 
                                 res, 
                                 qmgrName,
                                 getTestSubCategory());
    }
}

Notes on above source code

Skip to next section.

Creating your test object


As specified previously, your test should extend WMQTest. WebSphere MQ Explorer will instantiate the test object using the provided constructor WMQTest(). There is no need to subclass this constructor.

Launching the test


WebSphere MQ Explorer calls runTest(WMQTestEngine, IProgressMonitor, MQExtObject[] contextObjects, TreeNode treenode) to start running your test. The main body of your test should be here.

The start of the runTest method should be a call to the default implementation of runTest with super.runTest(callback, guimonitor, contextObjects, treenode). This caches handles to the provided parameters, which are required for various background tasks.

The WMQTestEngine parameter provides a handle to the test engine running the test. The handle lets tests return results while a test is in progress, using the test engine’s returnResult(WMQTestResult[], WMQTest) method:

  • First parameter of this method (WMQTestResult[]) contains the results to be returned.
  • Second parameter (WMQTest) should be this, so that the test engine knows where the results have come from.

Using the WMQTestEngine parameter to return interim results is optional, but may be useful for long-running tests. Alternatively, test results can be returned on test completion as outlined below.

Displaying feedback in the GUI


The IProgressMonitor parameter provides a handle to the GUI feedback monitor being used for the current test run. It lets your test provide both textual feedback on the task and/or subtasks currently running, and a progress bar for completion.

The handle to the Progress Monitor is cached by the default implementation of runTest as mentioned above, so a handle to the Progress Monitor can also be accessed using the WMQTest method getGUIMonitor().

The Progress Monitor is a core Eclipse resource. For details on how to use it, see the Eclipse API documentation. Some useful methods are listed below:

  • beginTask(String taskName, int numberOfStepsInTask)
    indicates that a task is starting, providing the name to display and the expected number of steps for use in progress bar
  • worked(int numberOfStepsCompleted)
    increments the progress bar by the provided number of steps
  • done()
    indicates that the task has been completed

Test Attributes


The list below specifies some of the attributes of the WMQTest superclass, together with their accessor methods. These attributes are not intended to be changed by subclass implementations, but may be useful for output.

  • test id – getTestId()
    String containing the unique identifier for your test, as specified in your plugin.xml
  • name – getTestName()
    String containing the user-friendly name of the test, as specified in your plugin.xml
  • description – getDescription()
    String containing the description of your test, as specified in your plugin.xml
  • documentation path – getFurtherInfoPath()
    String containing the location of the HTML documentation for your test, as specified in your plugin.xml

Dealing with cancelling


The user is able to cancel individual tests while running, or the whole test run. The method isCancelled() can be used to check if a test should stop. A good test should regularly check to see whether it has been cancelled to avoid delaying the user unnecessarily.

If you try to cancel a test, but the test fails to return for an extended period of time, the test engine will force the test to stop by killing the thread that is running it. But do not rely on this method — it is preferable that a test returns in time, enabling it to clean up any resources and return any test results generated.

Reporting errors


Errors encountered during a test run can be reported as shown in the code samples above. The error will be written to the Eclipse Errors View, including the stack trace contained in a Java exception if provided. Uncaught exceptions and errors thrown as a result of running your test will be caught by the Tests plugin test engine and written to the Errors View in this way. Therefore it is a good idea to check the Errors View regularly when developing a new test.

Creating a test result


When your test finds something that it wants to be returned to the user, it should create a test result object to describe the problem. Test results are implemented as WMQTestResult objects and should be created using new WMQTestResult(int severity, String description, String objectname, WMQSubCategory testType)

  • severity – an integer identifying the severity of the problem. should be one of the following: IMarker.SEVERITY_ERROR, IMarker.SEVERITY_WARNING or IMarker.SEVERITY_INFO
  • description – the string explaining the problem found by the test, to be displayed in the Problems View
  • qmgrname – the name of the object where the problem was found
  • testType – a handle to the test category, giving the class of object where the problem can be found (e.g. “Queues”, “Channels” etc.)

Completing a test


A test is completed by calling testComplete(WMQTestResult[]) and passing it an array of test result objects. The testComplete method requires a handle to the test engine that started the test running, and will not work if the default implementation of runTest has not been called prior to the testComplete call, as described above.

You can return results at completion using this method in addition to, or as an alternative to, returning test results during a test run using returnResult, as explained above. However, any results that are returned twice will be displayed twice.

Even if your test uses the WMQTestEngine method returnResult to return all of its results, it must still call testComplete on completion in order to complete the test processing. An empty array of WMQTestResult objects can be provided in the testComplete method if there are no additional results to be returned.

User preferences


Tests should conform to the user preferences provided using the Eclipse Preferences dialog. Access the preferences using:

RETURNS TRUE IF… RETURNS FALSE IF…
PreferenceStoreManager.getIncludeHiddenQmgrsPreference()
you should include queue managers that have been hidden from the WebSphere MQ Explorer in the test you should exclude queue managers that have been hidden from the WebSphere MQ Explorer in the test
PreferenceStoreManager.getIncludeSysObjsPreference()
system objects (objects which have names beginning with SYSTEM.) should be included in the test system objects (objects which have names beginning with SYSTEM.) should be excluded from the test

Complex tests

Test structure

As previously explained, the WMQTest method runTest defines the body of the test, and is called to start a test running.

The end of the runTest method does not imply the end of the test (which needs to be specified explicitly using testComplete), leaving test developers free to implement tests using asynchronous approaches to getting data to analyse.

For example, runTest can submit a request to get data about WebSphere MQ objects. The test execution can continue from the listener method that receives the reply. This essentially lets the test wait for data without test developers needing to implement thread waiting. The pseudocode example in the original developerWorks article demonstrates how you might approach this.

If a manual wait/sleep is needed as a part of a test, you can use the object monitor for your test object when wanting to use the Java wait/notify methods. The threading of the Healthcheck test engine is implemented without using the object monitors of individual test objects.

Conclusion

This post showed you how to extend WebSphere MQ Explorer functionality by writing an Eclipse plug-in using Java. The post outlined the steps to write an extension that enables WebSphere MQ Explorer to verify that MQ object names use a predefined set of prefixes.

Source for the naming-conventions-test discussed here have been included with the 6.0.2.0 Refresh Pack, in the com.ibm.mq.explorer.tests.sample_6.0.2.0 plugin. It can be found in C:\Program Files\IBM\WebSphere MQ\eclipse\plugins\ on Windows and /opt/mqm/eclipse/plugins/ on Linux.

Advertisements