+ Add base file for the uitest.

This commit is contained in:
liyang
2024-04-22 14:25:48 +08:00
parent 06bd329658
commit 65d4e4f41e
20 changed files with 2174 additions and 87471 deletions
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env php
<?php
/**
title=用户登录
cid=10001
pid=79
>> 登录测试 : PASS!
**/
include dirname(__FILE__) . '/product.class.php';
$tester = new product('创建产品', 'createproduct');
$product = array();
$result = $tester->createProductTest($product);
r($result->nameTip->getText()) && p() && e('『产品名称』不能为空。'); // 判断名称是否必输
$product['name'] = array('setValue' => '产品' . time());
$result = $tester->createProductTest($product);
r($result->settings->getText()) && p() && e('设置'); // 只输入名称创建产品
$result = $tester->createProductTest($product);
r($result->nameTip->getText()) && p() && e('『产品名称』已经有'); // 相同名称判断
$product['name'] = array('setValue' => '产品' . time());
$product['type'] = array('picker' => '多分支');
$product['reviewer'] = array('multiPicker' => array('xmjl01'));
$result = $tester->createProductTest($product);
r($result->branchdropmenu->getText()) && p() && e('所有'); // 创建多分支产品
$tester->closeBrowser();
+15
View File
@@ -0,0 +1,15 @@
<?php
class productPage extends Page
{
public function __construct($driver)
{
parent::__construct($driver);
$doms = array(
'settings' => "//*[@id='navbar']//a[@data-id='settings']/span",
'reviewer' => "//*[@name='reviewer[]']",
'branchdropmenu' => "//*[@id='pick-branch-dropmenu']/span",
);
$this->doms = array_merge($this->doms, $doms);
}
}
+73
View File
@@ -0,0 +1,73 @@
<?php
include dirname(__FILE__, 2) . '/zentao.class.php';
class product extends zentao
{
/**
* Test create product features.
*
* @param object $product
* @access public
* @return object
*/
public function createProductTest($formData)
{
$productPage = new productPage($this->driver);
$this->su();
$this->go('product', 'mainNav');
$this->createInFrom('product', $formData);
$this->driver->wait(1);
return $productPage;
}
/**
* Access the product under secondary navigation.
*
* @param int $nav
* @access public
* @return mixed
*/
public function toProductNav($nav)
{
$testData = $this->config->testData->product;
$iframe = $this->dom->common->iframe;
$this->driver->switchToUrl('index.php?m=product&f=all', true);
$this->driver->wait(1)->switchTo($iframe->product);
$this->tester->searchProduct($testData->productName);
try
{
$this->driver->wait(1)->click("link:{$testData->productName}");
}
catch(Exception $e)
{
$this->driver->wait(1)->click($this->dom->product->all->mainContent->productList->firstTR->programSpan);
$this->driver->wait(1)->click("link:{$testData->productName}");
}
$this->driver->wait(1);
$this->tester->openNav('product', $nav);
$this->driver->getErrors($iframe->product);
}
/**
* Search the product plan
*
* @param int $searchField
* @param int $value
* @access public
* @return mixed
*/
public function searchProductPlan($searchField, $value)
{
$e = $this->dom->productPlan->browse;
$this->driver->wait(1)->click($e->mainMenu->searchBtn);
$this->driver->wait(1)->picker($e->mainContent->queryBox->searchChosen, $searchField);
$this->driver->wait(1)->setValue($e->mainContent->queryBox->firstValue, $value);
$this->driver->click($e->mainContent->queryBox->saveBtn);
}
}
+125
View File
@@ -0,0 +1,125 @@
<?php
include dirname(__FILE__, 3) . '/lib/init.class.php';
$driver = uiTester::factory('zentaopms', 'webdriver', $config->chrome);
$lang = new stdclass();
class zentao
{
public $driver;
public $page;
public $config;
/**
* Init driver, config, dom.
*
* @access public
* @return void
*/
public function __construct($pageName, $code)
{
global $driver;
$driver->setCase($pageName, $code);
$this->driver = $driver;
$this->page = new Page($driver);
$this->config = $driver->config;
}
/**
* Login to the test URL.
*
* @param string $account
* @param string $password
* @access public
* @return void
*/
public function su($account = '', $password = '')
{
if(!$account) $account = $this->config->zentaopms->defaultAccount;
if(!$password) $password = $this->config->zentaopms->defaultPassword;
$this->page->deleteCookie();
$this->page->get('');
$this->page->getErrors();
$this->page->account->setValue($account);
$this->page->password->setValue($password);
$this->page->submit->click();
$this->page->getCookie();
return $this->page;
}
/**
* open a mainMenu, navBar or URl.
*
* @param string $value
* @param string $type mainNav|navBar|switchToUrl
* @access public
* @return void
*/
public function go($value, $type = 'switchToUrl')
{
if(in_array($type, array('mainNav', 'navBar')))
{
try
{
$this->page->$type($value)->click();
}
catch(Exception $e)
{
$this->page->menuMoreNav->click();
$this->page->mainNav($value)->click();
}
$this->page->wait(1)->switchTo('appIframe-' . $value);
}
if($type == 'switchToUrl') $this->page->$type($value, true);
return $this->page;
}
/**
* Create object in from page.
*
* @param string $app
* @param object $form
* @access public
* @return object
*/
public function createInFrom($app, $form)
{
global $lang;
$this->page->btn($lang->$app->addBtn)->click();
$this->page->wait(1)->getErrors("appIframe-{$app}");
foreach($form as $formName => $value)
{
if(isset($value['wait'])) $this->page->wait($value['wait']);
if(isset($value['picker'])) $this->page->$formName->picker($value['picker']);
if(isset($value['multiPicker'])) $this->page->$formName->multiPicker($value['multiPicker']);
if(isset($value['datePicker'])) $this->page->$formName->datePicker($value['datePicker']);
if(isset($value['setValue'])) $this->page->$formName->setValue($value['setValue']);
if(isset($value['click'])) $this->page->$formName->click();
}
$this->page->btn($lang->$app->saveBtn)->click();
return $this->page;
}
/**
* Close the browser.
*
* @access public
* @return void
*/
public function closeBrowser()
{
$this->driver->closeBrowser();
}
}
-2619
View File
File diff suppressed because it is too large Load Diff
+69
View File
@@ -0,0 +1,69 @@
<?php
/** * Config 主文件
*/
$config = new stdclass;
$config->baseRoot = dirname(__FILE__, 2);
$config->gitlabRoot = 'https://gitlab.zcorp.cc/easycorp/testing/-/blob/master/ui/project';
/* 截图相关配置 */
$config->captureRoot = $config->baseRoot . '/www/data/capture/';
$config->captureWebRoot = '/data/capture/';
/* 报告相关配置 */
$config->reportRoot = $config->baseRoot . '/www/data/report';
$config->reportWebRoot = '/data/report/';
$config->reportType = 'html'; //html or markdown
$config->reportTemplate = array();
$config->reportTemplate['markdown'] = "# {TITLE}";
$config->reportTemplate['html'] = <<<EOT
<html>
<meta charset="utf-8">
<head>
<title>{TITLE}</title>
</head>
<body>
<div style='max-width:1024px;margin:0 auto;'>
EOT;
/*Chorme 浏览器默认配置。*/
$config->chrome = new stdclass;
$config->chrome->host = '';
$config->chrome->options = array();
$config->chrome->options[] = '--no-sandbox'; // 解决DevToolsActivePort文件不存在的报错
$config->chrome->options[] = 'window-size=1366x768'; // 指定浏览器分辨率
$config->chrome->options[] = '--disable-gpu'; // 谷歌文档提到需要加上这个属性来规避bug
//$config->chrome->options[] = '--hide-scrollbars'; // 隐藏滚动条; 应对一些特殊页面
//$config->chrome->options[] = 'blink-settings=imagesEnabled=false'; // 不加载图片; 提升速度
$config->chrome->options[] = '--ignore-certificate-errors';
//$config->chrome->options[] = '--ignore-ssl-errors';
//$config->chrome->options[] = '--headless'; // 浏览器不提供可视化页面
$config->chrome->options[] = '--test-type';
$config->chrome->options[] = '--start-maximized';
/* 项目配置 */
$config->zentaopms = new stdclass;
$config->zentaopms->defaultAccount = 'admin';
$config->zentaopms->defaultPassword = '123Qwe!@#';
$config->zentaopms->db = new stdclass;
$config->zentaopms->db->host = 'localhost';
$config->zentaopms->db->port = '3306';
$config->zentaopms->db->name = 'ta' . time();
$config->zentaopms->db->password = '123456';
$config->selectorAlias = array();
$config->selectorAlias['xpath'] = 'xpath';
$config->selectorAlias['css'] = 'cssSelector';
$config->selectorAlias['name'] = 'name';
$config->selectorAlias['id'] = 'id';
$config->selectorAlias['class'] = 'className';
$config->selectorAlias['tag'] = 'tagName';
$config->selectorAlias['link'] = 'linkText';
$config->onException = true;
/* Include extension config files. */
$extConfigFiles = glob(dirname(__FILE__) . DS . 'ext' . DS . '*.php');
if($extConfigFiles) foreach($extConfigFiles as $extConfigFile) include $extConfigFile;
+5
View File
@@ -0,0 +1,5 @@
## cookie目录说明
1. 如果要使用cookie请将该目录赋值权限777
2. 在调用项目下ui/lib/driver/webdriver/webdriver.class.php下的getCookie方法,会在该目录下新建cookie文件,重复调用则覆盖相同名称文件
+1
View File
@@ -0,0 +1 @@
config 扩展目录
-3629
View File
File diff suppressed because it is too large Load Diff
-13674
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
<?php
+9
View File
@@ -0,0 +1,9 @@
<?php
$lang = new stdClass();
$lang->product = new stdClass();
$lang->product->addBtn = '添加产品';
$lang->product->saveBtn = '保存';
$lang->program = new stdClass();
$lang->program->addBtn = '添加项目集';
$lang->program->saveBtn = '保存';
File diff suppressed because it is too large Load Diff
+202
View File
@@ -0,0 +1,202 @@
<?php
class page
{
public $driver;
public $xpathName;
public $doms;
public $xpath;
public $timeout = 5;
public function __construct($driver)
{
$this->driver = $driver;
$this->doms = array(
'menuMoreNav' => '//*[@id="menuMoreNav"]/li[2]/a'
);
}
/**
* Get element of mainNav menu.
*
* @param string $app
* @access public
* @return object
*/
public function mainNav($app)
{
$xpath = "//li[@data-app='$app']/a";
$this->driver->waitElement($xpath, $this->timeout)->getElement($xpath);
return $this;
}
/**
* Get element of navbar.
*
* @param string $nav
* @access public
* @return object
*/
public function navbar($nav)
{
$xpath = "//a[@data-id='$nav']";
$this->driver->waitElement($xpath, $this->timeout)->getElement($xpath);
return $this;
}
/**
* Get xpath of the zTable.
*
* @param string $colName
* @param string $index
* @access public
* @return object
*/
public function dTable($colName, $index)
{
$xpath = "//div[@class='dtable-cells-container']//[@data-col='$colName'][$index]";
return $xpath;
}
/**
* Get element of a button.
*
* @param string $value
* @param string $type
* @access public
* @return object
*/
public function btn($value, $type = 'text')
{
$xpath = $type == 'text' ? "//*[text()='$value']" : $value;
$this->driver->waitElement($xpath, $this->timeout)->getElement($xpath);
return $this;
}
/**
* Get the xpath of picker.
*
* @param string $value
* @access public
* @return object
*/
public function picker($value)
{
$this->driver->picker($this->xpath, $value);
return $this;
}
/**
* Get the xpath of multiPicker.
*
* @param string $value
* @access public
* @return void
*/
public function multiPicker($value)
{
$this->driver->multiPicker($this->xpath, $value);
return $this;
}
/**
* Use datePicker in webDriver.
*
* @param string $value
* @access public
* @return void
*/
public function datePicker($value)
{
$this->driver->datePicker($this->xpathName, $value);
}
public function __get($name)
{
$this->xpathName = $name;
if(isset($this->doms[$name]))
{
$xpath = $this->doms[$name];
}
else
{
$xpath = $this->getXpath($name);
}
$this->driver->waitElement($xpath, $this->timeout)->getElement($xpath);
$this->xpath = $xpath;
return $this;
}
/**
* Get xpath of an element.
*
* @param string $name
* @access public
* @return void
*/
public function getXpath($name)
{
$element = '//*[@name="' . $name . '"]';
try
{
$this->driver->getElement($element);
}
catch (Exception $e)
{
try
{
$element = '//*[@name="' . $name . '[]' . '"]';
$this->driver->getElement($element);
}
catch (Exception $e)
{
$element = '//*[@id="' . $name . '"]';
try
{
$this->driver->getElement($element);
}
catch (Exception $e)
{
$element = $name;
}
}
}
return $element;
}
public function __call($method, $params = array())
{
if(method_exists($this->driver, $method)) return call_user_func_array(array($this->driver, $method), $params);
return false;
}
/**
* Get result of the case.
*
* @access public
* @return void
*/
public function getResult()
{
$result = json_decode($this->driver->__toString(), true);
$this->driver->errors = array();
if($result['errors'])
{
foreach($result['errors'] as $error) echo str_replace("\n", '', $error) . PHP_EOL;
return array();
}
return $result;
}
}
+340
View File
@@ -0,0 +1,340 @@
<?php
define('DS', DIRECTORY_SEPARATOR);
define('CONFIG_ROOT', dirname(dirname(__FILE__)) . '/config/');
include CONFIG_ROOT . '/config.php';
/* Set the error reporting. */
error_reporting(E_ALL);
class uiTester
{
public static $instance;
public $config;
public $caseTitle;
public $caseCode;
public $reportFile;
public $reportURL;
public $errors = array();
public $results;
/**
* Factory function.
*
* @param string $project
* @param string $driver
* @param object $config
* @static
* @access public
* @return object
*/
public static function factory($project, $driver, $config)
{
if(empty(self::$instance)) self::$instance = array();
if(isset(self::$instance[$driver])) return self::$instance[$driver];
$className = $driver;
$classFile = dirname(__FILE__) . DS . 'drivers' . DS . $driver . DS . "$driver.class.php";
if(!is_file($classFile)) return trigger_error("the class file {$classFile} not found");
include $classFile;
self::$instance[$driver] = new $className($project, $config);
return self::$instance[$driver];
}
/**
* __construct function
*
* @param string $driver
* @param object $config
* @access public
* @return void
*/
public function __construct($project)
{
global $config;
$this->config = $config;
}
/**
* Auto echo return info.
*
* @access public
* @return mixed
*/
public function __toString()
{
$output = new stdclass;
$output->result = end($this->results);
$output->reportFile = $this->reportFile;
$output->reportURL = $this->reportURL;
$output->errors = $this->errors;
$output->caseTitle = $this->caseTitle;
return json_encode($output);
}
/**
* Set title and code.
*
* @param string $title
* @param string $code
* @param string $project
* @access public
* @return void
*/
public function setCase($title, $code)
{
$this->caseTitle = $title;
$this->caseCode = $code;
$this->initReport();
}
/**
* SetWebRoot of the driver.
*
* @param string $webRoot
* @access public
* @return mixed
*/
public function setWebRoot($webRoot)
{
$this->config->webRoot = $webRoot;
}
/**
* Create and init report.
*
* @access public
* @return void
*/
public function initReport()
{
$reportType = $this->config->reportType;
$reportTemplate = $this->config->reportTemplate[$reportType];
$reportPath = $this->config->reportRoot . DS . $this->caseCode . DS;
$suffix = ($reportType == 'markdown') ? 'md' : $reportType;
$this->reportFile = $reportPath . date('ymdhis') . '.' . $suffix;
$this->reportURL = str_replace($this->config->reportRoot, $this->config->reportWebRoot, $this->reportFile);
if(!is_dir($reportPath)) mkdir($reportPath, 0777, true);
$reportContent = str_replace(array('{TITLE}', '{CODE}'), array($this->caseTitle, $this->caseCode), $reportTemplate);
file_put_contents($this->reportFile, $reportContent);
}
/**
* Export test report of a page.
*
* @param array $alertsMessage
* @access public
* @return void
*/
public function saveReport($message)
{
$message .= "\n";
file_put_contents($this->reportFile, $message, FILE_APPEND);
}
/**
* Print close tag.
*
* @access public
* @return void
*/
public function endReport()
{
$message = '</div></body></html>';
$this->saveReport($message);
}
/**
* Log assert result to asserts.
*
* @param string $result
* @access public
* @return mixed
*/
public function logAsserts($result)
{
$this->results[] = $result;
}
/**
* Get asserts.
*
* @access public
* @return array
*/
public function getAsserts()
{
return $this->results;
}
}
include 'page.class.php';
$includeFiles = get_included_files();
if($includeFiles)
{
foreach(glob(dirname($includeFiles[0]) . '/page/*') as $file) include $file;
}
/**
* Save variable to $_result.
*
* @param mixed $result
* @access public
* @return bool true
*/
function r($result)
{
global $_result;
$_result = $result;
return true;
}
/**
* Print value or properties.
*
* @param string $key
* @param string $delimiter
* @access public
* @return void
*/
function p($keys = '', $delimiter = ',')
{
global $_result;
if(empty($_result)) return print(implode("\n", array_fill(0, substr_count($keys, $delimiter) + 1, 0)) . "\n");
if(is_array($_result) && isset($_result['code']) && $_result['code'] == 'fail') return print((string) $_result['message'] . "\n");
/* Print $_result. */
if($keys === '' && is_array($_result)) return print_r($_result) . "\n";
if($keys === '' || !is_array($_result) && !is_object($_result)) return print((string) $_result . "\n");
$parts = explode(';', $keys);
foreach($parts as $part)
{
$values = getValues($_result, $part, $delimiter);
if(!is_array($values)) continue;
foreach($values as $value) echo $value . "\n";
}
return true;
}
/**
* 当数组/对象变量$var存在$key项时,返回存在的对应值或设定值,否则返回$key或不存在的设定值。
* When the $var has the $key, return it, else result one default value.
*
* @param array|object $var
* @param mixed $valueWhenNone value when the key not exits.
* @param mixed $valueWhenExists value when the key exits.
* @access public
* @return mixed
*/
function zget($var, $key, $valueWhenNone = false, $valueWhenExists = false)
{
if(!is_array($var) and !is_object($var)) return false;
$type = is_array($var) ? 'array' : 'object';
$checkExists = $type == 'array' ? isset($var[$key]) : isset($var->$key);
if($checkExists)
{
if($valueWhenExists !== false) return $valueWhenExists;
return $type == 'array' ? $var[$key] : $var->$key;
}
if($valueWhenNone !== false) return $valueWhenNone;
return $key;
}
/**
* Get values
*
* @param mixed $value
* @param string $keys
* @param string $delimiter
* @access public
* @return void
*/
function getValues($value, $keys, $delimiter)
{
$object = '';
$index = -1;
$pos = strpos($keys, ':');
if($pos)
{
$arrKey = substr($keys, 0, $pos);
$keys = substr($keys, $pos + 1);
$pos = strpos($arrKey, '[');
if($pos)
{
$object = substr($arrKey, 0, $pos);
$index = trim(substr($arrKey, $pos + 1), ']');
}
else
{
$index = $arrKey;
}
}
$keys = explode($delimiter, $keys);
if($object !== '')
{
if(is_array($value))
{
$value = $value[$object];
}
else if(is_object($value))
{
$value = $value->$object;
}
else
{
return print("Error: No object name '$object'.\n");
}
}
if($index != -1)
{
if(is_array($value))
{
if(!isset($value[$index])) return print("Error: Cannot get index $index.\n");
$value = $value[$index];
}
else if(is_object($value))
{
if(!isset($value->$index)) return print("Error: Cannot get index $index.\n");
$value = $value->$index;
}
else
{
return print("Error: Not array, cannot get index $index.\n");
}
}
$values = array();
foreach($keys as $key) $values[] = zget($value, $key, '');
return $values;
}
/**
* Expect values, ztf will put params to step.
*
* @param string $exepect
* @access public
* @return void
*/
function e($expect)
{
}
-15020
View File
File diff suppressed because it is too large Load Diff
-11247
View File
File diff suppressed because it is too large Load Diff
-3925
View File
File diff suppressed because it is too large Load Diff
-27347
View File
File diff suppressed because it is too large Load Diff
-10010
View File
File diff suppressed because it is too large Load Diff