单元测试访问器(getter和setter)

tak*_*hin 27 php phpunit unit-testing accessor getter-setter

给出以下方法:

public function setFoo($foo) {
    $this->_foo = $foo;
    return $this;
}

public function getFoo() {
    return $this->_foo;
}
Run Code Online (Sandbox Code Playgroud)

假设,未来可能会更改为更复杂:

  • 你会如何为这些方法编写单元测试?
  • 只有一种测试方法?
  • 我应该跳过这些测试吗?
  • 代码覆盖怎么样?
  • @covers注释怎么样?
  • 也许在抽象测试用例中实现一些通用的测试方法?

(我使用Netbeans 7)

这似乎是浪费时间,但我不介意IDE是否会自动生成这些测试方法.

要从塞巴斯蒂安·伯格曼博客的评论中获得评论:

(就像测试getter和setter一样 - 失败!).无论如何,如果他们失败了; 那些依赖它们的方法不会失败吗?

那么,代码覆盖怎么样?

Dan*_*nie 8

如果你做TDD,你应该为getter和setter写一个测试.太.即使您的代码非常简单,也不要在没有测试的情况下编写一行代码.

它是一种宗教战争,可以使用串联的getter和setter进行测试,或者通过使用单元测试框架功能访问受保护的类成员来隔离每个.作为一个黑盒子测试人员,我更喜欢将我的单元测试代码绑定到公共API,而不是将其与具体的实现细节联系起来.我期待改变.我想鼓励开发人员重构现有代码.类内部不应该影响"外部代码"(在这种情况下是单元测试).我不想在内部更改时打破单元测试,我希望它们在公共API改变或行为改变时中断.好的,好的,如果单元测试失败,请不要指出唯一的问题来源.我必须查看getter和setter来找出导致问题的原因.大多数情况下,你的getter非常简单(少于5行代码:例如返回和带有异常的可选null检查).因此,首先检查这个并不是什么大问题,也不会耗费时间.检查setter的快乐路径大部分时间只是稍微复杂一些(即使你有一些验证检查).

尝试隔离您的测试用例 - 为SUT(被测试对象)编写一个测试,验证其正确性,而无需使用其他方法(除了上面的示例).您隔离测试越多,您的测试就越发现问题.

根据您的测试策略,您可能只想覆盖快乐路径(实用程序员).或者也是悲伤的.我更愿意涵盖所有执行方案.当我认为我发现所有执行模式时,我检查代码覆盖率以识别死代码(不识别是否存在未覆盖的执行路径 - 100%代码覆盖是一个误导性指示符).

黑盒测试者最好在严格模式下使用phpunit,并使用@covers隐藏附属文件.

当你编写单元测试时,你在A类上的测试应该独立于B类执行.所以你对A类的单元测试不应该调用/覆盖B类的方法.

如果要识别过时的getter/setter和其他"死"方法(生产代码不使用),请使用静态代码分析.您感兴趣的指标称为"方法级别的传入耦合(MethodCa)".不幸的是,这个度量标准(ca)在PHP Depend中的方法级别不可用(请参阅:http://pdepend.org/documentation/software-metrics/index.html http://pdepend.org/documentation/software-metrics /afferent-coupling.html).如果您真的需要它,请随意将其贡献给PHP Depend.从同一个类中排除调用的选项有助于获得没有"附带"调用的结果.如果你确定一个"死方法",试着弄清楚它是否意味着在不久的将来使用(对于另一个具有@depricated注释的方法),否则将其删除.如果它仅在同一个类中使用,请将其设为privat/protected.不要将此规则应用于库代码.

计划B:如果您有验收测试(集成测试,回归测试等),您可以在不同时运行单元测试且没有phpunits严格模式的情况下运行该测试.这可能会导致代码覆盖率非常相似,就像您分析了生产代码一样.但在大多数情况下,您的非单元测试不如您的生产代码那么强大.如果该计划B与生产代码"相同"以获得有意义的结果,则取决于您的纪律.

进一步阅读: - 书:实用程序员 - 书:清洁代码

  • @AnonymousDownvoter:当你向下投票时,请告诉我为什么你认为这篇文章没有帮助或错误.请发表评论. (2认同)

edo*_*ian 6

好问题,

我通常会尽量不直接测试getter和setter,因为我看到只测试实际执行某些操作的方法会带来更大的好处.

特别是当不使用TDD时,这有一个额外的好处,就是向我展示我不会在我的单元测试中使用的setter,这表明我的测试是不完整的,或者不使用/不需要setter."如果我可以执行所有"真正的"代码而不使用那个setter,为什么会这样."

当使用流畅的setter时,我有时会编写一个测试来检查setter的'fluent'部分,但通常会在其他测试中介绍.

要回答你的清单:

  • 只有一种测试方法?

这是我最不喜欢的选择.全部或全部.只测试一个并不容易让其他人理解并看起来"随机"或需要以某种方式记录.

评论后编辑:

是的,对于"琐碎的"获取/设置测试我每个属性只使用一个方法,这可能取决于案例,甚至只有一个方法用于整个类(对于具有许多getter和setter的值对象,我不想编写/维护许多测试)

  • 你会如何为这些方法编写单元测试?
  • 我应该跳过这些测试吗?

我不会跳过它们.也许吸气剂取决于你拥有多少(我倾向于只写我真正需要的吸气剂)但完全覆盖课程的任务不应该因为吸气剂而失败.

  • 代码覆盖怎么样?
  • @covers注释怎么样?

随着@covers我的采取总是"到处使用它或根本不使用它".混合两种"样式"的测试会消除注释的一些好处,并且对我来说看起来"未完成".

  • 也许在抽象测试用例中实现一些通用的测试方法?

对于像价值对象这样可以很好地工作的东西.一旦传入具有类型提示的对象/数组,它可能会破坏(或变得更复杂),但我原本更喜欢它而不是为500个getter和setter编写手动测试.