簡體   English   中英

我應該對每段代碼進行單元測試嗎

[英]Should I be unit testing every piece of code

我最近一直在開始單元測試,我想知道,我應該為 100% 的代碼覆蓋率編寫單元測試嗎?

當我最終編寫的單元測試代碼多於生產代碼時,這似乎是徒勞的。

我正在寫一個 PHP Codeigniter 項目,有時我寫這么多代碼似乎只是為了測試一個小的 function。

例如這個單元測試

public function testLogin(){
    //setup
    $this->CI->load->library("form_validation");
    $this->realFormValidation=new $this->CI->form_validation;
    $this->CI->form_validation=$this->getMock("CI_Form_validation");
    $this->realAuth=new $this->CI->auth;
    $this->CI->auth=$this->getMock("Auth",array("logIn"));
    $this->CI->auth->expects($this->once())
                   ->method("logIn")
                   ->will($this->returnValue(TRUE));

    //test
    $this->CI->form_validation->expects($this->once())
        ->method("run")
        ->will($this->returnValue(TRUE));
    $_POST["login"]=TRUE;
    $this->CI->login();
    $out = $this->CI->output->get_headers();
    //check new header ends with dashboard
    $this->assertStringEndsWith("dashboard",$out[0][0]);

    //tear down
    $this->CI->form_validation=$this->realFormValidation;
    $this->CI->auth=$this->realAuth;

}
public function badLoginProvider(){
    return array(
        array(FALSE,FALSE),
        array(TRUE,FALSE)
    );
}
/**
 * @dataProvider badLoginProvider
 */
public function testBadLogin($formSubmitted,$validationResult){
    //setup
    $this->CI->load->library("form_validation");
    $this->realFormValidation=new $this->CI->form_validation;
    $this->CI->form_validation=$this->getMock("CI_Form_validation");

    //test
    $this->CI->form_validation->expects($this->any())
        ->method("run")
        ->will($this->returnValue($validationResult));
    $_POST["login"]=$formSubmitted;
    $this->CI->login();
    //check it went to the login page
    $out = output();
    $this->assertGreaterThan(0, preg_match('/Login/i', $out));

    //tear down
    $this->CI->form_validation=$this->realFormValidation;
}

對於這個生產代碼

public function login(){
    if($this->input->post("login")){
        $this->load->library('form_validation');
        $username=$this->input->post('username');
        $this->form_validation->set_rules('username', 'Username', 'required');
        $this->form_validation->set_rules('password', 'Password', "required|callback_userPassCheck[$username]");
        if ($this->form_validation->run()===FALSE) {
            $this->load->helper("form");
            $this->load->view('dashboard/login');
        }
        else{
            $this->load->model('auth');
            echo "valid";
            $this->auth->logIn($this->input->post('username'),$this->input->post('password'),$this->input->post('remember_me'));
            $this->load->helper('url');
            redirect('dashboard');
        }
    }
    else{
        $this->load->helper("form");
        $this->load->view('dashboard/login');
    }
}

我哪里錯了?

在我看來,測試代碼不僅僅是生產代碼,這是正常的。 但是測試代碼往往是直截了當的,一旦你掌握它,它就像編寫測試一樣簡單。

話雖如此,如果您發現您的測試代碼太復雜,無法編寫/覆蓋生產代碼中的所有執行路徑,那么這是重構的一個很好的指標:您的方法可能太長,或者嘗試做幾件事,或者有這么多外部依賴等...

另一點是,擁有高測試覆蓋率是好的,但不需要100%或一些非常高的數字。 有時代碼中沒有邏輯,就像代碼只是將任務委托給其他人一樣。 在這種情況下,您可以跳過測試它們並使用@codeCoverageIgnore注釋在代碼覆蓋率中忽略它們。

在我看來,它的邏輯是測試代碼更多,因為你必須測試多個場景,必須提供測試數據,你必須檢查每個案例的數據。

通常,80%的測試覆蓋率是一個很好的價值。 在大多數情況下,沒有必要測試100%的代碼,因為你不應該測試例如setter和getter。 不要只測試統計數據;)

答案是視情況而定,但通常不會。 如果您要發布庫,那么大量測試很重要,甚至可以幫助創建文檔示例。

在內部項目中,您可能希望將代碼集中在復雜的函數和如果它們出現 go 錯誤時會很糟糕的事情上。 對於每個測試事物,在這里進行測試而不是在父 function 中進行測試的價值是什么?

你想要避免的是測試太多依賴於實現細節的任何東西,或者說私有方法/函數,否則如果你改變結構你會發現你將不得不重復重寫整個測試套件。

最好在更高級別進行測試,公共函數或模塊之間邊界處的任何東西,在最高級別進行一些測試應該會產生合理的收斂並確保代碼以實際調用代碼的方式工作. 這並不是說較低級別的函數不應該進行測試,而是在該級別上檢查邊緣情況比針對每個 function 對典型情況進行測試更多。

與其創建測試來增加覆蓋率,不如創建測試來覆蓋您發現並修復的錯誤,在您無論如何都必須手動測試新功能時創建針對新功能的測試。 創建測試以防止不應該發生的壞事。 應刪除或更改在重構期間容易破壞的脆弱測試,以減少對 function 實施的依賴。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM