Useful Unit Test

Posted by ayuayu on 2014/12/18

先不說要交出去的
這篇探討的是"怎麼用Unit Test"幫到自己
因此什麼理論什麼合理性,什麼覆蓋率請直接丟掉,至少對成品沒有直接幫助

以下以phpunit vs php開發為基準,java可能另有狀況,請勿直接當同一種
<請點選連結查看全文>




我不認同先寫單元測試才寫程式才是對的,這很容易侷限撰寫方式和卡狀況
相對的,我認為做完一段落程式才回來寫測試確認有沒有弄錯,能不能執行才是合理的

測試重點如下:

1.至少確定可以按照期望的run
測試幾種狀況"確認自己邏輯",絕非"證明自己程式運作沒有任何問題並且做過充分判斷"
因為你如果真的想達到這個目標,寫一個跟原本一模一樣的程式當判斷式才能符合
而這絕非測試需求,也測不到什麼東西

所以千萬不要斷言正則表達式,要這樣做還不如換幾個參數試試會不會出問題

2.mock object很好用,不過有一個小條件
"發現花了一段時間還沒有完成跡象,請直接放棄"
我們是要測能不能動,不是要交報告,發現太難mock,如果是原本程式架構的問題
常常不是複雜架構,就是這其實根本mock不出來
即便是其實有結果只是當下想不到怎麼mock,我都建議放棄,因為並不是跑不了Unit Test就從此無法測試,不會測試

實際上,mock很好用,有許多未完成的function都可以當成已完成來測試
對大部分接外部資料並能妥善切割的前提,測試算是蠻方便的

3.Unit Test重點是 Assert
很重要因此再說一次,請把重心放在Assert,什麼setUp tearDown只不過是輔助工具,而且即使不用也沒關係

因為即便是你根本不把他當成test case
如果你有以下的想法,代表你至少懂單元測試一半了
而是覺得我應該要new什麼A物件,然後執行Afunction得到什麼值再new另一個B物件代入初始化,如果回傳是我預想的x值,那我這程式大致就算能正常運作

實際幹一次就直接變成這樣
class testtroll extends TestCase{
    function test_myTroll(){
        $a = new A();
        $value = $a->Afunction();
        $breturn = new B($value);
        $this->assertEqual($breturn, 'x')
        print_r($breturn)
    }
}

以上寫法完全跟unit test正規方式差很多
可是我覺得單元測試本來就該是這種東西,原因如下:
1.他可以真正測你程式能不能跑(能不能run,不是有沒有correct)
2.開發速度最快,最直觀,最容易看出來是否難解需要放棄
3.這樣的測試不影響原程式,且可以重複執行
4.看看回傳值結果是否如自己預期

這可能不是正規的unit test
但絕對是對你有幫助的unit test

比較複雜的狀況
1.需要mock
2.測private
這兩種還可以接受,但最多簡單用一下,如果發現寫起來變超麻煩,一樣,跳過吧
更複雜的想都不要想,比原本程式還花時間的開發,你還不如去改進原本程式或開發新程式

然後有人可能會說,如果遇到"其他的XX狀況怎麼辦"
我只能說,我反對在單元測試幹這種事情
因為什麼時候該做這種測試,不是很明顯的嗎?
Exception Unit Test
好吧還是舉個例子大概會像這樣

/**
     * @expectedException InvalidDepositAmountException
     */
    public function testDepositAmountLowerThenZero() {
        $this->_account->deposit(-200);
    }

真的有Exception才測,不然額外狀況可以無限上綱,你測都測不完
把程式裡面的condition貼上來搞不好測還不夠還要配合測試優化好幾次,這就本末倒置了
拜託絕對不要做這種事情

老話一句
單元測試是要幫助自己開發的,不是拿來交作業的

沒有留言:

張貼留言