👉在 Ubuntu 上重新啟動 Teamviewer
由於開發與測試在不同的主機,所以使用 Teamviewer 作為遠端桌面,但上工前卻發現一直出現無法連結的狀況,應該是說,連結一段時間,一直停在畫面建構的狀態,然後就結束連結工作。
想到的解決方案,利用開發機 SSH 到測試機,重新啟動 Teamviewer。搜尋到的指令是
$ sudo teamviewer --daemon restart
重啟後就可以正常使用。附註有關 --daemon 資料
2018年10月18日 星期四
2018年10月17日 星期三
PHP的時間轉換
👉利用 selenium 玩遊戲時,需要設定玩遊戲分鐘數,需要用來換算及執行動作
✅利用 time() 來取得現在時間(秒),在加上要玩的秒數,利用 while 迴圈來控制
// 計算結束時間
$finishTime = time() + (int)$seconds;
while (time() < $finishTime) {
$action->moveByOffset(round($startBtnX),
round($startBtnY));
$action->moveToElement($canvas,
round($startBtnX), round($startBtnY))
->click()->perform();
$tester->wait(Parameters::$waitingTime['short']);
}
因為沒有要求很準確的結束,這樣已經可以滿足需求。
✅利用 time() 來取得現在時間(秒),在加上要玩的秒數,利用 while 迴圈來控制
// 計算結束時間
$finishTime = time() + (int)$seconds;
while (time() < $finishTime) {
$action->moveByOffset(round($startBtnX),
round($startBtnY));
$action->moveToElement($canvas,
round($startBtnX), round($startBtnY))
->click()->perform();
$tester->wait(Parameters::$waitingTime['short']);
}
因為沒有要求很準確的結束,這樣已經可以滿足需求。
2018年10月8日 星期一
Java Develop Coder 開始 PHP Test Coder 的生活_2018/10/8 Day29
開始用 Cucumber 來寫測試案例,因為 Codeception 支援 BDD,加上 Gherkin 支援繁體中文,如果將設定及步驟完成後,之後就可以重複使用步驟來進行測試。
從 composer 下載回來看到 codeception 也是使用 Behat 來做 BDD,但是引入的部分少了很多,從 feature 對照到 step definition 以及生成 step 實作的方法與設定,都必須依照文件上的規定,原本想要分散不一樣頁面的 steps 到不同命名空間或是資料夾,都會發生 classNotFoundException,最後就...全部放在一起。
由於專案的 actor 就只有 AcceptanceTester,所以就把 feature 放在 tests 下,steps 放在 _support 資料夾下,原本在外面的輔助類別,也通通移進來,讓大家彼此看得到。執行方式就跟文件上相同,執行時可以看見用中文寫的步驟以及對應的程式碼,要除錯也方便。
👉PHPStrom
使用 PHPStrom 的時候,在使用 codeception 的 BDD 時會發現,就算把 step definition 的程式實作完成,IDE 還是會顯示 Undefinition step reference,在 Stack Overflow 找得到相關問題,但是解法會造成前面說的 classNotFoundException,最後就只好
use Behat\Behat\Context; class GeneralRegisterSteps implements Context\Context{
這樣做只是要 IDE 知道哪些 step 已經實作了,之後就不會重複寫。
2018年10月3日 星期三
Java Develop Coder 開始 PHP Test Coder 的生活_2018/10/3 Day24
今天開始建置比較完整的測試案例。
👉Composer
官網介紹是 PHP 的相依管理的套件,應該就像 Gradle 之類的套件吧! 之前安裝都是在專案內,這次就把它建置在 Global,各個專案在使用上就不需要一直去下載,方便得多。
首先依照指示下載 composer.phar
分別執行每一行 command,完成後會看到 composer.phar 會被下載到目前位置,然後再搬移檔案到公用執行的資料夾。
$ mv composer.phar /usr/local/bin/composer
之後在命令列執行 composer,就可以使用。不行的話,請參考官網下方附註。
👉Codeception
官網介紹可以在 PHP 語言架構上進行所有(幾乎)的測試,包含常用的框架。所以測試專案需要安裝這個套件。用上面裝好的 Composer 來安裝,在專案的目錄下執行
$ composer require "codeception/codeception" --dev
這次專案只需要進行接受性測試,所以用另一種方式初始化
$ php codecept init acceptance
再來就會有問答選項來完成專案的建置,完成後用命令列來生成 Codeception Test Case(cest)
$ php codecept generate:cest acceptance Xxxx
這樣就會在 tests 的目錄下生成 XxxxCest 的類別,執行時,Codeception 也會去找 cest 類別執行。然後就開始寫寫寫的測試生涯。
👉Composer
官網介紹是 PHP 的相依管理的套件,應該就像 Gradle 之類的套件吧! 之前安裝都是在專案內,這次就把它建置在 Global,各個專案在使用上就不需要一直去下載,方便得多。
首先依照指示下載 composer.phar
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === '93b54496392c062774670ac18b134c3b3a95e5a5e5c8f1a9f115f203b75bf9a129d5daa8ba6a13e2cc8a1da0806388a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
分別執行每一行 command,完成後會看到 composer.phar 會被下載到目前位置,然後再搬移檔案到公用執行的資料夾。
$ mv composer.phar /usr/local/bin/composer
之後在命令列執行 composer,就可以使用。不行的話,請參考官網下方附註。
👉Codeception
官網介紹可以在 PHP 語言架構上進行所有(幾乎)的測試,包含常用的框架。所以測試專案需要安裝這個套件。用上面裝好的 Composer 來安裝,在專案的目錄下執行
$ composer require "codeception/codeception" --dev
這次專案只需要進行接受性測試,所以用另一種方式初始化
$ php codecept init acceptance
再來就會有問答選項來完成專案的建置,完成後用命令列來生成 Codeception Test Case(cest)
$ php codecept generate:cest acceptance Xxxx
這樣就會在 tests 的目錄下生成 XxxxCest 的類別,執行時,Codeception 也會去找 cest 類別執行。然後就開始寫寫寫的測試生涯。
2018年10月2日 星期二
Java Develop Coder 開始 PHP Test Coder 的生活_2018/10/2 Day23
完成了一次的遊戲操作,但是需求是一整天一直玩,接下來處理這部分。
👉PHP 語法
為了重複做一件事情(玩遊戲),使用 while 迴圈實作。
...
while ($counts > 0) {
// 用 selenium 的 action 操控 canvas
$I->executeInSelenium(function (\Facebook\WebDriver\Remote\RemoteWebDriver $webDriver) {
$element = $webDriver->findElement(\Facebook\WebDriver\WebDriverBy::xpath('//div[@id=\'game\']/canvas'));
$action = $webDriver->action();
$action->moveByOffset(Parameters::$decreaseBets['x_offset'], Parameters::$decreaseBets['y_offset']);
$action->moveToElement($element, Parameters::$gameStart['x_offset'], Parameters::$gameStart['y_offset'])->doubleClick()->perform();
});
// 等候遊戲玩完
$I->wait(Parameters::$waitSeconds);
$counts--;
}
...
等到 counts 減完以後,就會跳出迴圈。
👉Selenium 語法
上面的程式在執行時,第2次(設定跑3次)要點擊時,都會產生沒有反應的狀況,所以在點擊前用moveByOffset先把滑鼠移到其他地方,再回到遊戲開始的按鈕,如此就能正常運作。
👉Codeception 語法
前篇把跟測試無關的輔助方法放在 XxxCest 的類別裡,會讓 Codeception 把它也當成是要執行的測試程式,而造成錯誤,所以就把輔助的動作移到 StepObject 裡,需要使用再呼叫就不會發生誤判的狀況。
用命令列建立 StepObject
php vendor/bin/codecept generate:stepobject acceptance Xxx
然後就會有互動步驟建立 function
php vendor/bin/codecept generate:stepobject acceptance Xxx
Add action to StepObject class (ENTER to exit): stepsOfXxx
Add action to StepObject class (ENTER to exit):
StepObject was created in /tests/acceptance/_support/Step/Acceptance/Xxx.php
接下來到剛剛生成的類別裡寫完方法後,就可以在測試程式裡叫用。
public function playGame(\Step\Acceptance\Xxx $I)
{
$I->waitForElement('canvas', 15);
$I->wait(Parameters::$waitSeconds);
$I->decreaseBets(Parameters::$pressDecreaseButtonTimes);
$I->playGameByGivenTimes(Parameters::$executeTimes);
}
👉Docker
想要同時執行多個相同的測試案例,Codeception 文件提到了 Parallel Execution ,裡面用 Docker 和 Robo 來實現。
先安裝好 Docker 及 Docker-Compose,再依照 Codeception 文件說的把 image 拉回來。
今天還沒辦法從 Docker 執行測試案例。
👉PHP 語法
為了重複做一件事情(玩遊戲),使用 while 迴圈實作。
...
while ($counts > 0) {
// 用 selenium 的 action 操控 canvas
$I->executeInSelenium(function (\Facebook\WebDriver\Remote\RemoteWebDriver $webDriver) {
$element = $webDriver->findElement(\Facebook\WebDriver\WebDriverBy::xpath('//div[@id=\'game\']/canvas'));
$action = $webDriver->action();
$action->moveByOffset(Parameters::$decreaseBets['x_offset'], Parameters::$decreaseBets['y_offset']);
$action->moveToElement($element, Parameters::$gameStart['x_offset'], Parameters::$gameStart['y_offset'])->doubleClick()->perform();
});
// 等候遊戲玩完
$I->wait(Parameters::$waitSeconds);
$counts--;
}
...
等到 counts 減完以後,就會跳出迴圈。
👉Selenium 語法
上面的程式在執行時,第2次(設定跑3次)要點擊時,都會產生沒有反應的狀況,所以在點擊前用moveByOffset先把滑鼠移到其他地方,再回到遊戲開始的按鈕,如此就能正常運作。
👉Codeception 語法
前篇把跟測試無關的輔助方法放在 XxxCest 的類別裡,會讓 Codeception 把它也當成是要執行的測試程式,而造成錯誤,所以就把輔助的動作移到 StepObject 裡,需要使用再呼叫就不會發生誤判的狀況。
用命令列建立 StepObject
php vendor/bin/codecept generate:stepobject acceptance Xxx
然後就會有互動步驟建立 function
php vendor/bin/codecept generate:stepobject acceptance Xxx
Add action to StepObject class (ENTER to exit): stepsOfXxx
Add action to StepObject class (ENTER to exit):
StepObject was created in /tests/acceptance/_support/Step/Acceptance/Xxx.php
接下來到剛剛生成的類別裡寫完方法後,就可以在測試程式裡叫用。
public function playGame(\Step\Acceptance\Xxx $I)
{
$I->waitForElement('canvas', 15);
$I->wait(Parameters::$waitSeconds);
$I->decreaseBets(Parameters::$pressDecreaseButtonTimes);
$I->playGameByGivenTimes(Parameters::$executeTimes);
}
👉Docker
想要同時執行多個相同的測試案例,Codeception 文件提到了 Parallel Execution ,裡面用 Docker 和 Robo 來實現。
先安裝好 Docker 及 Docker-Compose,再依照 Codeception 文件說的把 image 拉回來。
今天還沒辦法從 Docker 執行測試案例。
2018年10月1日 星期一
Java Develop Coder 開始 PHP Test Coder 的生活_2018/10/1 Day22
在進入控制遊戲之前,先記錄一下 monolog。
👉 PHP 的 Logger 框架 Monolog
在專案內建立 Logger 類別,用來取得 logger 並設定。建好類別之後引用執行報錯,[Error] Class 'Jutai\Robot\Utils\RobotLogger' not found,這...不是用 use 就算 import 進來了嗎? monolog 的套件也是用 use 就可以使用,原因是出在有 composer 的幫忙,處理 autoload,這樣就可以不需要在頁面裡用 use 還要加上 require。
基本的用法是在引入類別後,設定 Log 存放位置與級別,就可以開始使用。
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
// create a log channel
$log = new Logger('name');
$log->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING));
// add records to the log
$log->warning('Foo');
$log->error('Bar');
詳細的使用方法後續再研究。
👉 PHP 語法
🍎解決 use 沒有辦法發現類別問題
namespace 現在當成 Java 的 package 用
use 感覺像 Java 的 import,但是使用自己的類別要再加上 require 或 include (?)
require(reuqire_once) import 的另一半,reuqire_once 會檢查如果有引用過不會再引用,錯誤報 error,不繼續執行
include import 的另一半,錯誤報 warming,程式繼續執行
參考資料
[PHP]include 與 require 的差別
php中require,include,use的区别
PHP class not found when using namespace
🍎autoload
autoload 在處理引用類別的問題,有 PHP原生的 __autoload()、加強版的 spl_autoload 與 spl_autoload_register 以及使用 composer 依據 PSR-0(2014/10/21宣告棄用) 或 PSR-4 標準來驅動的 autoload。專案裡因為已經使用 composer,所以就採取最後一個解決方案。在 composer.json 加上 autoload 的宣告。
{
....
"autoload": {
"psr-4": {
"Jutai\\Robot\\Utils\\": "utils/"
}
}
....
}
前面是命名空間,後面是對應的資料夾位置,兩個反斜線應該是來逃逸用的。再執行 composer install,就可以直接使用 use 來引用類別。
參考資料
COMPOSER進階原理:PHP命名空間與PSR-0
PHP系列 - Autoload 自動載入
PHP Composer … The Autoloader
👉Selenium 操作 HTML5 canvas
進入遊戲後,要開始操作 canvas,但是由於 codeception 並沒有可以操作 html5 標籤的相關指令,所以只有借用 Selenium 來操作,精確的講,是利用 Facebook 實作 Selenium 的 WebDriver 的套件來操作,而且也不需要另外安裝,它被包含在 codeception 裡。
...
$I->executeInSelenium(function (\Facebook\WebDriver\Remote\RemoteWebDriver $webDriver) {
$element = $webDriver->findElement(\Facebook\WebDriver\WebDriverBy::xpath('//div[@id=\'game\']/canvas'));
$action = $webDriver->action();
$action->moveToElement($element, 1300, 390)->click()->perform();
});
...
程式碼還需要重構,因為需求會是玩一整天的遊戲。而按鈕的位置因為需要利用人工調整,所以也需要用變數替代。
參考資料
Automated Testing of HTML5 Canvas Applications with Selenium WebDriver
请教 Selenium 测试 HTML 5 canvas 问题
【基础7】selenium操作canvas
👉 PHPStorm 快捷鍵
Ctrl+Alt+L → Reformat Code
👉Ubuntu 指令
看 PATH
echo $PATH
👉 PHP 的 Logger 框架 Monolog
在專案內建立 Logger 類別,用來取得 logger 並設定。建好類別之後引用執行報錯,[Error] Class 'Jutai\Robot\Utils\RobotLogger' not found,這...不是用 use 就算 import 進來了嗎? monolog 的套件也是用 use 就可以使用,原因是出在有 composer 的幫忙,處理 autoload,這樣就可以不需要在頁面裡用 use 還要加上 require。
基本的用法是在引入類別後,設定 Log 存放位置與級別,就可以開始使用。
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
// create a log channel
$log = new Logger('name');
$log->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING));
// add records to the log
$log->warning('Foo');
$log->error('Bar');
詳細的使用方法後續再研究。
👉 PHP 語法
🍎解決 use 沒有辦法發現類別問題
namespace 現在當成 Java 的 package 用
use 感覺像 Java 的 import,但是使用自己的類別要再加上 require 或 include (?)
require(reuqire_once) import 的另一半,reuqire_once 會檢查如果有引用過不會再引用,錯誤報 error,不繼續執行
include import 的另一半,錯誤報 warming,程式繼續執行
參考資料
[PHP]include 與 require 的差別
php中require,include,use的区别
PHP class not found when using namespace
🍎autoload
autoload 在處理引用類別的問題,有 PHP原生的 __autoload()、加強版的 spl_autoload 與 spl_autoload_register 以及使用 composer 依據 PSR-0(2014/10/21宣告棄用) 或 PSR-4 標準來驅動的 autoload。專案裡因為已經使用 composer,所以就採取最後一個解決方案。在 composer.json 加上 autoload 的宣告。
{
....
"autoload": {
"psr-4": {
"Jutai\\Robot\\Utils\\": "utils/"
}
}
....
}
前面是命名空間,後面是對應的資料夾位置,兩個反斜線應該是來逃逸用的。再執行 composer install,就可以直接使用 use 來引用類別。
參考資料
COMPOSER進階原理:PHP命名空間與PSR-0
PHP系列 - Autoload 自動載入
PHP Composer … The Autoloader
👉Selenium 操作 HTML5 canvas
進入遊戲後,要開始操作 canvas,但是由於 codeception 並沒有可以操作 html5 標籤的相關指令,所以只有借用 Selenium 來操作,精確的講,是利用 Facebook 實作 Selenium 的 WebDriver 的套件來操作,而且也不需要另外安裝,它被包含在 codeception 裡。
...
$I->executeInSelenium(function (\Facebook\WebDriver\Remote\RemoteWebDriver $webDriver) {
$element = $webDriver->findElement(\Facebook\WebDriver\WebDriverBy::xpath('//div[@id=\'game\']/canvas'));
$action = $webDriver->action();
$action->moveToElement($element, 1300, 390)->click()->perform();
});
...
程式碼還需要重構,因為需求會是玩一整天的遊戲。而按鈕的位置因為需要利用人工調整,所以也需要用變數替代。
參考資料
Automated Testing of HTML5 Canvas Applications with Selenium WebDriver
请教 Selenium 测试 HTML 5 canvas 问题
【基础7】selenium操作canvas
👉 PHPStorm 快捷鍵
Ctrl+Alt+L → Reformat Code
👉Ubuntu 指令
看 PATH
echo $PATH
2018年9月30日 星期日
Java Develop Coder 開始 PHP Test Coder 的生活_2018/9/28 Day 19
目前需求開發一支可以控制 HTML5 Canvans 遊戲的機器人,現在的構想是用 Selenium 來控制網頁元件,以驗收測試為基礎來寫。
👉解析API傳回的JSON字串
首先,需要先進入遊戲,為了節省登入的步驟,所以以呼叫API的方式來進入遊戲。呼叫後傳回格式如下:
{
"data": {
"url": "https://h5c.cqgame.games/1/?token=da05d84ab17d2ed4f184d2f7axxxxxxxx&language=zh-CN"
},
"status": {
"code": 0,
"message": "success",
"timestamp": 1038106999
}
}
裡面的 url 就是進入遊戲的入口,將它擷取放入測試之前的步驟。接下來就要用 PHP 裡跟 JSON 有關的函式。首先利用 file_get_contents() 將 JSON 字串取回來,再利用 json_decode() 解碼。
// 處理 ssl 造成的錯誤
$stream_opts = [
"ssl" => [
"verify_peer"=>false,
"verify_peer_name"=>false,
]
];
// 取回 API 返回內容
$data = file_get_contents($this::$api_url, false, stream_context_create($stream_opts));
// JSON解碼,取得 url
$game_url = json_decode($data, true)['data']['url'];
接著就可以前往遊戲畫面。
👉Ubuntu Command
reboot 重開機
👉解析API傳回的JSON字串
首先,需要先進入遊戲,為了節省登入的步驟,所以以呼叫API的方式來進入遊戲。呼叫後傳回格式如下:
{
"data": {
"url": "https://h5c.cqgame.games/1/?token=da05d84ab17d2ed4f184d2f7axxxxxxxx&language=zh-CN"
},
"status": {
"code": 0,
"message": "success",
"timestamp": 1038106999
}
}
裡面的 url 就是進入遊戲的入口,將它擷取放入測試之前的步驟。接下來就要用 PHP 裡跟 JSON 有關的函式。首先利用 file_get_contents() 將 JSON 字串取回來,再利用 json_decode() 解碼。
// 處理 ssl 造成的錯誤
$stream_opts = [
"ssl" => [
"verify_peer"=>false,
"verify_peer_name"=>false,
]
];
// 取回 API 返回內容
$data = file_get_contents($this::$api_url, false, stream_context_create($stream_opts));
// JSON解碼,取得 url
$game_url = json_decode($data, true)['data']['url'];
接著就可以前往遊戲畫面。
👉Ubuntu Command
reboot 重開機
訂閱:
文章 (Atom)