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吧..
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言