Showing posts with label xqual. Show all posts
Showing posts with label xqual. Show all posts

Wednesday, 11 November 2009

SalomeToXQual.pl


#!/usr/bin/perl -w


=head1 NAME


Read in Salomé_TMF exported .xml file.
Choose a Test Plan and set of tests to import.
Write out .xml or .csv that XQual can read.


=head1 SYNOPSIS


Salomé project INX8000-OLC
-> Data exchange format -> Export xml xml_export_olc_all.xml (file saved to Desktop)


Read in that file (as XML).
Read in Famille Nom, offer user choice of Famille Nom and/or SuiteTest Nom to choose.
Read in all wanted particular items matching Famille and SuiteTest.
Save to ; delimited .csv (awkward with excel) and " " indented for "with testplan" option.
Write fields out (some values merged, others generated/hardcoded).


=head1 SPEC


I tried doing this Salome_TMF export -> excel -> .csv -> XStudio.
But excel .csv output is annoyingly limited.
Possibly could get closer with openoffice but feh.


=head2 INPUT Salome_TMF .xml format




.


OLC
.

SU_A2 OLC
Area for tests which are parts of this phase of testing


SU_A2


=head2 Mapping Salomé .xml/.xls fields to XStudio format


A+BI+BJ (projet+id_famille+Nom) category; (set to 4) priority; (set to "") canonicalPath;(set to test script name) path
BM (id_test) index; (set to 1) implemented; BP (Nom) name;
CK+CL+CM step;param1,param2,...; CN check1,check2,...


=head2 XQual XStudio .csv and .xml import format


Format .xml or .csv or .csv with test plan
The .xml format (detailed below) for import I have not tested.
The IDs are in the .xml, how would we decide on those when importing?
So I'm using use .csv to import.


Tests and Testcases (without testplan)
category;implemented;priority;canonicalPath;path;indexTestcase1,indexTestcase2,...


OR Tests and Testcases (with testplan>, indentation spaces matter)
category;priority;canonicalPath;path(script name)
index;implemented;name
step;param1,param2,...;check1,check2,...


=head2 OUTPUT XStudio .csv in format


# the indentation whitespace matters
# test path must begin with /
# numeric fields must be numeric
# ColdRestartsOfTCS.tcl is the script for this example (one script for all test cases in category)


SU_A2;4;TestCanPathIsScriptNameMaybe;/TestPath/ColdRestartsOfTCS


1159;0;Cold Restarts of TCS with no input power


Action_1075 A0 Check bringup wait time for WSS;;"20 minutes, or longer. [HLD.OPTA.BLK_E.0010]"
Action_1076,A1,There is no optical output during this startup phase [Bringup slides] & R[HLD.OPTA.BLK_E.0011];;Using a power meter confirm
Action_1077,A2,"After warm-up phase complete if BI available, manufacture and calibration phase available then the following three tasks commence \n1) CC TX - CC laser and APR ON \n2) CC RX - Coarse RX Loop starts \n3) Data plane 1st powers and warms up \n";;Confirm these tasks commence.
Action_1090,A3,###############################################################################################################################################################################################################################################################;;Due to the fact that only part of the functionally is available cannot see without that stubbing that the bring can complete. This step attempts to highlight this issue.


=head2 running


I'm using cygwin's perl for now. By default XML/LibXML.pm is available.


#!/cygdrive/c/Perl/bin/perl -w
$ perl c:/Perl/scripts/SalomeToXQual.pl
Can't locate XML/LibXML.pm in @INC (@INC contains: c:/Perl/site/lib c:/Perl/lib .) at c:/Perl/scripts/SalomeToXQual.pl line 283.


=head2 DESIGN


http://perl-xml.sourceforge.net/faq/#quick_choice


=cut


use strict;


use XML::LibXML;


# defaults
my $filename = shift;
my $ofilename;
my $match = shift;
$filename="c:/Documents and Settings/james.coleman/Desktop/xml_export_olc_all.xml" if (!defined $filename);
#$match = "SU_A2 OLC" if (undef $match);
$match = "" if (!defined($match));
my $matchhash = $match;
$matchhash =~ s/[^\w\d]/_/g;
if (!defined $ofilename) {
$ofilename=$filename;
$ofilename =~ s/.xml$//;
$ofilename .= "_${matchhash}.csv";
}
print "$0 filename=$filename ofilename=$ofilename match=$match\n";


my $parser = XML::LibXML->new();
my $doc = $parser->parse_file($filename);


# TODO user passes in filename [optional outfile] [optional regexp/list of famille to take]
#my $c = $#ARGV + 1;
#print FILE "ARGC=$c\n";
#foreach my $i (0 .. $#ARGV) {
# print FILE "arg ARGV[$i]=$ARGV[$i]\n";
#}


open(FILE, '>', $ofilename) or die $!;


# ct = current test
my %ct;
my ($category,$priority,$canonicalPath,$path);
my ($index,$impl,$name);
my ($step,$param1,$param2,$check1,$check2);


$ct{'category'} = "0xdeadbeef";
$ct{'path'} = "0xdeadbeef";
$ct{'index'} = "0xdeadbeef";
$ct{'name'} = "0xdeadbeef";
$ct{'step'} = "0xdeadbeef";
$ct{'param1'} = "";
$ct{'param2'} = "";
$ct{'check1'} = "";
$ct{'check2'} = "";


$ct{'priority'} = 4;
$ct{'canonicalPath'} = "";
$ct{'impl'} = 0;


$ct{'project'} = $doc->findnodes('//Nom')->to_literal;


foreach my $f ($doc->findnodes('//Familles/Famille')) {
my($n) = $f->findnodes('./Nom');
print $n->to_literal, "\n";


next if ($match eq "");


$_ = $n->to_literal;
if (m/$match/) {
print "MATCH ", $n->to_literal, "\n";
$ct{'category'} = $n->to_literal;
$ct{'cathash'} = $ct{'category'};
$ct{'cathash'} =~ s/ /_/g;
### PATH MUST BEGIN WITH /
$ct{'path'} = "/IntuneTest/".$ct{'cathash'}."TestScript";


#my $s = $f->findnodes('./SuiteTests');
#print "Suite: ", $s->to_literal, "\n";
my($tests) = $f->findnodes('.//Tests');
#print "Tests: ", $tests->to_literal, "\n";


#category;priority;canonicalPath;path(script name)
# index;implemented;name
# step;param1,param2,...;check1,check2,...
print FILE "\n$ct{'category'};$ct{'priority'};$ct{'canonicalPath'};$ct{'path'}\n";


foreach my $t ($tests->findnodes('.//Test')) {


my @a0 = $t->attributes();
#$ct{'index'} = $t->getAttribute('test_id');
$ct{'index'} = $a0[0]->getValue();
$ct{'index'} =~ s/[^0-9]//g;


my $tn = $t->findnodes('./Nom');
$ct{'name'} = $tn->to_literal;


# no test name in .csv :( NO, actually yuou can do it (and must I think) - had a different problem
# AND two \n's are VITAL!
print FILE "\n $ct{'index'};$ct{'impl'};$ct{'name'}\n\n";
#print FILE "\n $ct{'index'};$ct{'impl'}\n\n";
# place test name in 1st test step
#print FILE " $ct{'name'};;\n";

### TODO Test Description not included
# my $desc = $tests->findnodes('./Description')) {
foreach my $step ($t->findnodes('./TestManuel/ActionTest')) {
my @stepa0 = $step->attributes();
$ct{'step'} = $stepa0[0]->getValue();
$ct{'step'} .= "," . $step->findnodes('./Nom')->to_literal;
$ct{'step'} .= "," . $step->findnodes('./Description')->to_literal;
$ct{'check1'} = $step->findnodes('./ResultAttendu')->to_literal;
#print FILE " $ct{'step'};$ct{'param1'},$ct{'param2'},;$ct{'check1'},$ct{'check2'},\n";
$ct{'step'} =~ s/[;,]/_/g;
$ct{'param1'} =~ s/[;,]/_/g;
$ct{'check1'} =~ s/[;,]/_/g;
print FILE " $ct{'step'};$ct{'param1'};$ct{'check1'}\n";
}
}
}
}


my $ts = time();


close FILE;


Friday, 11 September 2009

a tcl launcher for XQual XStudio ...

It was trivial to modify the XQual XStudio launcher for perl to work for tcl (ActiveTcl).
It is working for very simple tcl scripts with ActiveTcl 8.5 (and with modification with 8.4).

Change the perl CLauncherImpl.java thusly:
s/perl/tcl/gi; s/\.pl/\.tcl/g;
Tcl interpreter: C:/Tcl/bin/tclsh85.exe

It implements the same test interface as XStudio perl (and other):
* Test generates log.txt with lines including [Success] or [Failure] or [Log].
* Test is deemed complete when a file test_completed.txt is created.

Note for XQual XStudio:
* tools seems very nice to use, developer good - closed source though ...
* source code for test launchers is provided in XAgent and XStudio dir trees.
* there doesn't seem to be a Developers Guide though it is referred to (there are javadocs)
* a launcher has 4 files (e.g. for tcl) tcl.jar and tcl.xml in launchers/, tcl/CLauncherImpl.java and buildTclLauncher.bat in src/*/ and build/

I've been evaluating using XQual XStudio as a test invoking tool. As opposed to Salome_tmf.
http://www.xqual.com/
http://xqual.freeforums.org/evaluating-test-tools-xqual-xstudio-salome-tmf-t349.html


Files here:
http://www.dspsrv.com/~jamesc/torture/work/tool_xqual_xstudio/

/*
+----------------------------------------------------------------------+
| Class: CLauncher |
| |
| Developer: Eric Gavaldo (egavaldo@xqual.com) |
| Jumbo |
| James Coleman (jamesc@dspsrv.com) |
| |
+----------------------------------------------------------------------+
*/

/*
This file was created by changing the perl CLauncherImpl.java
s/perl/tcl/gi; s/\.pl/\.tcl/g;
It has been tested with ActiveTcl, tcl interpreter: C:/Tcl/bin/tclsh85.exe

It implements the same test interface as XStudio perl (and other).
Test generates log.txt with lines including [Success] or [Failure]
or [Log]. Test is deemed complete when a file test_completed.txt is created.
*/

package com.xqual.xlauncher.tcl;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Vector;

import com.xqual.xagent.launcher.CExecutionStep;
import com.xqual.xagent.launcher.CLauncher;
import com.xqual.xagent.launcher.CParamParsingException;
import com.xqual.xagent.launcher.CReturnStatus;
import com.xqual.xagent.launcher.runner.CRunner;
import com.xqual.xagent.launcher.runner.IRunner;
import com.xqual.xcommon.CAttribute;
import com.xqual.xcommon.IConstantsResults;
import com.xqual.xlauncher.CTimeoutListener;

/**
* The CLauncherImpl implementation of ILauncher for Tcl.
* @author egavaldo & jumbo & jamesc
*/
public class CLauncherImpl extends CLauncher implements IConstantsResults {

// +==============================================================+
// | Attributes |
// +==============================================================+

static final String TRACE_HEADER = "{tcl } ";

// parameters impacting executing at run time set by the test operator
private String testRootPath;
private int timeout = 600;
private String tclInstallPath;
private File tclInterpreter;

private File workingDir;

private static final String TCL_INTERPRETER_EXE = "tclsh85.exe";

// +==============================================================+
// | Constructors |
// +==============================================================+

public CLauncherImpl() {
super(TRACE_HEADER);
}

// +==============================================================+
// | Methods |
// +==============================================================+

public CReturnStatus initialize(int sutId, String sutName, String sutVersion) {
setSutDetails(sutId, sutName, sutVersion);

// check the configuration sent by the manager
printConfiguration();

Vector executionSteps = new Vector();
try {
// retrieve the parameters we need
testRootPath = getStringParamValue("General", "Test root path");
timeout = getIntegerParamValue("General", "Asynchronous timeout (in seconds)");

tclInstallPath = getStringParamValue("Tcl", "Tcl install path");
tclInterpreter = new File(tclInstallPath + "\\" + TCL_INTERPRETER_EXE);
} catch (CParamParsingException e) {
traceln(LOG_PRIORITY_SEVERE, "parsing error during initialization");
executionSteps.add(new CExecutionStep(RESULT_FAILURE, "Exception during initialize: " + e.getMessage()));
return new CReturnStatus(RESULT_FAILURE, executionSteps);
}
return new CReturnStatus(RESULT_SUCCESS, executionSteps);
}

public CReturnStatus preRun(int testId, String testPath, String testName, Vector attributes) {
traceln(LOG_PRIORITY_INFO, "preRun testId=" + testId + " testPath=" + testPath + ":" + testName + "...");
Vector executionSteps = new Vector();
return new CReturnStatus(RESULT_SUCCESS, executionSteps);
}

public CReturnStatus run(int testId, String testPath, String testName, int testcaseIndex) {
traceln(LOG_PRIORITY_INFO, "run testId=" + testId + " testPath=" + testRootPath + "/" + testPath + "/" + testName + " testcaseIndex=" + testcaseIndex + "...");
Vector executionSteps = new Vector();

String scriptParentFolderPath = testRootPath + "/" + testPath + "/";
workingDir = new File(scriptParentFolderPath);

// +------------------------------------+
// | Interpret the script
// +------------------------------------+
CRunner tclRunner = new CRunner("[" + testId + "] "+ testPath + ":" + testName + "." + testcaseIndex,
tclInterpreter.toString() + " " + testRootPath + "/" + testPath + "/" + testName + ".tcl " +
"/debug " +
"/testcaseIndex=" + testcaseIndex,
workingDir);
short result = tclRunner.requestAction(IRunner.START_PROCESS, IRunner.DO_NOT_WAIT_END_OF_EXECUTION);
if (result == RESULT_FAILURE) {
executionSteps.add(new CExecutionStep(RESULT_FAILURE, "script interpretation failed"));
return new CReturnStatus(RESULT_FAILURE, executionSteps);
}

// to check if the execution completed correctly, we need to check if the "test_completed.txt" has been created
short resultTimeout = CTimeoutListener.waitForFile(new File(workingDir + "/test_completed.txt"), timeout);
if (resultTimeout != RESULT_SUCCESS) {
executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "timeout of " + timeout + " seconds to execute the test case expired"));
return new CReturnStatus(RESULT_FAILURE, executionSteps);
}

return parseResultFile(executionSteps);
}

public CReturnStatus postRun(int testId, String testPath, String testName) {
traceln(LOG_PRIORITY_INFO, "postRun testId=" + testId + " testPath=" + testPath + ":" + testName + "...");
Vector executionSteps = new Vector();
executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "postRun: succeeded"));
return new CReturnStatus(RESULT_SUCCESS, null);
}

public CReturnStatus terminate() {
Vector executionSteps = new Vector();
executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "Terminate"));
return new CReturnStatus(RESULT_SUCCESS, executionSteps);
}

// +--------------------------+
// ¦ Utilities ¦
// +--------------------------+

private CReturnStatus parseResultFile(Vector executionSteps) {
// parse the result file to get the result and the execution steps
File resultFile = new File(workingDir + "/log.txt");
if (!resultFile.exists()) {
traceln(LOG_PRIORITY_SEVERE, "Result file not found!");
executionSteps.add(new CExecutionStep(RESULT_FAILURE, "run: result file not found!"));
return new CReturnStatus(RESULT_FAILURE, executionSteps);
} else {
executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "run: result file found"));
}

String line, message;
boolean errorDetected = false;

try {
FileInputStream fileInputStream = new FileInputStream(resultFile);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));

while ((line = bufferedReader.readLine()) != null) {
line = line.trim();
System.out.println(">" + line);
if (line.indexOf("[Success]")>=0) {
message = line.substring(10, line.length()); // [Success] length = 9
executionSteps.add(new CExecutionStep(RESULT_SUCCESS, message));

} else if (line.indexOf("[Failure]")>=0) {
message = line.substring(10, line.length());
executionSteps.add(new CExecutionStep(RESULT_FAILURE, message));
errorDetected = true;

} else if (line.indexOf("[Log]")>=0) {
message = line.substring(6, line.length());
executionSteps.add(new CExecutionStep(RESULT_UNKNOWN, message));

} else {
//traceln(LOG_PRIORITY_SEVERE, "unknown tag!");
}
}

} catch (Exception e) {
traceln(LOG_PRIORITY_SEVERE, "exception whle parsing the result file: " + e);
executionSteps.add(new CExecutionStep(RESULT_FAILURE, "Exception whle parsing the result file: " + e));
errorDetected = true;
}

if (errorDetected) {
return new CReturnStatus(RESULT_FAILURE, executionSteps);
} else {
return new CReturnStatus(RESULT_SUCCESS, executionSteps);
}
}
}