2018年10月19日 星期五

碼農工作日誌-在 Linux 上安裝 Composer 並且設成全域執行、看 Linux 服務列表、全新主機要執行 PHP 測試需要安裝

👉在 Linux 上安裝 Composer 並且設成全域執行

Composer 作為 PHP 上套件相依的管理套件,如果和 PHP 設成可以全域執行,這樣在命令列上的指令就會比較減少,並且也不需要每個專案都下載 composer.phar。首先,先把下載安裝的過程建立成 sh 檔 :

#!/bin/sh

EXPECTED_SIGNATURE="$(wget -q -O - https://composer.github.io/installer.sig)"
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_SIGNATURE="$(php -r "echo hash_file('SHA384', 'composer-setup.php');")"

if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ]
then
    >&2 echo 'ERROR: Invalid installer signature'
    rm composer-setup.php
    exit 1
fi

php composer-setup.php --quiet
RESULT=$?
rm composer-setup.php
exit $RESULT

然後,執行 sh 檔之後,完成下載 composer.phar,再來把檔案搬到執行目錄下 :

$ mv composer.phar /usr/local/bin/composer

再試試設定是否成功 :

$ composer -V
Composer version 1.7.2 2018-08-16 16:57:12

這樣就可以直接使用 Composer。


👉看 Linux 服務列表

$  service --status-all

這樣會列出全部服務

$ service docker status

這樣會列出 docker 服務的狀態


👉全新主機要執行 PHP 測試需要安裝
  • PHP
  • Composer
  • Codeception
  • Monolog
  • Java JDK
  • Selenium 由主機直接下載
  • ChromeDriver 由主機直接下載
  • Chrome browser 尤其在 Linux 主機要記得,因為預設瀏覽器是 Firefox

2018年10月18日 星期四

碼農工作日誌-在 Ubuntu 上重新啟動 Teamviewer

👉在 Ubuntu 上重新啟動 Teamviewer

由於開發與測試在不同的主機,所以使用 Teamviewer 作為遠端桌面,但上工前卻發現一直出現無法連結的狀況,應該是說,連結一段時間,一直停在畫面建構的狀態,然後就結束連結工作。
想到的解決方案,利用開發機 SSH 到測試機,重新啟動 Teamviewer。搜尋到的指令是

$ sudo teamviewer --daemon restart

重啟後就可以正常使用。附註有關 --daemon 資料




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']);
}

因為沒有要求很準確的結束,這樣已經可以滿足需求。


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
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 執行測試案例。

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