【问题标题】:Should I be unit testing every piece of code我应该对每一段代码进行单元测试吗
【发布时间】:2014-03-25 02:46:04
【问题描述】:

我最近开始进行单元测试,想知道是否应该编写单元测试以实现 100% 的代码覆盖率?

当我最终编写的单元测试代码多于生产代码时,这似乎是徒劳的。

我正在编写一个 PHP Codeigniter 项目,有时我似乎编写了这么多代码只是为了测试一个小功能。

例如这个单元测试

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');
    }
}

我哪里错了?

【问题讨论】:

    标签: php codeigniter unit-testing


    【解决方案1】:

    在我看来,测试代码多于生产代码是正常的。但是测试代码往往很简单,一旦你掌握了它,编写测试就像一个不费脑筋的任务。

    话虽如此,如果您发现您的测试代码太复杂而无法编写/无法覆盖生产代码中的所有执行路径,这对于进行一些重构来说是一个很好的指标:您的方法可能太长,或者尝试执行多个东西,或者有这么多的外部依赖等等......

    另外一点是测试覆盖率高是好的,但不需要是 100% 或某个非常高的数字。有时有些代码没有逻辑,比如只是将任务委托给其他人的代码。在这种情况下,您可以跳过测试它们并使用@codeCoverageIgnore 注释在您的代码覆盖范围内忽略它们。

    【讨论】:

      【解决方案2】:

      在我看来,测试更多的代码是合乎逻辑的,因为您必须测试多个场景,必须提供测试数据并且您必须检查每个案例的数据。

      通常 80% 的测试覆盖率是一个不错的值。在大多数情况下,没有必要测试 100% 的代码,因为您不应该测试例如 setter 和 getter。不要只测试统计数据;)

      【讨论】:

      • 谢谢,不测试 setter 和 getter 意味着诸如 public function foo(){ return somePrivateFoo; }
      • 是的,目标是测试您的代码,而不是 PHP、Java 或任何其他编程语言,也不是测试任何框架的目标。因此,测试 getter 和 setter 只会测试 PHP 是否可以设置、获取或返回值;)更多关于您的程序是否正确使用了这些东西
      猜你喜欢
      • 1970-01-01
      • 2020-05-30
      • 1970-01-01
      • 2011-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-05
      相关资源
      最近更新 更多