Package org.jwalk.out

This sub-package for JWalk 1.1 contains various JWalk test reports, © Anthony J H Simons, 2006-2011.

See:
          Description

Class Summary
AlgebraReport AlgebraReport is a report on the test class's algebraic structure.
Confirmation Confirmation is a kind of question to confirm or reject a test result.
CycleReport CycleReport is a test report generated after executing one test cycle.
Notification Notification is a kind of acknowledged interaction with the tester.
ProtocolReport ProtocolReport is a report on the test class's public interface.
Question Question is the abstract ancestor of all kinds of question.
Report Report is the ancestor of all kinds of report.
StateReport StateReport is a report on the test class's high-level design states.
StatisticalReport StatisticalReport is an abstract report containing test statistics.
SummaryReport SummaryReport is a summary of test statistics once testing is finished.
 

Enum Summary
Answer Answer enumerates the possible symbolic answers to a dialog question.
Edition Edition enumerates the different kinds of Report and Question.
Urgency Urgency enumerates the possible levels of severity of a notification.
 

Package org.jwalk.out Description

This sub-package for JWalk 1.1 contains various JWalk test reports, © Anthony J H Simons, 2006-2011. These are the different kinds of Report and Question components transmitted back to third-party listeners by the JWalk 1.1 testing engine. Developers wishing to customise how their third-party testing tools display the results of tests will need to access the contents of these reporting components. This documentation should be read in conjunction with the main documentation for using the JWalk component kit:

The rest of this package documentation gives an overview of the different kinds of test report produced by the JWalk 1.1 tool suite. For information about the toolkit API, please refer to the root package org.jwalk.

Common JWalk Reporting Concepts

The JWalk 1.1 toolkit does not automatically output test results to files, or to the screen as text, but rather observes Java's event-based model for communication. This allows the core testing engine to be decoupled from different kinds of front-end tools for executing the testing algorithms. A third-party testing application must register suitable listeners with the core testing engine, which are capable of handling the events dispatched by the engine.

Registering Listeners

A JWalk 1.1 testing application always creates a single instance of the main test engine class JWalker. This provides two component APIs called Channels and Settings. The Channels API is an object whose purpose is to set up the communication channels between the core test engine and the third-party application. It is used in the following way:

        JWalker walker = new JWalker();
        Channels channels = walker.getChannels();
        channels.addQuestionListener(new MyQuestionListener());
        channels.addReportListener(new MyReportListener());
where MyQuestionListener and MyReportListener are classes supplied by the third-party application, which respectively satisfy the QuestionListener and ReportListener interfaces. Once added as listeners, these objects will receive QuestionEvents or ReportEvents from the core test engine, which respectively contain Question or Report reporting objects. How they present this information to the tester is up to the designer of the third-party application.

The Contract for ReportListener

A ReportListener is designed to publish test reports emitted by the JWalk 1.1 test engine. It must provide the single method:

        void publish(ReportEvent event)
which accepts a ReportEvent and publishes the contents of the report that this contains. That is, processing a ReportEvent should cause the third-party application to display the contents of a test report in the manner determined by the designer of that application. A simple skeleton implementation might be:
        void publish(ReportEvent event) {
            Report report = event.getReport();
            System.out.println(report.getContent());
        }
which simply prints the content of the report on standard output. Third-party applications may choose to interrogate the report-object in smarter ways, in order to customise how the content of the report is displayed. See below for how to determine the exact type of a report-object; and refer to its individual documentation.

The Contract for QuestionListener

A QuestionListener is designed to interact with the human tester in order to elicit a response to a question. It must provide the single method:

        Answer respond(QuestionEvent event)
which accepts a QuestionEvent and returns an enumerated value from the Answer type, indicating the user's answer to the question. That is, processing a QuestionEvent should cause the third-party application to ask the tester a question, and accept a reply from the tester, which can be converted into an Answer. The way in which the application does this is up to the designer, for example, it could pop up a dialog displaying the content of the question, and offer the tester several buttons to indicate the answer. A simple skeleton implementation might be:
        Answer respond(QuestionEvent event) {
            Question question = event.getQuestion();
            System.out.println(question.getContent());
            do {
                System.out.println(question.getQuestion());
                /* Get a response from the user */
            }
            while( /* Response not acceptable */ );
            /* Convert response to an Answer */
            return answer;
        }
which prints out the information-content of the question, then repeatedly prompts the user with a query for input, until a valid response is received. The content-part and question-part of a question object may be presented separately, as illustrated here. Dialogs will display just the content, and use buttons to elicit the response.

The Report and Question Components

Every kind of information object emitted by the JWalk 1.1 tool suite is some kind of Report. A Question is merely a kind of report that solicits a response from the tester. Both of these produce formatted output strings using getContent(); and questions also produce a formatted query prompts (as prompt strings) using getQuestion(). The various kinds of Report and Question emitted by the tool suite may be classified in a hierarchy:

Each of these reporting components also provides specific access methods to access different parts of the reported results; and a number of formatting methods to convert reported elements (objects) into conventional string representations, ready for display.

Whereas the content of a general test Report is merely published, a Question or Notification usually requires some kind of response from the user. Questions may trigger dialogs that offer yes, no orquit responses, whereas Notifications trigger dialogs that offer ok responses. From version 1.1, certain Notifications may also encapsulate exceptions raised by the test engine, so third-party programs need to process these selectively.

Discriminating Report and Question Types

To make it easier for third-party applications to access directly the exact types of reports and questions extracted from a ReportEvent or QuestionEvent events, the root Report class provides a discriminating method:

        Edition getEdition()
which returns an enumerated value from the Edition type. There is one unique value for each different kind of report or question. The result of this may be used in switch-statements to discriminate between each kind of report. This allows third-party applications to typecast the report- or question-objects to more specific types, prior to accessing their contents directly through their (different) public APIs. A skeleton implementation might be:
        void publish(ReportEvent event) {
            Report report = event.getReport();
            switch(report.getEdition()) {
                case Edition.PROTOCOL_REPORT :
                    handle((ProtocolReport) report); break;
                case Edition.ALGEBRA_REPORT :
                    handle((AlgebraReport) report); break;
                ...
            }
        }
This assumes that the third-party listener also provides overloaded versions of the handle() method for each kind of Report, which then access the contents of the reports directly. Please refer to the documentation associated with each Report subclass for further details.

The same approach is used to distinguish between Question and Notification requests unpacked from QuestionEvent events. Notification objects are further discriminated according to how serious the notification is. The urgency can be accessed using:

        Urgency getUrgency()
and this may be used to determine what kind of dialog to trigger in the GUI, for example:
        void handle(Notification notice) {
            switch(notice.getUrgency()) {
                case Urgency.SILENT :
                    // A silent notification, no response required
                case Urgency.NOTICE :
                    // A notice, trigger an information dialog
                case Urgency.WARNING :
                    // A warning, trigger a warning dialog
                case Urgency.ERROR :
                    // An exception, trigger an error dialog
            }
        }
From version 1.1, a Notification may encapsulate an exception raised by the test engine. This must be handled in some suitable way by the third-party code. Also, when the test engine is run in a separate thread, a SILENT notification is dispatched to signal the end of the thread's execution. This allows a third-party GUI to synchronise itself with the test engine. See the API of Notification.

Standard and Custom Presentation

By default, the getContent() method returns the content of a report as a formatted string, with carriage returns. Each different kind of report also offers an API that accesses the different parts of the report individually. The notion is that programmers may choose to format some of this data in custom ways. For example, different test results could be highlighted using different colours. To do this, you would access the list of test sequences directly from a CycleReport:

        List results = report.getTestResults();
        for (TestSequence sequence : results) {
            if (sequence.hasPassed())
                /* Display result with a green background */
            else 
                /* Display result with a red background */
            ...
        }
and similar visual or iconic conventions could be used to highlight sequences which executed normally, or which terminated in exceptions.

Each kind of report also offers formatting methods that allow the third-party application to format data in the standard string format, but on a piecemeal basis. So, for example, each TestSequence could be extracted individually and possibly filtered by the third-party application, but then displayed as a conventional string using the overloaded method:

        String toString(TestSequence sequence, boolean outcome)
provided by the reporting-class CycleReport. This formatting method allows the designer to supply a boolean flag, indicating whether the test outcome should be appended to the formatted text, or omitted (because the application indicates the outcome in some other way). The aim of providing these formatting methods is to give the desginer of third-party applications a completely free hand in whether to use the default formatting options, provide a custom display facility, or use a mixture of both.