Daemon API

The daemon API provides all methods necessary to directly control test execution via a QF-Test daemon. Typically the following relatively simple steps need to be implemented:

Note When writing an application based on the daemon API you need to take security considerations into account and either disable security or set some RMI-specific properties as described in section 53.3.

  • Get hold of a Daemon using the DaemonLocator service.
  • Either get hold of the shared TestRunDaemon or have the Daemon create a TestRunDaemon. You can use the TestRunDaemon to define global variables and the root directory of your test suites for the upcoming test runs.
  • Either get hold of the TestRunDaemon's shared DaemonRunContext or have it create one or more DaemonRunContext instances. A DaemonRunContext represents one test execution context for functional or load testing. Each DaemonRunContext is independent of the others, except for a group of contexts created via TestRunDaemon.createContexts(int threads) which creates a group of related contexts for load-testing similar to running QF-Test with the -threads <number> command line argument. Each DaemonRunContext requires one QF-Test development or runtime license during its lifetime.
  • Now you can tell the DaemonRunContext to execute tests on your behalf, either whole test suites or 'Test set' or 'Test case' nodes. With properly implemented 'Dependencies' you can have a Daemon execute 'Test cases' on your behalf in any arbitrary order without explicitly having to take care of any setup or cleanup tasks.
  • The DaemonRunContext also has methods to check the current state of a test run or wait for it to finish.
  • Finally you can get the run log of the test run from the Daemon. Right now, all you can do is save it, but we will open the run log API so that you will be able to integrate run logs from various daemons and test runs into a single run log.

For proper dependency management, including rollback of no longer required dependencies between 'Test case' invocations, it is important to use the same DaemonRunContext for execution of each related 'Test case'. The easiest way to achieve this is to use the shared TestRunDaemon and its shared DaemonRunContext each time you talk to a given Daemon.

The following sections provide a complete reference for the daemon API. Further explanations and examples are provided in section 23.2.

The DaemonLocator

The singleton class de.qfs.apps.qftest.daemon.DaemonLocator can be used to get hold of Daemon instances.

 
 
static DaemonLocator instance()
Get the singleton instance.
ReturnsThe singleton instance.
 
Daemon locateDaemon(String host, int port)
Get a Daemon from a specific host and port.
Parameters
host The target host, name or IP string.
port The target port.
ReturnsThe daemon or null if none can be found.
 
Daemon[] locateDaemons(long timeout)
Get all known daemons.
Parameters
timeout The time in milliseconds to wait for daemons to react.
ReturnsThe known daemons.
 
void setKeystore(String keystoreFile)
Sets the keystore, which should be used to to secure the daemon communication.
Parameters
keystoreFile The path to the keystore file used to encrypt the daemon communication.
 
void setKeystorePassword(String password)
Sets the password for the keystore defined with setKeystore.
Parameters
password The password.
 
void setTruststore(String truststoreFile)
Sets the truststore, which should be used to to secure the daemon communication. If not set, the keystore will be used, which has been set with setKeystore.
Parameters
truststoreFile The path to the truststore file used to encrypt the daemon communication.
 
void setTruststorePassword(String password)
Sets the password for the trststore defined with setTruststore.
Parameters
password The password.
 
 

The Daemon

The de.qfs.apps.qftest.daemon.Daemon interface is an envelope for various kinds of QF-Test daemons. Currently only the TestRunDaemon is available, but something like an SUTClientStarterDaemon is already planned and others may follow.

 
 
void cleanup()
Clean up all TestRunDaemons belonging to this Daemon and then kill all clients. The default timeout of 30 seconds is used to wait for possible dependency rollback.
Throws
RemoteException If something RMI specific goes wrong.
 
void cleanup(long timeout)
Clean up all TestRunDaemons belonging to this Daemon and then kill all clients.
Parameters
timeout The maximum time in milliseconds to wait for possible dependency rollback.
Throws
RemoteException If something RMI specific goes wrong.
 
TestRunDaemon createTestRunDaemon()
Get access to a TestRunDaemon.
Returns A TestRunDaemon.
Throws
RemoteException If something RMI specific goes wrong.
 
String getHost()
Get the host of the Daemon.
ReturnsThe host of the Daemon.
Throws
RemoteException If something RMI specific goes wrong.
 
String getIp()
Get the ip of the Daemon.
Returns The ip of the Daemon.
Throws
RemoteException If something RMI specific goes wrong.
 
int getPort()
Get the port of the Daemon.
Returns The port of the Daemon.
Throws
RemoteException If something RMI specific goes wrong.
 
TestRunDaemon getSharedTestRunDaemon()
Get the shared TestRunDaemon.
Returns The shared TestRunDaemon.
Throws
RemoteException If something RMI specific goes wrong.
 
TestRunDaemon[] getTestRunDaemons()
Get all TestRunDaemons created by the Daemon that are still live.
Returns The set of live TestRunDaemons created by the Daemon. Does not include the shared TestRunDaemon.
Throws
RemoteException If something RMI specific goes wrong.
 
void killClients()
Kill all clients that belong to the VM of the daemon.
Throws
RemoteException If something RMI specific goes wrong.
 
void ping()
Test whether the Daemon is still alive.
Throws
RemoteException If something RMI specific goes wrong.
 
void terminate(int exitCode)
Terminate the daemon process by calling System.exit.
Parameters
exitCode The exit code for the daemon.
Throws
RemoteException If something RMI specific goes wrong.
 
 

The TestRunDaemon

The de.qfs.apps.qftest.daemon.TestRunDaemon is the outer interface for test execution. It is used to define the environment for associated test runs and create the DaemonRunContext instances that handle the actual test execution.

Miscellaneous

 
 
Daemon getDaemon()
Get the Daemon to which the TestRunDaemon belongs.
Returns The Daemon of the TestRunDaemon.
Throws
RemoteException If something RMI specific goes wrong.
 
 

Global variable handling

The TestRunDaemon has its own set of global variables which are used to initialize the globals when creating a new DaemonRunContext. The following methods have no effect on already running DaemonRunContext instances.

 
 
void clearGlobals()
Clear all global variables.
Throws
RemoteException If something RMI specific goes wrong.
 
String getGlobal(String name)
Get a global variable value.
Parameters
name The name of the global variable.
Returns The value of the global variable or null if undefined.
Throws
RemoteException If something RMI specific goes wrong.
 
Properties getGlobals()
Get all global variable values.
Returns All global variable values.
Throws
RemoteException If something RMI specific goes wrong.
 
void setGlobal(String name, String value)
Set a global variable value.
Parameters
name The name of the global variable.
value The value of the global variable.
Throws
RemoteException If something RMI specific goes wrong.
 
 

Test execution

 
 
void cleanup()
Clean up and release all contexts belonging to this TestRunDaemon. The default timeout of 30 seconds is used to wait for possible dependency rollback.
Throws
RemoteException If something RMI specific goes wrong.
 
void cleanup(long timeout)
Clean up and release all contexts belonging to this TestRunDaemon.
Parameters
timeout The maximum time in milliseconds to wait for possible dependency rollback.
Throws
RemoteException If something RMI specific goes wrong.
 
DaemonRunContext createContext()
Create a single daemon run context. Needs to acquire a license.
Returns The context or null if no license can be acquired.
Throws
RemoteException If something RMI specific goes wrong.
 
DaemonRunContext[] createContexts(int threads)
Create daemon run contexts for multiple threads. Needs to acquire one license per thread.
Parameters
threads The number of threads for the contexts.
Returns The contexts or null if not enough licenses can be acquired.
Throws
RemoteException If something RMI specific goes wrong.
 
DaemonRunContext[] getContexts()
Get all DaemonRunContexts created by the TestRunDaemon that are still live and have not been released.
Returns The set of live DaemonRunContexts created by the TestRunDaemon. Does not include the shared DaemonRunContext.
Throws
RemoteException If something RMI specific goes wrong.
 
DaemonRunContext getSharedContext()
Get the shared daemon run context. Needs to acquire a license if the shared context must be created first.
Returns The shared context or null if no license can be acquired.
Throws
RemoteException If something RMI specific goes wrong.
 
void setRootDirectory(String directory)
Set the test suite root directory for new created daemon run contexts.
Parameters
directory The new root directory.
Throws
RemoteException If something RMI specific goes wrong.
 
 

Identification

 
 
String getIdentifier()
Get the identifier for the TestRunDaemon. If no identifier was previously set with setIdentifier(), a default identifier is created from the name of the Daemon, to which the TestRunDaemon belongs, and a counter.
Returns The identifier for the TestRunDaemon.
Throws
RemoteException If something RMI specific goes wrong.
 
void setIdentifier(String identifier)
Set an identifier for the TestRunDaemon. This can be useful in identifying a TestRunDaemon retrieved via Daemon.getTestRunDaemons().
Parameters
identifier The identifier to set.
Throws
RemoteException If something RMI specific goes wrong.
 
 

The DaemonRunContext

The de.qfs.apps.qftest.daemon.DaemonRunContext interface is in charge of the actual test execution.

The following run states are defined:

StateValueDescription
STATE_INVALID-1Invalid after release - cannot be reactivated.
STATE_IDLE0No run scheduled.
STATE_SCHEDULED1Run scheduled but not started.
STATE_RUNNING2Running.
STATE_PAUSED3Running but paused.
STATE_FINISHED4Run finished, result and run log available.
Table 53.1:  The run state

6.0+ The following result codes for the getResult() method are the same as everywhere in QF-Test:

ResultValueDescription
RESULT_OK0Run OK, no warnings, errors or exceptions.
RESULT_WARNING1Run mostly OK, some warnings but no errors or exceptions.
RESULT_ERROR2Run failed with errors but no exceptions.
RESULT_EXCEPTION3Run failed with an exception.
Table 53.2:  The result codes
 
 
void addTestRunListener(DaemonTestRunListener listener, boolean synchronous, long timeout)
Add a DaemonTestRunListener to the DaemonRunContext.
Parameters
listenerThe listener to add.
synchronous Whether the listener should get notified synchronously, in which case the test run will be blocked while the listener is processing the event.
timeout Timeout in milliseconds for callbacks to the listener. If the listener does not reply within that time the listener is automatically unregistered to prevent further problems. In case of a synchronous listener the test run will then continue. A value of 0 means no timeout which is dangerous but may be useful.
 
boolean callProcedure(String procedure, Properties bindings=None)
Call a procedure in the run context.
Parameters
procedure The procedure to run, of the form Suite#Procedure where Procedure is the fully qualified name of the 'Procedure'.
bindings An optional set of variable bindings. These variables have higher precedence than the globals or any bindings on the fallback stack.
Returns True if the procedure call was started, false if suite or procedure could not be found.
Throws
RemoteException If something RMI specific goes wrong.
IllegalStateException If no run can be started in the current state, i.e. if the state is neither STATE_IDLE nor STATE_FINISHED.
 
void clearGlobals()
Clear all global variables of the DaemonRunContext.
Throws
RemoteException If something RMI specific goes wrong.
 
void clearTestRunListeners()
Remove all DaemonTestRunListeners from the DaemonRunContext.
 
String getGlobal(String name)
Retrieve the value of a global variable from the DaemonRunContext.
Parameters
nameThe name of the variable.
Returns The value of the variable or null if undefined.
Throws
RemoteException If something RMI specific goes wrong.
 
Properties getGlobals()
Retrieve all global variables from the DaemonRunContext.
Returns The global variables.
Throws
RemoteException If something RMI specific goes wrong.
 
String getIdentifier()
Get the identifier for the DaemonRunContext. If no identifier was previously set with setIdentifier(), a default identifier is created from the name of the TestRunDaemon, to which the DaemonRunContext belongs, and a counter.
Returns The identifier for the DaemonRunContext.
Throws
RemoteException If something RMI specific goes wrong.
 
String getLastTest()
Get the name of the test that is currently running or was last run on this DaemonRunContext.
Returns The name of the currently running or most recently executed test.
Throws
RemoteException If something RMI specific goes wrong.
 
int getNumThreads()
Get the number of threads in the group to which the DaemonRunContext belongs.
Returns The number of threads of the DaemonRunContext's group.
Throws
RemoteException If something RMI specific goes wrong.
 
Properties getProperties(String group)
Retrieve all properties from a property or resource group from the DaemonRunContext.
Parameters
nameThe name of the property or resource group.
Returns The properties or null if no such group exists.
Throws
RemoteException If something RMI specific goes wrong.
 
String getProperty(String group, String name)
Retrieve the value of a property or resource from the DaemonRunContext.
Parameters
nameThe name of the property or resource group.
nameThe name of the property.
Returns The value of the property or null if undefined.
Throws
RemoteException If something RMI specific goes wrong.
 
int getResult()
Get the result of the test run.
Returns The result of the run, one of RESULT_OK, RESULT_WARNING, RESULT_ERROR or RESULT_EXCEPTION.
Throws
RemoteException If something RMI specific goes wrong.
IllegalStateException If the state isn't STATE_FINISHED.
 
byte[] getRunLog()
Get the run log of the test run.
Returns The run log dumped into a byte array.
Throws
RemoteException If something RMI specific goes wrong.
IllegalStateException If the state isn't STATE_FINISHED.
 
int getRunState()
Get the current run state of the context.
Returns The current run state, one of STATE_IDLE, STATE_SCHEDULED, STATE_RUNNING, STATE_PAUSED or STATE_FINISHED.
Throws
RemoteException If something RMI specific goes wrong.
 
TestRunDaemon getTestRunDaemon()
Get the TestRunDaemon to which the DaemonRunContext belongs.
Returns The TestRunDaemon of the DaemonRunContext.
Throws
RemoteException If something RMI specific goes wrong.
 
int getThreadNum()
Get the thread index of the DaemonRunContext.
Parameters
Returns The thread index of the DaemonRunContext.
Throws
RemoteException If something RMI specific goes wrong.
 
void release()
Release the DaemonRunContext and return its license. If a test is running, stop it.
Throws
RemoteException If something RMI specific goes wrong.
IllegalStateException If no DaemonRunContext was allocated.
 
void removeTestRunListener(DaemonTestRunListener listener)
Remove a DaemonTestRunListener from the DaemonRunContext.
Parameters
listenerThe listener to remove.
 
void rollbackDependencies()
Roll back the dependencies for this DaemonRunContext.
Throws
RemoteException If something RMI specific goes wrong.
IllegalStateException If no run can be started in the current state, i.e. if the state is neither STATE_IDLE nor STATE_FINISHED.
 
boolean runTest(String test, Properties bindings=None)
Run a test in the run context.
Parameters
test The test to run, of the form Suite#Test where #Test is optional and Test is the fully qualified name of a 'Test set' or 'Test case' or just ".". The latter is equivalent to specifying just Suite and causes the whole test suite to be executed. Examples:
MySuite   Runs whole test suite MySuite.
MySuite#.   Runs whole test suite MySuite.
MySuite#MyTestSet   Runs test set MyTestSet in test suite MySuite.
MySuite#MyTestSet.MyTestCase   Runs test case MyTestCase located in test set MyTestSet in test suite MySuite.
bindings An optional set of variable bindings. These variables have higher precedence than the globals or any bindings on the fallback stack.
Returns True if the test was started, false if suite or test could not be found.
Throws
RemoteException If something RMI specific goes wrong.
IllegalStateException If no run can be started in the current state, i.e. if the state is neither STATE_IDLE nor STATE_FINISHED.
 
void setGlobals(Properties globals)
Set the global variables of the DaemonRunContext.
Parameters
globals The global variables to set.
Throws
RemoteException If something RMI specific goes wrong.
 
void setIdentifier(String identifier)
Set an identifier for the DaemonRunContext. This can be useful in identifying a DaemonRunContext retrieved via TestRunDaemon.getContexts().
Parameters
identifier The identifier to set.
Throws
RemoteException If something RMI specific goes wrong.
 
void setRootDirectory(String directory)
Set the test suite root directory for the next test run.
Parameters
directory The new root directory.
Throws
RemoteException If something RMI specific goes wrong.
 
void stopRun()
Stop the test run.
Throws
RemoteException If something RMI specific goes wrong.
IllegalStateException If no run was scheduled.
 
boolean waitForRunState(int state, long timeout)
Wait for the context to reach a given state.
Parameters
state The state to wait for.
timeout Maximum time in milliseconds to wait.
Returns True if the state was reached, false if timed out.
Throws
RemoteException If something RMI specific goes wrong.
 
 

3.1+53.2.5
The DaemonTestRunListener

The de.qfs.apps.qftest.daemon.DaemonTestRunListener interface is identical to the interface de.qfs.apps.qftest.extensions.qftest.TestRunListener described in section 52.7, except that its methods can throw a RemoteException on RMI failure. When implementing this interface you must derive your class from java.rmi.server.UnicastRemoteObject.

You can register the listener with a DaemonRunContext via its addTestRunListener method described in the previous section.