2011-04-04 96 views
4

我在CakePHP中进行单元测试时遇到了一些问题,特别是在测试数据库插入/更新时。比方说,我有一个模型,它是这样的:测试驱动的开发 - 单元测试(在CakePHP中)

class User { 
    var $name = 'User'; 

    function updatePassword($data) { 
    return $this->updateAll($data); 
    } 
} 

class UserTestCase { 
    function testUpdatePassword() { 
    $tmpData = array(
     'User' => array(
     'password' => sha1(uniqid('', true)) //dummy pass 
    ); 

    $result = $this->User->updatePassword($tmpData); 

    $this->assertTrue($result); 
    } 
} 

我的问题是,在我的测试案例:

  • 我必须提供将通常从形式
  • 检索到的虚拟数据
  • 虚拟数据的格式没有考虑到实际表单数据可能不正确的事实
  • 我只测试更新是否成功:它似乎需要很多努力才能创建所有虚拟数据测试这个

这个例子似乎有点做作(I可以做在控制器的update而不必创建例如一个额外的模型法),但主要的一点是,测试更新/插入时,该数据是伪数据和从表单中检索的数据可能会有所不同,但好处似乎并不高于成本。

您对TDD和单元测试的方法非常感谢,并且您一般会尝试给出什么样的覆盖范围会很好。

干杯

TDD对我
+0

我建议您阅读一本关于此主题的书,例如:https://leanpub.com/cakephpunittesting/ – rrd 2013-04-13 12:24:57

回答

8

有人曾经说单元测试应该讲一个故事。这种方法可以帮助您编写测试,这些测试对于您正在编写的应用程序而言是有意义的。撰写描述性的名称为每个测试方法,如:

function testUpdatingInsecurePasswordShouldFail() { 
    $data = array('User' => array(
     'password' => 'password' 
    )); 
    $result = $this->User->updatePassword($data); 
    $this->assertFalse($result); 

    $data = array('User' => array(
     'password' => '' 
    )); 
    $result = $this->User->updatePassword($data); 
    $this->assertFalse($result); 
} 

已经告诉了不安全的密码的“故事”,就可以让新的测试通过,那么写的型号代码。另一个例子:

function testUpdatingStrongPasswordShouldSucceed() { 
    $data = array('User' => array(
     // forget about hashing for the moment 
     'password' => 'battery hoarse collect maple' 
    )); 
    $this->User->updatePassword($data); 
    $result = $this->User->find('count', array(
     'conditions' => array(
      // making some assumptions about the test data here 
      'User.username' => 'test_user1', 
      'User.password' => 'battery hoarse collect maple', 
     ), 
    ); 
    $this->assertEqual($result, 1); 
} 

注意我们正在做更多的工作来验证更新是否正常工作。当测试框架开始提取错误和回归时,您会很高兴您付出了额外的努力。好的描述测试名

一边好处是,现在我们可以使用cake test --testdox选项输出的结果可以理解英语:

[x] Updating insecure password should fail 
[x] Updating strong password should succeed 
3

利益(一旦你完全让你的头包裹着它):

  1. 我可以调试我的代码,而无需浏览器
  2. 如果我的代码是依赖于各种部分代码和我(或其他人)做了一个意外的改变,意外地破坏了我以前测试过的东西,我的自动化单元测试将立即捕捉到这个结果
  3. (个人)它改变了我对输入的想法 - 而不是输入g数据手动转换为文本字段,我发现自己开始考虑可能来自脚本而不是浏览器的输入 - 真的让我专注于清理输入更多
  4. 自动化测试 - 一旦系统完成,我就可以运行所有我的测试,并让他们在几秒钟内执行,以确保一切正常,而不是尝试手动运行整个系统,这可能需要几个小时,这取决于复杂性。
2

ddawber,

你提三点:

1.

我必须提供虚拟数据, 通常会从 形式

检索您应该看一看到CakePHP的fixtures

2.

虚拟数据 的格式不考虑到这样的事实 是实际表格数据可能是 不正确

表格数据根据模型的验证规则see here进行验证。

3.

我只测试 更新是否成功:好像努力了很多 创建的所有虚拟数据 测试这个

这应该然后简单地通过编写一个测试方法来解决(并且只挑选相关案例),考虑1.和2.。 也许您对事实感兴趣,即CakePHP开发人员可以在2.0版本中从simpletest切换到phpunit,这可以帮助您规划您的工作。

无论如何,我们都可以轻松进入CakePHP的测试工具。

编辑0: 代码覆盖的第四点似乎有争议。如果你想达到100%的覆盖率,你必须写很多模拟对象,只是为了确保控制器的行为在你调用它时被实际调用。写这样的东西对于框架开发者来说是一项任务,省略编写这种多余的代码直接影响了代码覆盖率。

+0

+1 for fixtures – kaklon 2011-10-11 14:14:26