diff options
author | xue <> | 2006-07-07 14:54:15 +0000 |
---|---|---|
committer | xue <> | 2006-07-07 14:54:15 +0000 |
commit | 61bb16ee2e5f0a66234e1575242169a10fde47b5 (patch) | |
tree | 3ee24dcc36ceae2c213130df1ea3d5c9fc110a27 /tests/test_tools/selenium/php | |
parent | 7b84938b1b5964f2274d66e28ba17435924ffe35 (diff) |
Merge from 3.0 branch till 1253.
Diffstat (limited to 'tests/test_tools/selenium/php')
-rw-r--r-- | tests/test_tools/selenium/php/TestRunner.php | 169 | ||||
-rw-r--r-- | tests/test_tools/selenium/php/results.php | 160 | ||||
-rw-r--r-- | tests/test_tools/selenium/php/selenium.php | 477 |
3 files changed, 806 insertions, 0 deletions
diff --git a/tests/test_tools/selenium/php/TestRunner.php b/tests/test_tools/selenium/php/TestRunner.php new file mode 100644 index 00000000..a82ce0dd --- /dev/null +++ b/tests/test_tools/selenium/php/TestRunner.php @@ -0,0 +1,169 @@ + +<html> + +<head> +<HTA:APPLICATION ID="SeleniumHTARunner" APPLICATIONNAME="Selenium" > +<!-- the previous line is only relevant if you rename this + file to "TestRunner.hta" --> + +<!-- The copyright notice and other comments have been moved to after the HTA declaration, + to work-around a bug in IE on Win2K whereby the HTA application doesn't function correctly --> +<!-- +Copyright 2004 ThoughtWorks, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type" /> + +<title>Selenium Functional Test Runner</title> +<link rel="stylesheet" type="text/css" href="<?php echo $base_dir; ?>core/selenium.css" /> +<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-browserdetect.js"></script> +<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-browserbot.js"></script> +<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/prototype-1.4.0.js"></script> +<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/find_matching_child.js"></script> +<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-api.js"></script> +<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-commandhandlers.js"></script> +<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-executionloop.js"></script> +<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-testrunner.js"></script> +<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-logging.js"></script> +<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/selenium-version.js"></script> +<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/scripts/htmlutils.js"></script> +<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/xpath/misc.js"></script> +<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/xpath/dom.js"></script> +<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>core/xpath/xpath.js"></script> +<script language="JavaScript" type="text/javascript" src="<?php echo $base_dir; ?>prado-functional-test.js"></script> +<script language="JavaScript" type="text/javascript"> + function openDomViewer() { + var autFrame = document.getElementById('myiframe'); + var autFrameDocument = getIframeDocument(autFrame); + this.rootDocument = autFrameDocument; + var domViewer = window.open('<?php echo $base_dir; ?>core/domviewer/domviewer.html'); + return false; + } + + Logger.prototype.openLogWindow = function() + { + this.logWindow = window.open( + "<?php echo $base_dir; ?>core/SeleniumLog.html", "SeleniumLog", + "width=600,height=250,bottom=0,right=0,status,scrollbars,resizable" + ); + return this.logWindow; + } + + var post_results_to = "<?php echo $driver; ?>"; + +</script> +</head> + +<body onLoad="start();"> + + <table class="layout"> + <form action="" name="controlPanel"> + + <!-- Suite, Test, Control Panel --> + + <tr class="selenium"> + <td width="25%" height="30%" ><iframe name="testSuiteFrame" id="testSuiteFrame" src="<?php echo $driver; ?>?testSuites" application="yes"></iframe></td> + <td width="50%" height="30%" ><iframe name="testFrame" id="testFrame" application="yes"></iframe></td> + + <td width="25%"> + <table class="layout"> + <tr class="selenium"> + <th width="25%" height="1" class="header"> + <h3><a href="http://selenium.thoughtworks.com" title="The Selenium Project">Selenium</a></h3> + </th> + </tr> + <tr> + <td width="25%" height="30%" id="controlPanel"> + + <fieldset> + <legend>Execute Tests</legend> + + <div> + <input id="modeRun" type="radio" name="runMode" value="0" checked="checked"/><label for="modeRun">Run</label> + <input id="modeWalk" type="radio" name="runMode" value="500" /><label for="modeWalk">Walk</label> + <input id="modeStep" type="radio" name="runMode" value="-1" /><label for="modeStep">Step</label> + </div> + + <div> + <button type="button" id="runSuite" onClick="startTestSuite();" + title="Run the entire Test-Suite"> + <strong>All</strong> + </button> + <button type="button" id="runTest" onClick="runSingleTest();" + title="Run the current Test"> + <em>Selected</em> + </button> + <button type="button" id="continueTest" disabled="disabled" + title="Continue the Test"> + Continue + </button> + </div> + + </fieldset> + + <table id="stats" align="center"> + <tr> + <td colspan="2" align="right">Elapsed:</td> + <td id="elapsedTime" colspan="2">00.00</td> + </tr> + <tr> + <th colspan="2">Tests</th> + <th colspan="2">Commands</th> + </tr> + <tr> + <td class="count" id="testRuns">0</td> + <td>run</td> + <td class="count" id="commandPasses">0</td> + <td>passed</td> + </tr> + <tr> + <td class="count" id="testFailures">0</td> + <td>failed</td> + <td class="count" id="commandFailures">0</td> + <td>failed</td> + </tr> + <tr> + <td colspan="2"></td> + <td class="count" id="commandErrors">0</td> + <td>incomplete</td> + </tr> + </table> + <!-- + <fieldset> + <legend>Tools</legend> + <button type="button" id="domViewer1" onClick="openDomViewer();"> + View DOM + </button> + <button type="button" onClick="LOG.show();"> + Show Log + </button> + + </fieldset> + --> + </td> + </tr> + </table> + </td> + </tr> + + <!-- AUT --> + + <tr> + <td colspan="3" height="70%"><iframe name="myiframe" id="myiframe" src="<?php echo $base_dir; ?>core/TestRunner-splash.html"></iframe></td> + </tr> + </form> + </table> + +</body> +</html>
\ No newline at end of file diff --git a/tests/test_tools/selenium/php/results.php b/tests/test_tools/selenium/php/results.php new file mode 100644 index 00000000..77dab43b --- /dev/null +++ b/tests/test_tools/selenium/php/results.php @@ -0,0 +1,160 @@ +<?php + +class SeleniumTestCaseResult +{ + public $name; + public $commands = array(); + public $result = 'passed'; + public $failures = array(); +} + +class SeleniumTestResult +{ + public $result = 'passed'; + public $totalTime = 0; + public $numTestPasses = 0; + public $numTestFailures = 0; + public $numCommandPasses = 0; + public $numCommandFailures = 0; + public $numCommandErrors = 0; + public $suites = array(); + public $browser = ''; + public $date; + + public function __construct() + { + $this->parse_data(); + $this->browser = $_SERVER['HTTP_USER_AGENT']; + $this->date = time(); + } + + protected function parse_data() + { + $this->result = $_POST['result']; // failed || passed + $this->totalTime = $_POST['totalTime']; + $this->numTestPasses = $_POST['numTestPasses']; + $this->numTestFailures = $_POST['numTestFailures']; + $this->numCommandPasses = $_POST['numCommandPasses']; + $this->numCommandFailures = $_POST['numCommandFailures']; + $this->numCommandErrors = $_POST['numCommandErrors']; + + foreach($_POST['tests'] as $test) + { + $case = new SeleniumTestCaseResult(); + $case->name = $test['testcase']; + $case->commands = $test['commands']; + for($i = 0; $i < count($case->commands); $i++) + { + //$trace = $case->commands[$i]['trace']; + //$trace = html_entity_decode($trace); + //$case->commands[$i]['trace'] = @unserialize($trace); + if($case->commands[$i]['result'] == 'failed') + { + $case->result = 'failed'; + array_push($case->failures, $case->commands[$i]); + } + } + + $this->suites[$case->name] = $case; + } + + } +} + +class SeleniumHtmlReporter +{ + protected $test; + + public function __construct($result) + { + $this->test = $result; + } + + protected function renderHeader() + { + $contents = <<<EOD +<html> +<head> +<title>Functional Test Results</title> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> +<style type="text/css"> +body {font-family:"Verdana";font-weight:normal;color:black;background-color:white;} +.failed { background-color: red; } .error0 { background-color: lightgray; } +.info { padding: 0.5em; margin-top: 1em; color: white; } +.passed { background-color: green; } +.error_case div { padding: 0.3em 0.2em; margin: 0.5em 0; } +.error_msg { padding: 0.5em; border-bottom:1px solid #ccc; } +.msg { color:#c00; } +.function { font-family:"Lucida Console";color: gray;} +.file { border-bottom: 1px dashed gray; } +.env { color: gray; font-size:10pt; padding: 0.5em; } +.odd { background-color: #fee; } +</style> +</head> +<body> +EOD; + return $contents; + } + + public function render() + { + echo $this->renderHeader(); + echo $this->renderBody(); + echo $this->renderFooter(); + } + + protected function renderBody() + { + /* SeleniumTestResult */ + $test = $this->test; + $total = count($test->suites); + $date = @strftime('%Y-%m-%d %H:%M',$test->date); +$contents = <<<EOD +<h1 class="suite">Functional Test Results</h1> +<div class="info {$test->result}"> + <strong>{$total}</strong> test cases completed, + <strong>{$test->numTestPasses}</strong> passes + ({$test->numCommandPasses} commands), and + <strong>{$test->numTestFailures}</strong> fails + ({$test->numCommandErrors} commands). +</div> +<div class="env"> + {$date}, {$test->browser} +</div> +EOD; + $count = 1; + foreach($test->suites as $suite) + { + foreach($suite->failures as $error) + $contents .= $this->getErrorMsg($suite, $error, $count++); + } + + return $contents; + } + + + protected function getErrorMsg($suite, $info, $count) + { + $parity = $count%2==0 ? 'even' : 'odd'; + $command = explode("|",$info['command']); +$msg = <<<EOD + <div class="error_msg {$parity}"> + <strong>#{$count}.</strong> + "<span class="msg">{$info['msg']}</span>" in + <span class="function"> + {$suite->name}::{$command[1]}('{$command[2]}'); + </span> + </div> +EOD; + + return $msg; + } + + protected function renderFooter() + { + return "</body></html>"; + } +} + + +?>
\ No newline at end of file diff --git a/tests/test_tools/selenium/php/selenium.php b/tests/test_tools/selenium/php/selenium.php new file mode 100644 index 00000000..9ad4955b --- /dev/null +++ b/tests/test_tools/selenium/php/selenium.php @@ -0,0 +1,477 @@ +<?php +/** + * Selenium PHP driver. Saves the test command in a "out" queue (in session), + * and for each selenese request, remove the first comand from the "out" queue + * and push the results into the "in" queque (also in session). When "out" queque + * is empty, write the results to disk. + * + * Usage: See ../../example.php + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the BSD License. + * + * Copyright(c) 2004 by Wei Zhuo. All rights reserved. + * + * To contact the author write to {@link mailto:weizhuo[at]gmail[dot]com Wei Zhuo} + * The latest version of PRADO can be obtained from: + * {@link http://prado.sourceforge.net/} + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version $Revision: 1.66 $ $Date: Wed Nov 02 10:13:17 EST 2005 10:13:17 $ + * @package Prado.tests + */ + +/** + * Selenium automatic client runner, + * + * @author Wei Zhuo<weizhuo[at]gmail[dot]com> + * @version $Revision: 1.66 $ $Date: Fri Nov 04 13:20:12 EST 2005 13:20:12 $ + * @package Prado.tests + */ + +require_once(dirname(__FILE__).'/results.php'); + +class SeleniumTestRunner +{ + protected $driver; + protected $base_dir = ''; + + public function __construct($driver=null, $base_dir='../javascript/') + { + if(is_null($driver) && !(php_sapi_name() == 'cli')) + $driver = $_SERVER['SCRIPT_NAME']; + $this->driver = $driver; + $this->base_dir = $base_dir; + } + + public function render() + { + if((php_sapi_name() == 'cli')) return; + $file = dirname(__FILE__).'/TestRunner.php'; + $driver = $this->driver; + + //$base_dir = $this->base_dir; + $base_dir = $driver.'?sr='; + include($file); + } + + public function getDriver() + { + return $this->driver; + } +} + +class SeleniumTestStorage +{ + protected $outputs = array(); + protected $tests = array(); + + public function getTests() + { + return $this->tests; + } + + public function addCommand($test_case_id, $command) + { + $data = array($test_case_id, $command); + array_push($this->outputs, $data); + } + + public function getCommand() + { + return array_shift($this->outputs); + } + + public function addTestCase($command, $trace_details, $test_name, $test_suite) + { + $data = array(0, 0, $command, "", $trace_details, $test_name, $test_suite); + array_push($this->tests, $data); + } +} + +class SeleneseInterpreter +{ + protected $storage; + protected $tracer; + + public function __construct($storage, $tracer) + { + $this->storage = $storage; + $this->tracer = $tracer; + } + + public function getTests() + { + return $this->storage->getTests(); + } + + public function getCommand() + { + $command = $this->storage->getCommand(); + return empty($command) ? "|testComplete|||" : "{$command[1]}<{$command[0]}>"; + } + + public function __call($func, $args) + { + if($func{0} == '_') return; + + $ID = isset($args[0]) ? $args[0] : ""; + $value = isset($args[1]) ? $args[1] : ""; + if(strpos(strtolower($func),'htmlpresent') || strpos(strtolower($func),'htmlnotpresent')) + $ID = htmlspecialchars($ID); + $command = array($func, $ID, $value); + $trace = debug_backtrace(); + + if(is_int(strpos(strtolower($func), 'visible'))) + $this->addCommand(array('pause','500',''),$trace); + + return $this->addCommand($command, $trace); + } + + protected function addCommand($command, $trace) + { + list($trace, $test, $suite) = $this->tracer->getTrace($trace); + $test_id = $this->storage->addTestCase($command, $trace, $test, $suite); + $this->storage->addCommand($test_id, $command); + } +} + +class SeleniumTestTrace +{ + protected $root; + + public function __construct($root) + { + $this->root = $root; + } + + public function getTrace($trace) + { + $group = array_pop($trace); + $info = $trace[3]; + $test = $group['args'][0]->getTestList(); + $i = count($test); + $name = $test[$i-2].'::'.$test[$i-1]; + $suite = $test[0]; + unset($info['object']); + /* + for($i = 0; $i < count($info['args']); $i++) + { + if($info['args'][$i] instanceof TControl) + $info['args'][$i] = $info['args'][$i]->ClientID; + }*/ + $file = str_replace($this->root, '', $info['file']); + $info['file'] = substr($file, 1); + return array($info, $name, $suite); + } +} + +class SimpleSeleniumProxyServer +{ + protected $runner; + protected $int; + protected $result_file; + + public function __construct($runner, $int, $result_file) + { + $this->int = $int; + $this->runner = $runner; + $this->result_file = $result_file; + } + + public function proxy() + { + return $this->int; + } + + + public static function getInstance($root='/', $result_file='results.dat', $base_dir='selenium/') + { + static $instance; + if(!isset($instance)) + { + $storage = new SeleniumTestStorage(); + $tracer = new SeleniumTestTrace($root); + $interpreter = new SeleneseInterpreter($storage, $tracer); + $runner = new SeleniumTestRunner(null, $base_dir); + $instance = new SimpleSeleniumProxyServer($runner, $interpreter, $result_file); + } + $instance->serveResults(); + return $instance; + } + + public function handleRequest() + { + $client = new SeleniumTestRunnerServer($this->int, $this->runner); + $client->serve(); + return true; + } + + public function serveResults() + { + if(isset($_POST['result'])) + { + $result = new SeleniumTestResult(); + $reporter = new SeleniumHtmlReporter($result); + $reporter->render(); + exit(); + } + } + +} + +class SeleniumTestSuiteWriter +{ + protected $suites; + protected $name; + protected $runner; + + function __construct($suites, $name, $runner) + { + $this->suites = $suites; + $this->name = $name; + $this->runner = $runner; + + } + + protected function renderHeader() + { + $contents = <<<EOD +<html> +<head> +<meta content="text/html; charset=UTF-8" http-equiv="content-type"> +<title>Test Suite</title> + +</head> + +<body> + +<table cellpadding="1" + cellspacing="1" + border="1"> + <tbody> + <tr><td><b>{$this->name}</b></td></tr> +EOD; + return $contents; + } + + public function render() + { + echo $this->renderHeader(); + foreach($this->suites as $name => $suite) + { + $file = $suite[0]['trace']['file']; + $file = strtr($file,'\\','/'); + $url = $this->runner->getDriver()."?case={$name}&file={$file}"; + echo "<tr>\n"; + echo "<td><a href=\"{$url}\">{$name}</a></td>\n"; + echo "</tr>\n"; + } + echo $this->renderFooter(); + } + + protected function getJsTraceInfo() + { + $contents = "var prado_trace = {};\n"; + foreach($this->suites as $name => $suite) + { + $name = $name; + $contents .= "prado_trace['{$name}'] = ["; + $cases = array(); + foreach($suite as $testcase) + $cases[] = "'".addslashes(htmlspecialchars(serialize($testcase['trace'])))."'"; + $contents .= implode(",\n", $cases)."];\n\n"; + } + return $contents; + } + + protected function renderFooter() + { + $trace = '';//$this->getJsTraceInfo(); + $contents = <<<EOD + </tbody> + </table> + <script type="text/javascript"> + /*<![CDATA[*/ + $trace + /*]]>*/ + </script> +</body> +</html> +EOD; + return $contents; + } +} + +class SeleniumTestCaseWriter +{ + protected $case; + protected $tests; + + function __construct($case, $tests) + { + $this->case = $case; + $this->tests = $tests; + } + + protected function renderHeader() + { + $contents = <<<EOD +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<title>{$this->case}</title> + <meta content="text/html; charset=UTF-8" http-equiv="content-type"> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1" id=TABLE1> + <tbody> + <tr> + <td rowspan="1" colspan="3"><strong>{$this->case}</strong></td> + </tr> +EOD; + return $contents; + } + + public function render() + { + echo $this->renderHeader(); + foreach($this->tests as $test) + { + $t = $test['test']; + if($t[0] == "open") + $t[1] = "<a href=\"{$t[1]}\" target=\"_blank\">{$t[1]}</a>"; + echo "<tr>\n"; + echo "<td>{$t[0]}</td>\n"; + echo "<td>{$t[1]}</td>\n"; + echo "<td>{$t[2]}</td>\n"; + echo "</tr>\n"; + } + echo $this->renderFooter(); + } + + protected function renderFooter() + { + $contents = <<<EOD + </tbody> +</table> +</body> +</html> +EOD; + return $contents; + } +} + +class SeleniumTestRunnerServer +{ + protected $cases = array(); + protected $trace = array(); + protected $name; + protected $runner; + + public function __construct($int, $runner) + { + $this->runner = $runner; + $this->initialize($int); + } + + protected function initialize($int) + { + foreach($int->getTests() as $command) + { + $case = $command[5]; + $this->cases[$case][] = + array('test' => $command[2], 'trace' => $command[4]); + if(is_null($this->name)) + $this->name = $command[6]; + } + } + + function serve() + { + if($this->isTestSuiteRequest()) + { + $testSuite = new SeleniumTestSuiteWriter($this->cases, + $this->name, $this->runner); + $testSuite->render(); + } + else if($this->isTestCaseRequest()) + { + if(($case = $this->getTestCaseRequest()) !== false) + { + + $testCase = new SeleniumTestCaseWriter($case, $this->getTestCase()); + $testCase->render(); + } + } + else + { + $this->runner->render(); + } + } + + protected function isTestSuiteRequest() + { + return isset($_GET['testSuites']); + } + + protected function isTestCaseRequest() + { + return isset($_GET['case']); + } + + public function isClientRequest() + { + return !$this->isTestSuiteRequest() && !$this->isTestCaseRequest(); + } + + protected function getTestCaseRequest() + { + $case = $_GET['case']; + if(isset($this->cases[$case])) + return $case; + else return false; + } + + protected function getTestCase() + { + $case = $_GET['case']; + if(isset($this->cases[$case])) + return $this->cases[$case]; + else + return array(); + } +} + + +class SeleniumTestCase extends UnitTestCase +{ + protected $selenium; + protected $Page; + + function __construct() + { + $server = SimpleSeleniumProxyServer::getInstance(); + if(!is_null($server)) + $this->selenium = $server->proxy(); + parent::__construct(); + } + + function getPage($class) + { + $info = new ReflectionClass($class); + return Prado::getApplication()->getTestPage($info->getFileName()); + } + + function __call($func, $args) + { + if(count($args) == 0) + return $this->selenium->{$func}(); + else if (count($args) == 1) + return $this->selenium->{$func}($args[0]); + else if (count($args) == 2) + return $this->selenium->{$func}($args[0], $args[1]); + } +} + +?>
\ No newline at end of file |