codeigniter 我应该对每一段代码进行单元测试吗

i7uq4tfw  于 2022-12-06  发布在  其他
关注(0)|答案(3)|浏览(162)

我最近开始了单元测试,我想知道,我应该为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');
    }
}

我哪里做错了?

hsgswve4

hsgswve41#

在我看来,测试代码比生产代码多是正常的。但是测试代码往往是直接的,一旦你掌握了窍门,编写测试就像是一个不用动脑筋的任务。
话虽如此,如果您发现测试代码太复杂,无法编写/覆盖生产代码中的所有执行路径,这是进行某些重构的一个很好的指标:你的方法可能太长,或者试图做几件事,或者有太多的外部依赖项,等等...
另一点是,测试覆盖率高是好的,但不需要是100%或某个很高的数字。有时候有些代码没有逻辑,比如简单地将任务委托给其他人的代码。在这种情况下,你可以跳过测试它们,并使用@codeCoverageIgnore注解在代码覆盖率中忽略它们。

yhqotfr8

yhqotfr82#

在我看来,测试更多的是代码,这是合乎逻辑的,因为你必须测试多个场景,必须提供测试数据,你必须检查每个案例的数据。
通常80%的测试覆盖率是一个很好的值。在大多数情况下,没有必要测试100%的代码,因为你不应该测试例如setter和getter。不要只测试统计信息;)

azpvetkf

azpvetkf3#

答案是这要看情况而定,但通常不是。如果您要发布一个库,那么大量的测试是很重要的,甚至可以帮助创建文档的示例。
对于内部项目,你可能希望把代码集中在复杂的函数上,如果它们出错的话会很糟糕。对于每一个测试,在这里而不是在父函数中进行测试有什么价值?
您需要避免的是测试太多依赖于实现细节的东西,或者说私有方法/函数,否则,如果您更改结构,您将发现您必须重复重写整个测试套件。
最好在更高的层次上测试公共函数或模块之间边界上的任何东西,在最高级别的一些测试应该产生合理的收敛,并确保代码以实际调用的方式工作。这并不是说低级别的函数不应该有测试,但在那个级别,检查边缘情况比针对每个功能测试典型情况要多。
不要创建测试来增加覆盖率,而是创建测试来覆盖您发现的bug并修复它们,创建针对新功能的测试(无论如何您都必须手动测试它)。创建测试来防止不应该发生的坏事情。应该删除或更改在重构过程中容易中断的脆弱测试,以减少对功能实现的依赖。

相关问题