Develop a Laucher

Developing a new launcher essentially consists in:
  • Implementing the main java class (extending CLauncher)
  • Writing the configuration template

Implementing the main java class

The main java class will have to extend the class com.xqual.xagent.launcher.CLauncher
There will be 5 methods to implement. These methods will be automatically called by XStudio or XAgent's execution scheduler:

Launcher Process

5 methods to implement


CReturnStatus initialize(int sutId, String sutName, String sutVersion)
The initialize method is executed once at the instantiation of the launcher by the agent or by XStudio.
You can put there all operations of initialization that needs to be done before everything else.
This method is called by XStudio when the session starts. This is the right place to setup the test environment. Sometimes it is useful to know which SUT is going to be tested so all the SUT information are passed to the launcher at this point. This is also where we generally parse the configuration information with the getXXXParamValue() methods.
CReturnStatus preRun(int testId, String testPath, String testName, Vector<CTestAttribute> attributes, String additionalInfo)
The preRun step is executed before all the testcases are run.
You can put there all operations of initialization that needs to be done before all testcases are executed.
This is called when a new test is about to start. All the attributes of the test are passed (as well a s the additional Info string) so that the launcher can eventually use them.
CReturnStatus run(int testId, String testPath, String testName, int testcaseId, int testcaseIndex, String testcaseName, Vector<CTestcaseParam> params, String additionalInfo)
The run step is the main entry point to execute a particular testcase.
The testcase must handle correctly all cleanup tasks (apart from operations previously executed in preRun
This is in this method that you will have to execute your test case.
CReturnStatus postRun(int testId, String testPath, String testName)
The postRun step is executed after all the testcases have been executed.
You can put there all operations of cleanup necessary to bring back the SUT to its initial state.
It's a good idea to rollback what were previsously done in the preRun step.
This is called when a new test is about to be terminated: all test cases have been executed. We're leaving this test and are going to get to the next one.
CReturnStatus terminate()
The terminate method is executed once when the launcher is not anymore used.
You can put there all operations of termination that needs to be done after all the tests have been executed.
Basically you do here all the cleanup.

The mandatory APIs

Build structured messages to be returned

The messages returned are include in the CReturnStatus object returned by the 5 methods to implement described above.
Most of the time you will build a CReturnStatus object using this kind of code:
Vector executionSteps = new Vector();

executionSteps.add(new CExecutionStep(CCalendarUtils.getCurrentTime(),
RESULT_INFO, "This is a message you want to see in the test case execution details"));

executionSteps.add(new CExecutionStep(CCalendarUtils.getCurrentTime(),
RESULT_SUCCESS, "This is a message informing about a successful step"));

executionSteps.add(new CExecutionStep(CCalendarUtils.getCurrentTime(),
RESULT_FAILURE, "This is a message informing about a failed step"));

// in this case, RESULT_FAILURE is the global result given to the test case execution:
return new CReturnStatus(RESULT_FAILURE, executionSteps);

for more details about the result codes, check out the SDK API reference.

Add attachments


void addSessionMessageAttachment(File file)
Add an attachment file to the session being executed.

void addSessionMessageAttachments(Vector files)
Add several attachment files to the session being executed.

void addSessionMessageAttachmentFolder(File file)
Add all attachment files contained in a folder to the session being executed.

void addTestcaseMessageAttachment(File file) (replace the deprecated addAttachment(File file) method)
Add an attachment file to the testcase being executed in the session.

void addTestcaseMessageAttachments(Vector files) (replace the deprecated addAttachments(Vector files) method)
Add several attachment files to the testcase being executed in the session.

void addTestcaseMessageAttachmentFolder(File file) (replace the deprecated addAttachmentFolder(File file) method)
Add all attachment files contained in a folder to the testcase being executed in the session.

Auto-extractable html zip files: In many places, you can attach some files to objects in XStudio.
When you attach a zip file and open it later, the default application for zip file (configurable in your OS's settings) is used to open it.
This is fine but in certain cases (i.e. html structure), it could be useful to unzip the file on the fly and open a specific entry point file in the zip.

You can do this now just by naming a specific way your zip file.

Let's imagine you attach a file named my_report.html.zip that contains several files (.css, images, html etc.).
When the user will open this attachment from XStudio, XStudio will recognise the double extension (.html + .zip) so will start by unzipping the file in a temporary folder then XStudio will open directly the my_report.html file that is included in the zip. Hence you can read an entire complex HTML reports (including images etc.) directly without having to unzip and open manually the right index file.

The expert APIs

In each of these 5 methods implementation you can use any API included in the SDK.
The included APIs include many libraries allowing to:
  • execute processes synchronously or asynchronously,
  • monitor a task using a timer,
  • parse XML files,
  • download files from shared folders/ftp server,
  • add attachments to the test case execution in XStudio
  • many utilities (conversion, file/date/time manipulation, etc.)
In addition, some methods allow accessing data related to the whole campaign being run. You should not need to use those methods but in particular cases this may be useful.

Identifiers


int getCampaignSessionId()
Returns the id of the campaign session being executed.

int getInstanceId()
Returns the instance id of the thread being executed. An instance is the campaign session/agent association.

Helpers to parse objects passed


Test's attributes
Vector<String> getStringAttributeValues(Vector>CTestAttribute> attributes, String attributeName)
String getStringAttributeValue(Vector>CTestAttribute> attributes, String attributeName)
Vector<Integer> getIntegerAttributeValues(Vector>CTestAttribute> attributes, String attributeName)
Integer getIntegerAttributeValue(Vector>CTestAttribute> attributes, String attributeName)
boolean getBooleanAttributeValue(Vector>CTestAttribute> attributes, String attributeName)

Test case's params
String getStringParamValue(String formName, String paramName, int index)
int getIntegerParamValue(String formName, String paramName, int index)
Double getDoubleParamValue(String formName, String paramName, int index)
boolean getBooleanParamValue(String formName, String paramName, int index)

Campaign session content


Vector<CTestExecution> getTestExecutionVector()
Returns the complete list of tests and test cases included in the campaign session being executed.
Vector<Integer> getTestIdVector()
Returns the complete list of test ids that are going to be executed in this campaign session.
Vector<Integer> getTestcaseIdVector()
Returns the complete list of test case ids that are going to be executed in this campaign session.

Defects


Vector<CIdAndNameDescriptor> getTestDefects(int testId)
Returns the ids and names of all bugs attached to the test passed as argument.

Attachments


Vector<CIdAndNameDescriptor> getTestAttachments(int testId)
Returns the ids and names of all files attached to the test passed as argument.
The class CIdAndNameDescriptor includes 2 getter methods getId() and getName().
Vector<CIdAndNameDescriptor> getTestcaseAttachments(int testcaseId)
Returns the ids and names of all files attached to the test case passed as argument.

Test cases custom fields


Vector<CNameAndValueDescriptor> getTestcaseBooleanCustomFieldsHashtable(int testcaseId)
Returns the names and values of all the boolean custom fields of the test case passed as argument.
The class CNameAndValueDescriptor includes 2 getter methods getName() and getValue().
Vector<CNameAndValueDescriptor> getTestcaseIntegerCustomFieldsHashtable(int testcaseId)
Returns the names and values of all the integer custom fields of the test case passed as argument.
Vector<CNameAndValueDescriptor> getTestcaseStringCustomFieldsHashtable(int testcaseId)
Returns the names and values of all the string custom fields of the test case passed as argument.
Vector<CNameAndValueDescriptor> getTestcaseHtmlCustomFieldsHashtable(int testcaseId)
Returns the names and values of all the formatted string custom fields of the test case passed as argument.
Vector<CNameAndValueDescriptor> getTestcaseStringChoiceCustomFieldsHashtable(int testcaseId)
Returns the names and values of all the drop-down custom fields of the test case passed as argument.

SUT custom fields


Vector<CNameAndValueDescriptor> getSutBooleanCustomFieldsVector()
Returns the names and values of all the boolean custom fields of the SUT being tested.
The class CNameAndValueDescriptor includes 2 getter methods getName() and getValue().
Vector<CNameAndValueDescriptor> getSutIntegerCustomFieldsVector()
Returns the names and values of all the integer custom fields of the SUT being tested.
Vector<CNameAndValueDescriptor> getSutStringCustomFieldsVector()
Returns the names and values of all the string custom fields of the SUT being tested.
Vector<CNameAndValueDescriptor> getSutHtmlCustomFieldsVector()
Returns the names and values of all the formatted string custom fields of the SUT being tested.
Vector<CNameAndValueDescriptor> getSutStringChoiceCustomFieldsVector()
Returns the names and values of all the drop-down custom fields of the SUT being tested.

Build returned messages including rich-text and embedding images generated on-the-fly

If your test-automation framework generates some images automatically (i.e. screenshots), you can of course upload the images as attachment of the testcase execution using the standard addTestcaseMessageAttachment.

You can also reference this image within your rich-text messages.
In your launcher, just do the following:

i) upload the images as usual:
addTestcaseMessageAttachment(new File("C:\\test_repository\\data\\screenshot.png"))

ii) Insert a message referencing the image using the "OTF_" prefix:
executionSteps.add(new CExecutionStep(CCalendarUtils.getCurrentTime(),
RESULT_INFO, "This is a [b]nice/embedded[/b] image: [img]OTF_screenshot.png[/img]"));

Writing the configuration template


The configuration template file is an XML file that describes the form displayed to the user when he creates the execution configurations.
All the information you are going to describe here are going to be filled by the user and are going to be passed to the launcher at run time.
The user will be able to create some configuration once and reuse them later.
From the launcher you can get those values by calling the methods getXXXParamValue()
.