phpunit+gearman產生的矛盾

Posted by ayuayu on 2014/07/29

嗯,經過各種接近極限整人的測試以後,發現以下幾點,有誤請指正
指正是拿具體例子或明顯可執行/實作的例子來反駁,如果舉不出可行的簡單例子,請勿來亂,謝謝。

------------------------
先說結論

phpunit沒有辦法正確顯示coverage的原因是沒有直接call,然而這個應該是gearman的必然現象

判斷的結果,既然是單元測試,那麼必然是我直接call他可以得到期望的回傳(即使中間有邏輯),好死不死gearman的運作機制並不是這類型的

首先是worker部分必然是脫離phpunit獨立執行,因為開worker那部份一定要無窮回圈來listen(不然用gearman就失去意義了)

phpunit比起coverage實際上assert才是重要的檢證機制(畢竟他不只可以用來assert true,assert false,或是assert 特定的value,還可以使用regexp來檢查return,是相當有效的防修改掛掉的test

然後listen的client部分為什麼沒有cover呢? 很簡單,即使用了class,即使require,我們也不會去直接執行那條function
因為在沒有job的狀態下,去執行那條function毫無意義,然而如果是發出去的worker需求,會變成這樣:
"我們(傳資料)給已經註冊的job server function,由他幫你處理註冊好先前設定的工作"
所以中間的code都是我們一開始註冊的無窮迴圈狀態的worker在執行的,既然是別人在執行,那就不會cover了


-----------------------
為了接近其他的測試範例,我們使用class gearman來完成這個目標

worker架構:
class裡面,先private $worker
然後在__construct裡面new Gearmanworker,addserver,addfunction (注意第二個參數必須是 array($this, 'domyworker'),不然因為你寫在class裡面會找不到

註冊完,隨便寫個function來啟動
public function run(){
    while ($this->worker->work());
 }
當然這要在別的terminal開的,開始listen

client(test)架構:
 client test的寫法由於直接call沒有意義,我們要把assert放在job執行成功後的回傳裡面
然後addtask 完讓他run
請參照https://github.com/vlucas/phpunit-gearman-testing

同樣,由於在class裡面,因此如果想call functon請改成$this->function

再來就可以測試了
我們可以正確測到預期丟job過去應該有的回傳
(如果說實際應用的例子沒有值得回傳的資料,那就回傳個執行狀態的陣列總行吧)

不過你去開report就會發現,coverage居然是0%
一開始以為是什麼設定錯誤,寫法問題,或者根本是BUG之類的
但是理解一次以後就清楚了

在測試過程中,執行job那些code的是server,而不是測試程式(注意你的unittest只有丟job出去,phpunit還沒強大到可以trace到底,不過以後可能會更新?)

所以以上的程式都有執行到,但phpunit會認為他都沒執行到,很有趣吧

--------------------------
二三事:
1.$task = self::$client->addTaskBackground($name, $params, null, $taskId);
如果你改成這樣,因為return會直接切掉,因此你的assert會直接失效

2.使用gearman來寫code的時候,完全沒有辦法靠php本身的debug機制來除錯
因為你註冊好job以後,出錯的話永遠是錯在無窮迴圈那行
(因為正在執行的行永遠是那條無窮迴圈,由那個區域去call其他的function)
解法也直覺,自己echo var_dump吧..

FuelPHP 模組/HMVC筆記

Posted by ayuayu on 2014/07/24

FuelPHP對HMVC敘述不明不白,附帶一提那個V還是有問題的(後來新版架構已改成presenter)

app/config裡面的'module_paths' 項目要做好路徑設定,不過不是設自己的名稱
而是內定的APPPATH.'modules'.DS,

module裡面最底限要有類似fuelphp的架構
因為module和package的差距就是module"可以路由"
也就是說,如果執行netpath/mymodule/moduleincontroller/index之類的路徑
我們是可以像自己本身專案的PHP一樣使用的

然後實際上用的方式,可以用HMVC直接請求回傳結果,拿來給原本的主程式使用

首先我們模組裡面的控制器使用以下程式:
namespace hellomodule;
Class Controller_Hellomodule extends \Controller{
    public function action_index(){
        echo Model_mymodel::hellol();
     
        if( ! \Request::is_hmvc()){
            echo 'Normal request!';
        }
        else{
            echo 'HMVC request!';
        }
    }
}

模組裡面的模型(註:module裡面的model)使用以下的程式:
namespace hellomodule;
class Model_mymodel extends \Model{
    public static function hellol(){
         return 'I already hate hello world!<br/>';
    }
}

此時我們直接連線到hellomodule/hellomodule/index
將得到:
I already hate hello world!
Normal request!

但是如果我們在原本的控制器用一個HMVC式的請求
$temptext  = Request::forge('hellomodule/hellomodule/index',false)->execute();

此時$temptext 裡面的回傳內容如果被echo出來,將會是:
I already hate hello world!
HMVC request!

FuelPHP 套件筆記

Posted by ayuayu on

最低限度設置:

app/config裡面的 'packages'  項目要做好路徑設定
'filename'=>PKGPATH.'filename/'大概這樣的形式

packages裡面最低限度要有classes資料夾,裡面放一個自己要用的class
然後底下要有bootstrap.php

Autoloader::add_core_namespace('套件名稱',true);
Autoloader::add_classes(array(
  'NAMESPACE\\CLASSNAME' => __DIR__.'/PATH/filename.php',
));

注意
1.classname和filename可以不同
2.package裡面的檔案要有namespace,不然會redlare error

全部都做好以後,就可以直接使用package裡面的class,可以呼叫裡面的靜態function,不需要再加任何namespace

Example:
'packages'  => array(
    'ayu'=>PKGPATH.'ayu/',
),

測試設置: ayu/classes/ayu.php  以及ayu/bootstrap.php

ayu.php內容如下(為了確認class名稱與檔名是分開設定,這邊我們弄成不同的名稱
而namespace太容易辨識了就不再做額外處理)
<?php
namespace ayu;
class Tsukimiya{
 public static function holyworld(){
  echo 'Holy Package Loading and Working Success<br/>';
 }
}

bootstrap.php內容如下:
<?php
Autoloader::add_core_namespace('ayu',true);
Autoloader::add_classes(array(
  'ayu\\Tsukimiya' => __DIR__.'/classes/ayu.php',  //即NAMESPACE\\CLASSNAME' => __DIR__.'/PATH/filename.php',
));

任意一個Controller裡面置入以下測試內容:
Tsukimiya::holyworld();

就可以得到正確的輸出
Holy Package Loading and Working Success


FuelPHP 擴充實作篇

Posted by ayuayu on

學官網在classes下面直接加入 class MyConfig extends Config,然後隨便呼叫一個已經設定的設定值

echo "MyConfig::get('config_key1') = ".MyConfig::get('config_key1');

得到MyConfig::get('config_key1') = config_value1

隨便裡面加個函數並echo "MyConfig::test() = ".MyConfig::test();
public static function test(){
    return 7;
}
得到MyConfig::test() = 7

因此隨便副寫個get
public static function get($item, $default = NULL){
    return 1;
}

結果MyConfig::get('config_key1')輸出1,代表可以簡單用自訂函數去override

但是如果一定要使用官方的核心指令,那就必須要用同名class 同名函數去override
另外也必須正確把這個同名class在bootstrap當中預先add class,才能生效

實際上,FuelPHP有擴充限制,具體限制那些在官網可以看到
http://fueldocs.ycnets.com/general/extending_core.html

example 複寫log
class Log extends Fuel\Core\log{
 public static function info($msg, $method = null){
  return static::write(\Fuel::L_INFO, 'troll my info method ver2'.$msg, $method);
 }
}

Autoloader::add_classes(array(
    'Log'=>APPPATH.'classes/log.php',
));

如此,以後紀錄的info訊息都會加上一些自訂文字在裡面

FuelPHP 擴充詳解

Posted by ayuayu on 2014/07/18

基本上老話題一下
官網只要你沒實作出來,文件都看不懂,因為他的Example給的通常都很詭異

那他到底在寫啥呢?

擴充但不取代核心類別
也就是你用任何自己的自訂名稱去extend核心類別的項目
例如我可以用Mylog去extend Log   ,我可以用MycOnFiG去extend Config
但是同名不行,不是掛掉就是沒效果

擴充且取代核心類別
這意思其實是說,我不管怎樣,下核心指令都想要用自己的
也就是例如,我view東西就是要自己的方法,log就是要有自己處理過的
這時候就去用同樣的名稱去extend,並且在bootstrap去add classes

然後最大的問題其實在

FuelPHP只有這兩種方法可以擴充,那些什麼很曖昧的作法是不存在的
所有曖昧或不合理的用法只有報錯,不執行或直接掛掉這三種狀況
(不要懷疑真的可能掛掉,例如你add class裡面丟config,又真的有那檔案,執行下去就死給你看)
例如我能不能偷偷用一個同名extend一下但不取代
或者能不能用自己方法去實作最後再回來假裝表面銜接後add class一下

因此,若當你已經知道那機制的內容,回去重看文件
恩,他寫的沒什麼大問題啊?
但是你交給一個還不懂狀況的:
fking shxt,那官網到底在寫O小朋友.....

php var_dump 突然無法顯示全部

Posted by ayuayu on 2014/07/17

如果有看到什麼 ...more element啥的
一定是不小心裝到什麼xdebug

以ubuntu為例,來到/etc/php5/mods-avaliable/xdebug.ini裡面(或php.ini,自行嘗試)
加入xdebug.var_display_max_children=512 (預設是128,沒幾條就會超過了)

然後重開apache2
不放心的話去phpinfo看設定

如果發現層數明顯沒有引完
則是去設定xdebug.var_display_max_depth

可能是預防太多層螢幕顯示不好看吧,要設幾層自己衡量了

FuelPHP的ViewModel 還真的消失了

Posted by ayuayu on

一開始就在想說 這個實際上不算MVC的V(連一半都不到)
且還是optional(沒有必要實作)

新版的1.7.2已經變成Presenter Class
https://github.com/fuel/core/wiki/Changelog-v1.7.2

實際上,使用HMVC就會發現,即使請求回來頂多也就是"修正view的需求"
幾乎不會在HMVC裡面直接連過去(會這樣做的話,你應該會考慮直接讓這項目升級成主架構)

舊版本如果真的有用ViewModel意味著有小改寫的必要,不過幅度應該不大XD

補充一提,FuelPHP的V即使在HMVC也仍然能用
同樣的\Response::forge(\view::forge('PATHLINK')); 是會正確生效的
但是MVC架構卻不放在一起,只能說FuelPHP認為他本來就不是同一個層級的東西吧

FuelPHP各種try

Posted by ayuayu on 2014/07/11

https://drive.google.com/file/d/0Bz9IvLZNUkriUkdXc1l5OHZ4Y00/edit?usp=sharing

改自訂環境,CSRF,路由應用的小try

SSL基本理解

Posted by ayuayu on

SSL 產生憑證參考網站1 http://note.tc.edu.tw/662.html
SSL 產生憑證參考網站2 http://wiki.centos.org/zh-tw/HowTos/Https
SSL 產生憑證參考網站3 http://twpug.net/x/modules/newbb/viewtopic.php?viewmode=compact&order=ASC&topic_id=2893&forum=22
基本上照著跑就可以

由於沒有真的上線需求,就先不去做真的認證了
產生的三個檔案分別放在

/etc/testssl/certs/ca.crt
/etc/testssl/private/ca.csr
/etc/testssl/private/ca.key

接下來應該是ubuntu需求(上面的連結是centOS設法,有些微不同)

首先先到/etc/apache2/sites-avaliable/default-ssl做基本設定

SSLCertificateFile /etc/testssl/certs/ca.crt
SSLCertificateKeyFile /etc/testssl/private/ca.key

然後啟動 ssl module

啟用 ssl 模組
a2enmod ssl
啟用 ssl 虛擬站台
a2ensite default-ssl
安裝 ssl 套件
apt-get install openssl ssl-cert
重啟 apache
/etc/init.d/apache2 restart

然後直接把檔案改https,應該就可以連上了

不過這時候會發現一件事情,那就是我們的route設定不見了
由於各個linux版本不同,以現在自己手上的ubuntu為例子,要到/etc/apache2/sites-avaliable/default-ssl裡面
往下看到DocumentRoot做相關設定,這樣就會正常了

FuelPHP每次連線必warning的修正

Posted by ayuayu on 2014/07/08

WARNING - 2014-07-08 14:06:43 --> Fuel\Core\Fuel::init - The configured locale en_US is not installed on your system.

基本上每次連都會在log留下一次紀錄
然後假使這不是單機測試而是大量使用...那就GG了

註:自己安裝哪個語言可以在linux環境以下用echo $LANG來查看

找到APPPATH/config.php

然後把locale設定弄成空字串,再來訊息就不會再出現了

Linux基本理解

Posted by ayuayu on 2014/07/04

https://drive.google.com/file/d/0Bz9IvLZNUkriLXBqVUJmNFkzeUU/edit?usp=sharing


應該不會掛,吧(?

理解了一次的結果,總之先做個紀錄