{"id":491,"date":"2012-03-28T15:21:55","date_gmt":"2012-03-28T19:21:55","guid":{"rendered":"http:\/\/www.jetmore.org\/john\/blog\/?p=491"},"modified":"2012-05-11T15:14:07","modified_gmt":"2012-05-11T19:14:07","slug":"missing-testlink-api-function-getexecutionresults","status":"publish","type":"post","link":"https:\/\/www.jetmore.org\/john\/blog\/2012\/03\/missing-testlink-api-function-getexecutionresults\/","title":{"rendered":"Missing TestLink API Function &#8211; getExecutionResults()"},"content":{"rendered":"<p>I have finally come to terms with the TestLink API and have bashed out an automated test runner written in perl (which I hope to clean up and post in the next few days, there don&#8217;t seem to be many (or any) examples of this in the wild).<\/p>\n<p>After getting nightly automated testing running, I wanted a very simple script which would, for each test case in a given test plan, compare the last and the second to last result and print a warning if they were different.  Long term I will have better automated reporting, but our test script library is still so new that it&#8217;s not really news that a lot of them are failing.  What would be news is if a specific test case passed two nights ago but failed last night.<\/p>\n<p><!--more--><\/p>\n<p>This seemed like a really easy thing to do, but I couldn&#8217;t find an API function to support it.  The closest thing I could find was <code>getLastExecutionResult()<\/code>, but that only gave me the last execution, it didn&#8217;t give me the execution history I needed.  I also could have leveraged the fact that <code>getTestCasesForTestPlan()<\/code> includes each case&#8217;s last execution status to have done in-place alarming if the new status didn&#8217;t match the old status, but I felt like that would limit my ability to expand reporting in the future.  I toyed with the idea of getting the info out of the DB directly, but decided instead of just implement the API function I needed.  It&#8217;s mostly a copy of <code>getLastExecutionResult()<\/code>, but it has an added parameter <code>numexecs<\/code> which allows you to specify how many executions to return.<\/p>\n<p>I hope to wrap all of these TestLink patches up into a better place at some point in the future, but for now it feels better to just get the code out where Google can find it as fast as possible.<\/p>\n<p>Here&#8217;s the patch for adding the <code>getExecutionResults()<\/code> function:<\/p>\n<blockquote><p><strong>Update 2012-05-08<\/strong>: There&#8217;s a <a href=\"https:\/\/github.com\/jetmore\/TestLink-Misc\/blob\/master\/patches\/getExecutionResults.patch\">real, usable-with-patch-command patch file for this change<\/a> available at the <a href=\"https:\/\/github.com\/jetmore\/TestLink-Misc\">github repo I started for my TestLink changes<\/a>.<\/p><\/blockquote>\n<pre class=\"brush: diff; title: ; notranslate\" title=\"\">\r\n--- xmlrpc.class.php\t(revision 268)\r\n+++ xmlrpc.class.php\t(revision 270)\r\n@@ -176,6 +176,7 @@\r\n \tpublic static $testSuiteNameParamName = &quot;testsuitename&quot;;\r\n \tpublic static $timeStampParamName = &quot;timestamp&quot;;\r\n     public static $titleParamName = &quot;title&quot;;\r\n+    public static $numexecsParamName = &quot;numexecs&quot;;\r\n \r\n \r\n     public static $urgencyParamName = &quot;urgency&quot;;\r\n@@ -255,6 +256,7 @@\r\n \t                            'tl.getBuildsForTestPlan' =&gt; 'this:getBuildsForTestPlan',\r\n \t                            'tl.getLatestBuildForTestPlan' =&gt; 'this:getLatestBuildForTestPlan',\t\r\n                                 'tl.getLastExecutionResult' =&gt; 'this:getLastExecutionResult',\r\n+                                'tl.getExecutionResults' =&gt; 'this:getExecutionResults',\r\n \t                            'tl.getTestSuitesForTestPlan' =&gt; 'this:getTestSuitesForTestPlan',\r\n \t                            'tl.getTestSuitesForTestSuite' =&gt; 'this:getTestSuitesForTestSuite',\r\n \t                            'tl.getTestCasesForTestSuite'\t=&gt; 'this:getTestCasesForTestSuite',\r\n@@ -1220,8 +1222,78 @@\r\n \r\n \t\treturn $maxbuild;\r\n \t}\r\n-\t\r\n+\r\n \t\/**\r\n+\t * Gets the result of LAST EXECUTION for a particular testcase \r\n+\t * on a test plan, but WITHOUT checking for a particular build\r\n+\t *\r\n+\t * @param struct $args\r\n+\t * @param string $args[&quot;devKey&quot;]\r\n+\t * @param int $args[&quot;tplanid&quot;]\r\n+\t * @param int $args[&quot;testcaseid&quot;]: optional, if does not is present           \r\n+\t *                                 testcaseexternalid must be present\r\n+\t *\r\n+\t * @param int $args[&quot;testcaseexternalid&quot;]: optional, if does not is present           \r\n+\t *                                         testcaseid must be present\r\n+\t * @param int $args[&quot;numexecs&quot;]: optional.  If set, number of cases to\r\n+\t *                               return.  If unset, all will be returned\r\n+\t *\r\n+\t * @return mixed $resultInfo\r\n+\t *               if execution found, array with these keys:\r\n+\t *               id (execution id),build_id,tester_id,execution_ts,\r\n+\t *               status,testplan_id,tcversion_id,tcversion_number,\r\n+\t *               execution_type,notes.\r\n+\t *\r\n+\t *               if test case has not been execute,\r\n+\t *               array('id' =&gt; -1)\r\n+\t *\r\n+\t * @access public\r\n+\t *\/\r\n+\tpublic function getExecutionResults($args)\r\n+\t{\r\n+\t\t$operation=__FUNCTION__;\r\n+\t\t$msg_prefix=&quot;({$operation}) - &quot;;\r\n+\t\t\r\n+\t\t$this-&gt;_setArgs($args);\r\n+\t\t$resultInfo = array();\r\n+\t\t$status_ok=true;\r\n+\t\t\r\n+\t\t\/\/ Checks are done in order\r\n+\t\t$checkFunctions = array('authenticate','checkTestPlanID','checkTestCaseIdentity');\r\n+\t\t\r\n+\t\t$status_ok=$this-&gt;_runChecks($checkFunctions,$msg_prefix) &amp;&amp; \r\n+\t\t           $this-&gt;_checkTCIDAndTPIDValid(null,$msg_prefix) &amp;&amp;\r\n+\t\t           $this-&gt;userHasRight(&quot;mgt_view_tc&quot;);       \r\n+\t\t\r\n+\t\tif( $status_ok )\r\n+\t\t{\r\n+\t\t\t\/\/ get all, then return last\r\n+\t\t\t$sql = &quot; SELECT * FROM {$this-&gt;tables['executions']} &quot; .\r\n+\t\t\t       &quot; WHERE testplan_id = {$this-&gt;args[self::$testPlanIDParamName]} &quot; .\r\n+\t\t\t       &quot; AND tcversion_id IN (&quot; .\r\n+\t\t\t       &quot; SELECT id FROM {$this-&gt;tables['nodes_hierarchy']} &quot; .\r\n+\t\t\t       &quot; WHERE parent_id = {$this-&gt;args[self::$testCaseIDParamName]})&quot; .\r\n+\t\t\t       &quot; ORDER BY id DESC&quot;;\r\n+\r\n+\t\t\t$limit   = $this-&gt;args[self::$numexecsParamName] &gt; 0 ? $this-&gt;args[self::$numexecsParamName] : -1;\r\n+\t\t\t$records = $this-&gt;dbObj-&gt;get_recordset($sql, null, $limit);\r\n+\t\t\t\r\n+\t\t\tif(null == $records)\r\n+\t\t\t{\r\n+\t\t\t\t\/\/ has not been executed\r\n+\t\t\t\t\/\/ execution id = -1 =&gt; test case has not been runned.\r\n+\t\t\t\t$resultInfo[]=array('id' =&gt; -1);\r\n+\t\t\t} \r\n+\t\t\telse\r\n+\t\t\t{\r\n+\t\t\t\t$resultInfo = $records;\r\n+\t\t\t}\r\n+\t\t}\r\n+\t\t\r\n+\t\treturn $status_ok ? $resultInfo : $this-&gt;errors;\r\n+\t}\r\n+\r\n+\t\/**\r\n      * Gets the result of LAST EXECUTION for a particular testcase \r\n      * on a test plan, but WITHOUT checking for a particular build\r\n      *\r\n<\/pre>\n<p>This function suffers from a few warts, but they are ones mostly inherited from <code>getLastExecutionResult()<\/code>.  If I were to polish this up (beyond my normal TestLink API beefs like some sort of standardized return format), I would definitely add optional <code>buildid<\/code> and <code>platformid<\/code> parameters so you could narrow down the executions you&#8217;re looking for even more.  But that&#8217;s a problem for another day&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I have finally come to terms with the TestLink API and have bashed out an automated test runner written in perl (which I hope to clean up and post in the next few days, there don&#8217;t seem to be many &hellip; <a href=\"https:\/\/www.jetmore.org\/john\/blog\/2012\/03\/missing-testlink-api-function-getexecutionresults\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[5],"tags":[8,9,14],"_links":{"self":[{"href":"https:\/\/www.jetmore.org\/john\/blog\/wp-json\/wp\/v2\/posts\/491"}],"collection":[{"href":"https:\/\/www.jetmore.org\/john\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jetmore.org\/john\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jetmore.org\/john\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jetmore.org\/john\/blog\/wp-json\/wp\/v2\/comments?post=491"}],"version-history":[{"count":10,"href":"https:\/\/www.jetmore.org\/john\/blog\/wp-json\/wp\/v2\/posts\/491\/revisions"}],"predecessor-version":[{"id":684,"href":"https:\/\/www.jetmore.org\/john\/blog\/wp-json\/wp\/v2\/posts\/491\/revisions\/684"}],"wp:attachment":[{"href":"https:\/\/www.jetmore.org\/john\/blog\/wp-json\/wp\/v2\/media?parent=491"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jetmore.org\/john\/blog\/wp-json\/wp\/v2\/categories?post=491"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jetmore.org\/john\/blog\/wp-json\/wp\/v2\/tags?post=491"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}