2012-04-14 39 views
1

對於我正在開發的PHP應用程序,我需要讀取當前的git修訂版SHA,當然,我可以通過使用shell_exec或反引號來輕鬆地執行git命令行客戶端。我該如何測試執行命令行程序的PHP類方法?

我明顯地把這個調用放到了它自己的方法中,這樣我就可以輕鬆地隔離和嘲笑我的其餘單元測試。所以我的課看起來有點像這樣:

class Task_Bundle 
{ 

    public function execute() 
    { 
     // Do things 
     $revision = $this->git_sha(); 
     // Do more things 
    } 

    protected function git_sha() 
    { 
     return `git rev-parse --short HEAD`; 
    } 
} 

當然,雖然我可以嘲笑git_sha測試大多數類的,我掙扎,看看如何測試實際git_sha()方法,因爲我不沒有看到爲它創建一個已知狀態的方法。我認爲單元測試中沒有任何實際價值可以稱爲git rev-parse來比較結果嗎?我想知道至少斷言該命令已經運行,但我看不出有什麼辦法可以獲得由PHP執行的shell命令的歷史記錄 - 即使我指定PHP應該使用BASH而不是SH,歷史列表出現了空,我認爲,因爲單獨的反引號執行是單獨的終端會話。

我很樂意聽到關於如何測試這個問題的任何建議,或者可以保留未經測試的方法並在將來維護應用程序時小心一點。

+1

我認爲,根據定義,這不再是一個*單元*測試...你可以測試它,但不是真正與它使用的任何東西分開。 – cHao 2012-04-14 23:13:30

+0

我想我想要的仍然是一個單元測試,但通過驗證我的代碼以預期的方式調用git的公共API,進一步進行了嘲諷。例如,如果git是一個外部PHP庫中的類,我會得到它的一個模擬,並聲明rev-parse方法是用期望的參數調用的。 – acoulton 2012-04-14 23:36:10

回答

5

雖然你已經接受一個答案,讓我發佈一些關於什麼方法單元測試應該工作,因爲即使發佈的解決方案確實有效並且確實很好,它也會有一些退步。

首先你不想真正執行你的命令,因爲這會測試一個外部軟件。從這個時刻開始,你將依賴於你無法控制的外部事物(如果我想在我的電腦上測試你的軟件,會發生什麼?我必須安裝git或git-mock嗎?)。你真正想做的是看命令行命令是否正確並且執行得很好。

因爲我以前就一直在努力,所以我做了:我創建了一個執行shell_exec的類。我希望與shell進行交互的地方,我注入並使用它。所以爲了測試,我可以嘲笑這個類,看看是否執行了正確的方法,以及是否設置了正確的參數。

這樣做有很多好處:

  • 我與外殼進行交互的一個點。如果將來有什麼變化,或者如果我在執行命令之前需要做任何事情,我可以將行爲添加到類中。 PHP函數封裝得很好。
  • 它適用於每臺PC,即使shell_exec命令由於任何原因而不起作用。測試在每臺PC(開發機器,測試服務器,集成服務器)上執行,無需擔心外部依賴性。

當然要驗證您的軟件是一個整體,您必須進行不會嘲笑任何東西的集成測試。但這是完全不同的情況。 Unittests應該確保你的類(或方法)做它需要做的事情。有時候這並不明確,因爲你可能決定在某個地方使用真正的課程,因爲嘲笑它會導致很多開銷。但是,就我而言,如果它依賴於可能沒有安裝或因某種原因可能無法運行的外部庫/軟件,它不再是單位測試。

0

我想如果你真的想要,你可以寫一個虛擬的git,並將它的位置預先設置到你的環境的PATH。讓它做你需要做的任何驗證,然後產生與真實情況一致的輸出。如果你想要的話,你甚至可以把它轉發到真實的git,但是你不能保證結果。

你必須要小心,但是......你只想做得足夠好,這樣班級就可以被愚弄到認爲它真的是git,但是如果你讓它變得太像真實的東西那樣,這相當於編寫你自己的一半版本的Git。

+0

謝謝,我認爲這是一個非常整潔的解決方案,並且相當於$ this-> getMock()的命令行。我實際上並不是想要驗證git是否按預期運行,所以我認爲一個簡單的腳本將接收到的參數寫入磁盤進行驗證,並輸出一個假sha作爲返回值就足夠了。如果git改變它們的命令行參數(本質上是API),那麼我需要處理那些外部庫的情況。當我幾個小時後回到機器上時,我會試一試,但我認爲這很可能會被接受。謝謝! – acoulton 2012-04-14 23:40:58

+0

好的,這幾乎工作 - 我不得不使用'putenv'而不是直接設置$ _ENV ['PATH']。我正在考慮將這個功能包裝到CLI模擬生成器中,以允許像'$ this-> getMockCLI('git') - > expectsArgs('rev-parse --short HEAD') - > will($ this - > returnValue('abcdefg'));'我認爲這可能更普遍有用,並允許測試非零返回等。 – acoulton 2012-04-15 04:15:17

1

至少你可以做類似的檢查將retured字符串匹配/^[abcdef0-9] {7} $/

+0

感謝您的建議 - 一個好主意,但我喜歡@ cHao的更多,這也將允許我來測試我的代碼是否正確處理錯誤條件等。 – acoulton 2012-04-15 04:19:18