New scenarios can be developed independently for test cases and decorator types. A scenario is identified by a marker interface. A scenario marker interface doesn't declare any methods. Instead, it uses static variables to declare a scenario runner as well as a name and a description that can be used by a test runner UI to for more user friendly reporting.
The following marker interfaces must be extended in order to define new scenarios:
|
Artefact |
Base marker interface |
Required variables |
|---|---|---|
|
Test cases |
com.thekirschners.TESTARE.core.scenarios.testcases TestCaseScenario |
SCENARIO_TEST_CASE_RUNNER SCENARIO_NAME SCENARIO_DESCRIPTION |
|
Fixtures |
com.thekirschners.TESTARE.core.scenarios.fixtures FixtureScenario |
SCENARIO_FIXTURE_RUNNER SCENARIO_NAME SCENARIO_DESCRIPTION |
|
Global fixtures |
com.thekirschners.TESTARE.core.scenarios.globalfixtures GlobalFixtureScenario |
SCENARIO_FIXTURE_RUNNER SCENARIO_NAME SCENARIO_DESCRIPTION |
|
Probes |
com.thekirschners.TESTARE.core.scenarios.probes TestProbeScenario |
SCENARIO_PROBE_RUNNER SCENARIO_NAME SCENARIO_DESCRIPTION |
|
Guards |
com.thekirschners.TESTARE.core.scenarios.guards TestGuardScenario |
SCENARIO_GUARD_RUNNER SCENARIO_NAME SCENARIO_DESCRIPTION |
All SCENARIO_XYZ_RUNNER variables must be of type class. SCENARIO_NAME and SCENARIO_DESCRIPTION must be strings.
The following code samples show how to declare a new test case execution scenario and and how to implement a new scenario test case runner.
This is an example of a test case execution scenario declaration:
public interface ClientSideTest extends TestScenario {
public static final Class SCENARIO_TEST_CASE_RUNNER = ClientSideScenarioTestRunner.class;
public static final String SCENARIO_NAME = "Client JVM execution, no transaction";
public static final String SCENARIO_DESCRIPTION = "The test will be executed in a client JVM,
without starting a user transaction. Should be used to test
client side JAVA classes, or EJBs called from the client side.";
}
public class ClientSideScenarioTestRunner implements TestCaseRunner {
/**
* should call setUp, the test method, tearDown
* @param testCaseInstance
* @param scenario
* @param testMethod
* @return
* @throws TestCaseExecutionException
*/
public TestResultDescriptor runTest(TestCase testCaseInstance, Class scenario, String testMethod)
throws TestNotFoundException, TestCaseExecutionException {
return TestMethodRunner.runTest(testCaseInstance, scenario, testMethod);
}
/**
* execute fixtures locally - for those fixture for which a scenario was not specified
* this is required for executing floating fixtures
* @param f
* @return
* @throws com.thekirschners.TESTARE.core.runner.decorators.fixtures.FixtureSetUpException
*/
public Fixture setUp(Fixture f) throws FixtureSetUpException {
f.setUp(); // for other scenarios, this call can be delegated to a remote environment like an
EJB container, an RMI server, a CORBA ORB or a JMS listener
return f;
}
/**
* executes a test probe locally
* this is required to execute floating probes
* @param probe
* @throws TestProbeException
*/
public void runProbe(TestProbe probe) throws TestProbeException {
probe.executeProbe(); // for other scenarios, this call can be delegated to a remote environment like an EJB container, an RMI server,
// a CORBA ORB or a JMS listener
}
/**
* execute fixtures locally - for those fixture for which a scenario was not specified
* this is required to execute floating fixtures
*
* @param f
* @param testResultDescriptor
* @throws FixtureTearDownException
*/
public void tearDown(Fixture f, TestResultDescriptor testResultDescriptor) throws FixtureTearDownException {
f.tearDown(testResultDescriptor); // for other scenarios, this call can be delegated to a remote environment
// like an EJB container, an RMI server, a CORBA ORB or a JMS listener
}
}
The following code samples show how to declare a new fixture execution scenario and how to implement a new scenario fixture runner.
public interface ClientSideFixture extends FixtureScenario {
public static final Class SCENARIO_FIXTURE_RUNNER = ClientSideFixtureRunner.class;
public static final String SCENARIO_NAME = "client side execution";
public static final String SCENARIO_DESCRIPTION = "Fixtures will be executed in the save JVM as the test suite runner";
}
public class ClientSideFixtureRunner implements FixtureRunner {
public Fixture setUp(Fixture f) throws FixtureSetUpException {
return f.setUp(); // for other scenarios, this call can be delegated to a remote
// environment
}
public void tearDown(Fixture f, TestResultDescriptor testResultDescriptor) throws FixtureTearDownException {
f.tearDown(testResultDescriptor); // for other scenarios, this call can be delegated to a remote
// environment like an EJB container, an RMI server, a CORBA ORB or a JMS listener
}
}
The following code samples show how to declare a new global fixture execution scenario and how to implement a new global scenario fixture runner.
public interface ClientSideGlobalFixture extends GlobalFixtureScenario {
public static final Class SCENARIO_FIXTURE_RUNNER = ClientSideGlobalFixtureRunner.class;
public static final String SCENARIO_NAME = "Client Side Global Fixture Scenario";
public static final String SCENARIO_DESCRIPTION = "Glbal fixtures will be executed in the save JVM as the test suite runner.";
}
public class ClientSideGlobalFixtureRunner implements GlobalFixtureRunner {
public void setUp(GlobalFixture globalFixture) throws GlobalFixtureSetUpException {
globalFixture.setUp(); // for other scenarios, this call can be delegated to a remote
// environment like an EJB container,
// an RMI server, a CORBA ORB or a JMS listener
}
public void tearDown(GlobalFixture globalFixture) throws GlobalFixtureTearDownException {
globalFixture.tearDown(); // for other scenarios, this call can be delegated to a remote environment like an
// EJB container, an RMI server, a CORBA ORB or a JMS listener
}
}
public interface ClientSideTestProbe extends TestProbeScenario {
public static final Class SCENARIO_PROBE_RUNNER = ClientSideTestProbeRunner.class;
public static final String SCENARIO_NAME = "Client Side Probe Scenario";
public static final String SCENARIO_DESCRIPTION = "The test environment probe will
be executed in the save JVM as the test suite runner";
}
public class ClientSideTestProbeRunner implements TestProbeRunner {
public void runProbe(TestProbe probe) throws TestProbeException {
probe.executeProbe(); // for other scenarios, this call can be delegated to a
//remote environment like an EJB container,
// an RMI server, a CORBA ORB or a JMS listener
}
}
public interface ClientSideTestGuard extends TestGuardScenario {
public static final Class SCENARIO_GUARD_RUNNER = ClientSideTestGuardRunner.class;
public static final String SCENARIO_NAME = "Client Side Guard Scenario";
public static final String SCENARIO_DESCRIPTION = "The test guard will be executed in
the save JVM as the test suite runner";
}
public class ClientSideTestGuardRunner implements TestGuardRunner {
public void checkPrecondition(TestGuard guard) throws TestPreconditionException {
guard.checkPrecondition(); // for other scenarios, this call can be delegated to a
// remote environment like an EJB container, an
// RMI server, a CORBA ORB or a JMS listener
}
public void checkPostcondition(TestGuard guard) throws TestPostconditionException {
guard.checkPostcondition(); // for other scenarios, this call can be delegated to a
// remote environment like an EJB container, an RMI server,
// a CORBA ORB or a JMS listener
}
}
TESTARE comes with three test result repoting plugins out of the box:
a plain text test result reporter that can print the results either to the console or to a file
a xml test result reporter that outputs test results in XML format to a file. This XML file can then be transformed at wish using XSL. Some default XSL transformation sheets may be included in the future.
A Velocity based HTML reporter, which is highly cutomizable as it uses template based HTML code generation. In this first version it only generates static HTML content, but in the future it could be modified to generate more ergonomic dynamic HTML.
If this is not enough, one can attempt to develop new test result reporting tools. In order to achieve this one has to implement the TestResultReportPrinter interface in the com.thekirschners.TESTARE.core.runner.reports package. Example implementations can be found in the com.thekirschners.TESTARE.core.runner.reports.velocity and com.thekirschners.TESTARE.core.runner.reports.xml packages, in the core module.
The default test artifact finder in TESTARE is file system based. This should suffice for most cases but some extensions may be required in special situations, like when integrating with different IDEs or custom build tools. In order to implement new test artifacts finders one has to extend the abstract TestCaseFinder class from the com.thekirschners.TESTARE.integrations.testgroups package, and then write a helper class to find the test artifacts using the new finder, execute them all and then display or report the results in any other way. For an example of how to do it, one can look at the FileSystemTestCaseFinder and FileSystemFinderRunnerHelper in the com.thekirschners.TESTARE.integrations.testgroups package in the core module.
TESTARE offers everything one may need to integrate with a third party IDE and / or command line build tool. An ANT integration is already provided out of the box. Integrating with IDEA and Eclipse are high priority features on the roadmap.
In order to achieve such an integration one will have to write a plug-in for the host system in which TESTARE must be integrated. This plug-in will have to use a test artifact finder either the default file system based one or the new, dedicated one , run the tests, output reports and display the results, all in a way that integrates nicely with the host system.