Oct
15
2008

Q. How do I integrate watir with TestLink?

A. This requires several hacks and use of the developer API …

The first step to integrating these products is to download and install
TestLink 1.8.0 BETA2
Once finished, add the TestLink API BETA

Their blog has installation instructions for both.

Regarding the API there are a number of changes you will need to ensure:
1. create api_developer_keys table using the api_sql_changes.sql included with the API
2. create an api developer key in your new api_developer_keys table
3. update the api.const.inc.php database constants
4. $ chmod -R 755 api/
5. change the paths to relevant libraries in xmlrpc.php, mine looks like this:

change xmlrpc.php
/** 
 * IXR is the class used for the XML-RPC server 
 */
require_once(dirname(__FILE__) . "/../third_party/xml-rpc/class-IXR.php");
require_once("api.const.inc.php");
// require_once("APIErrors.php");
require_once(dirname(__FILE__) . "/../config.inc.php");
require_once(dirname(__FILE__) . "/../lib/functions/common.php");
require_once(dirname(__FILE__) . "/../lib/functions/testproject.class.php");
require_once(dirname(__FILE__) . "/../lib/functions/testcase.class.php");
require_once(dirname(__FILE__) . "/../lib/functions/testsuite.class.php");

You can be creative as you want with the API. The way I implemented this, was to change the test execution template to allow corresponding test cases to be executed within watir such that the following calls are made:

TestLink -> test_harness.php -> test_harness.rb -> test_suite.rb

I had to first modify the TestLink gui/templates/execute/execSetResults.tpl template as per the following (approx line 544):

   {if $tc_exec.can_be_executed}
      {include file="execute/inc_exec_controls.tpl"
               args_input_enable_mgmt=$input_enabled_disabled
               args_tcversion_id=$tcversion_id
               args_webeditor=$gui->exec_notes_editors[$tc_id]
               args_labels=$labels}
      <!--ADDED BY tim.koopmans@90kts.com-->
      {include file="execute/inc_exec_watir.tpl"}

I then added a new TestLink template in gui/templates/execute/inc_exec_watir.tpl as per the following:

{* 
TestLink Open Source Project - http://testlink.sourceforge.net/
$Id: inc_exec_watir.tpl,v 0.1 2008/10/15 05:03:53 $
Purpose: draw execution controls for watir based test cases
Author : tim.koopmans@90kts.com
*}	
      {assign var="ResultsStatusCode" value=$tlCfg->results.status_code}
  		<table class="invisible">
  		<tr>
  			<th rowspan="2" style="text-align: center;">
  				<div class="title">Watir Test Case {$tc_id}
<a href="http://localhost/~koops/testlink/watir/test_harness.php?name={$tc_exec.name}&id={$gui->tcasePrefix}{$tc_exec.tc_external_id}&tcid={$tc_id}">Execute &rarr;</a>
  			</th>
  			<td valign="top" style="width: 30%;">			
    			</td>
    		</tr>
  		</table>

This essentially adds a new link to the test execution screen which will call a test_harness from PHP using a system call. The screen mod looks like this:
The PHP harness which it calls is located in watir/test_harness.php and looks like the following:

<?php
  if (isset($_GET["name"])) $name = $_GET["name"];
  if (isset($_GET["id"])) $id = $_GET["id"];
  if (isset($_GET["tcid"])) $tcid = $_GET["tcid"];
  print "Executing watir test case id: $tcid<br/>";
  system("ruby /Users/koops/Sites/testlink/watir/test_harness.rb $id $tcid");
?>

The purpose of this is to launch a test_harness client in Ruby passing it the client ID and test case ID required for execution. This client is based on the API examples and it could have been written in PHP, but I felt more comfortable with Ruby. So there is a little double handling here which could be improved… The Ruby harness it calls is located in watir/test_harness.rb and looks like the following:

require 'xmlrpc/client'
 
class TestlinkAPIClient  
  # substitute your server URL Here
  SERVER_URL = "http://localhost/~koops/testlink/api/xmlrpc.php"
 
  def initialize(dev_key)
    @server = XMLRPC::Client.new2(SERVER_URL)
    @devKey = dev_key
  end
 
  def reportTCResult(tcid, tpid, status)
    args = {"devKey"=>@devKey, "tcid"=>tcid, "tpid"=>tpid, "status"=>status}
    @server.call("tl.reportTCResult", args)
  end
 
  def getProjectIDByClientID(clientid)
    args = {"devKey"=>@devKey}
    result = @server.call("tl.getProjects", args)
    result.each do |project| 
      return projectid = project["id"] if project["name"] =~ /#{clientid}/
    end
    return 'ERROR: Unable to find project by client id: ' + clientid
  end
 
  def getProjectTestPlanIDByName(testprojectid, testplanname)
    args = {"devKey"=>@devKey, "testprojectid"=>testprojectid}
    result = @server.call("tl.getProjectTestPlans", args)
    result.each do |testplanid, values|
      p values
      return testplanid if values["name"] =~ /#{testplanname}/
    end
    return 'ERROR: Unable to find test plan name by test project id ' + testprojectid   
  end
 
  def getProjectTestPlanID(testprojectid)
    args = {"devKey"=>@devKey, "testprojectid"=>testprojectid}
    result = @server.call("tl.getProjectTestPlans", args)
    result.each do |testplanid, values|
      return testplanid
    end
    return 'ERROR: Unable to find test plan id ' + testprojectid   
  end
 
  def getTestCaseIDByName(testcasename)
    args = {"devKey"=>@devKey, "testcasename"=>testcasename}
    @server.call("tl.getTestCaseIDByName", args)
  end
end
 
# param args
watirid  = ARGV[0] || "ID74278-1"
tcid     = ARGV[1] || 62
clientid = watirid[/[\w\d]+/]
 
# execute watir test suite
stdout = %x[ruby /Users/koops/Sites/testlink/watir/test_suite.rb --name test_#{tcid}]
puts stdout
status = "f"
status = "p" if stdout =~ /0 errors/
 
# substitute your Dev Key Here
client = TestlinkAPIClient.new("f2a979d533cdd9761434bba60a88e4d8")
 
# find a project id by client id [custom]
projectid = client.getProjectIDByClientID("Client #{clientid}")
 
# find the first test plan id for a given project id [native]
tpid = client.getProjectTestPlanID(projectid)
 
result = client.reportTCResult(tcid.to_i, tpid, status)
puts "Run ID: " + result[0]["id"] + "<br/>"

This harness essentially calls a corresponding Test::Unit test suite (by test case ID) and returns the results using the XML-RPC client back into TestLink.
To give you an idea, my example test suite looked like this:

require 'rubygems'
require 'test/unit'
require 'firewatir'
 
include FireWatir
class TestSuite < Test::Unit::TestCase
 
  def setup
    @b=Firefox.new
  end
 
  def test_62
    @b.goto('http://www.google.com')
  end
end

So, stitching it all together, TestLink can call watir test cases using the test case ID which is unique to TestLink and passing it to the relevant test runner or harness in Ruby. Ruby then does the execution and feeds the results (pass/fail) using the XML-RPC client API back into TestLink. You end up with test results being tracked in TestLink and presented (in progress) like this:

It’s all a bit hacky and would be happy for others to progress with this. Just some ideas to get you started =)

Written by Tim Koopmans in: firewatir, watir | Tags:

5 Comments »

  • I am trying to do the same sort of implementation,

    Thanks for the input, good start for me to know how to add automation port to testlink.

    Thanks,
    sathyz

    Comment | October 15, 2008
  • vasuki

    Do we need to learn PHP to integrate testlink with Watir

    Comment | October 16, 2008
  • Natasha

    Hi,

    I am thinking of implementing this soon.

    Had some basic queries:

    1. will I be able to execute tests selectively .. based on some keyword or a whole test plan

    2. Also does it generate user friendly test execution report like a table with test case id, summary and output of execution

    Thanks,
    Natasha

    Comment | November 20, 2008
  • Tim

    Hi Natasha,

    It is possible to execute tests selectively and it also has keyword support. There is also a test execution report available. One shortcoming is that it only shows the results from the last execution in the report (I would like to see whole history) however as this is oss with an active development community I’m sure someone would consider adding that functionality =)

    Comment | November 27, 2008
  • Tim

    Hi Vasuki, testlink is effectively written in PHP, so some understanding to implement hacks like this is required. However to just install and use testlink, very little knowledge is required. The installation is quite simple.

    Comment | November 27, 2008

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress | Aeros Theme | TheBuckmaker.com WordPress Themes