热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

Giventhefollowingmethods:鉴于以下方法:publicfunctionsetFoo($foo){$this->_foo$foo;

Given the following methods:

鉴于以下方法:

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

public function getFoo() {
    return $this->_foo;
}

Assuming, they may be changed to be more complex in the future:

假设它们在未来会变得更加复杂:

  • How would you write unit tests for those methods?
  • 如何为这些方法编写单元测试?
  • Just one test method?
  • 只是一个测试方法?
  • Should I skip those tests?
  • 我应该跳过这些测试吗?
  • What about code coverage?
  • 代码覆盖呢?
  • How about @covers annotation?
  • @covers注释呢?
  • Maybe some universal test method to implement in the abstract test case?
  • 在抽象的测试用例中实现什么通用的测试方法?

(I use Netbeans 7)

(我使用Netbeans 7)

This seems like a waste of time, but I wouldn't mind if IDE would generate those test methods automatically.

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

To qoute from the comment of Sebastian Bergman's blog:

来自塞巴斯蒂安·伯格曼博客评论的qoute:

(it's like testing getters and setters -- fail!). In any case, if they were to fail; wouldn't the methods that depend on on them fail?

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

So, what about the code coverage?

那么,代码覆盖率呢?

3 个解决方案

#1


6  

Good Question,

好问题,

i usually try not to test getters&setters directly since i see a greater benefit in testing only the methods that actually do something.

我通常尽量不直接测试getters&setters,因为我发现只测试实际执行的方法有更大的好处。

Especially when not using TDD this has the added benefit of showing me setters that i don't use in my unittests showing me that ether my tests are incomplete or that the setter is not used/needed. "If i can execute all the "real" code without using that setter why is it there."

特别是当不使用TDD时,这有一个额外的好处,就是可以向我显示我在unittests中不使用的setter,从而显示我的测试是不完整的,或者setter是不使用/不需要的。如果我可以执行所有的“真正的”代码而不使用setter,为什么会有它呢?

When using fluent setter i sometimes write a test checking the 'fluent' part of the setters but usually that is covered in other tests.

在使用fluent setter时,我有时会编写一个测试来检查setter的“fluent”部分,但通常在其他测试中会涉及到。

To answer your list:

回答你的列表:

  • Just one test method?
  • 只是一个测试方法?

That is my least favorite option. All or none. Testing only one is not easy for other people to understand and looks 'random' or needs to be documented in a way.

这是我最不喜欢的选择。全部或没有。对其他人来说,只测试一个并不容易理解,而且看起来“随机”,或者需要以某种方式进行记录。

Edit after comment:

编辑后的评论:

Yes, for "trivial" get/set testing I'd only use one method per property maybe depending on the case even only one method for the whole class (for value objects with many getters and setters I don't want to write/maintain many tests)

是的,对于“平凡”的get/set测试,我每个属性只使用一个方法,可能取决于情况,甚至整个类只有一个方法(对于具有许多getter和setter的值对象,我不想编写/维护多个测试)

  • How would you write unit tests for those methods?
  • 如何为这些方法编写单元测试?
  • Should I skip those tests?
  • 我应该跳过这些测试吗?

I wouldn't skip them. Maybe the getters depending on how many you have (i tend to write only getters i actually need) but the task of having a class completely covered shouldn't fail because of getters.

我不会跳过它们。可能getters取决于你有多少个(我倾向于只写我实际需要的getter),但是完全覆盖一个类的任务不应该因为getter而失败。

  • What about code coverage?
  • 代码覆盖呢?
  • How about @covers annotation?
  • @covers注释呢?

With @covers my take is always "use it everywhere or don't use it at all". Mixing the two 'styles' of testing takes away some of the benefits of the annotation and looks 'unfinished' to me.

对于@cover,我的理解总是“在任何地方使用它,或者根本不使用它”。混合使用这两种“风格”的测试会减少注释的一些好处,在我看来是“未完成”的。

  • Maybe some universal test method to implement in the abstract test case?
  • 在抽象的测试用例中实现什么通用的测试方法?

For something like value objects that could work nicely. It might break (or gets more complicated) once you pass in objects / array with type hinting but I'd presonally prefer it over writing manual tests for 500 getters and setters.

对于像value这样可以很好地工作的对象。一旦您传入带有类型提示的对象/数组,它可能会被破坏(或者变得更复杂),但与为500个getter和setter编写手工测试相比,我更喜欢它。

#2


7  

If you do TDD you should write a test for getter and setter. too. Do not write a single line of code without a test for it - even if your code is very simple.

如果您执行TDD,您应该为getter和setter编写一个测试。了。不要在没有测试的情况下编写一行代码——即使您的代码非常简单。

Its a kind of religious war to use a tandem of getter and setter for your test or to isolate each by accessing protected class members using your unit test framework capabilities. As a black box tester i prefer to tie my unit test code to the public api instead of tie it to the concrete implementation details. I expect change. I want to encourage the developers to refactor existing code. And class internals should not effect "external code" (unit tests in this case). I don want to break unit tests when internals change, i want them to break when the public api changes or when behavior changes. Ok, ok, in case of a failing unit test do not pin-point to the one-and-only source of problem. I do have to look in the getter AND the setter to figure out what caused the problem. Most of the time your getter is very simple (less then 5 lines of code: e.g. a return and an optional null-check with an exception). So checking this first is no big deal and not time consuming. And checking the happy path of the setter is most of the time only a little more complex (even if you have some validation checks).

使用一系列的getter和setter进行测试,或者通过使用单元测试框架功能访问受保护的类成员来隔离每个成员,这是一种宗教战争。作为一个黑盒测试人员,我更喜欢将单元测试代码绑定到公共api,而不是将它绑定到具体的实现细节。我期待改变。我希望鼓励开发人员重构现有代码。类内部不应该影响“外部代码”(在本例中是单元测试)。我不想在内部变更时破坏单元测试,我想在公共api变更或行为变更时破坏单元测试。好的,如果单元测试失败了,不要指向唯一的问题源。我必须在getter和setter中查找导致问题的原因。大多数时候,您的getter非常简单(少于5行代码:例如返回和一个异常的可选的空检查)。所以首先检查这个并不重要,也不浪费时间。检查setter的愉快路径大部分时间都只是稍微复杂一点(即使您有一些验证检查)。

Try to isolate your test cases - write a test for a SUT (Subject under test) that validates its correctness without reley on other methods (except my example above). The more you isolate the test, the more your tests spot the problem.

尝试隔离您的测试用例——编写一个测试SUT(被测试的对象),它可以在没有其他方法的情况下验证其正确性(除了上面的例子)。您越是隔离测试,您的测试就越能发现问题。

Depending on your test strategy you may be want to cover happy path only (pragmatic programmer). Or sad pathes, too. I prefer to cover all execution pathes. When i think i discovered all execution pathes i check code coverage to identify dead code (not to identify if there are uncovered execution pathes - 100% code coverage is a missleading indicator).

根据您的测试策略,您可能希望只覆盖“快乐路径”(实用程序员)。或悲伤道。我倾向于覆盖所有执行路径。当我认为我发现了所有执行路径时,我检查代码覆盖率来识别死代码(不确定是否有未发现的执行路径——100%的代码覆盖率是一个错误的指示器)。

It is best practice for black box testers to use phpunit in strict mode and to use @covers to hide collateral coverage.

黑盒测试人员最好在严格的模式下使用phpunit,并使用@cover隐藏附属覆盖率。

When you write unit test your test on class A should be executed independent from class B. So your unit tests for class A should not call / cover method of class B.

当你写单元测试时,你在A类上的测试应该独立于B类来执行,所以你在A类上的单元测试不应该调用B类的方法。

If you want to identify obsolete getter/setter and other "dead" methods (which are not used by production code) use static code analysis for that. The metric you are interested in is called "Afferent coupling at method level (MethodCa)". Unfortunately this metric (ca) is not available at method-level in PHP Depend (see: http://pdepend.org/documentation/software-metrics/index.html and http://pdepend.org/documentation/software-metrics/afferent-coupling.html). If you realy need it, feel free to contribute it to PHP Depend. An option to exclude calls from the same class would be helpful to get a result without "collateral" calls. If you identify a "dead method" try to figure out if it is meant to be used in near future (the counterpart for an other method that has a @depricated annotation) else remove it. In case it is used in the same class only, make it privat / protected. Do not apply this rule to library code.

如果您想识别过时的getter/setter和其他“死”方法(不被生产代码使用),请使用静态代码分析。您感兴趣的度量称为“方法级的传入耦合(MethodCa)”。不幸的是,这个度量(ca)在PHP Depend的方法级别上是不可用的(参见:http://pdepend.org/documentation/softw-metrics/index.html和http://pdepend.org/documentation/softw-metrics/afferent -coupling.html)。如果您确实需要它,请将它贡献给PHP依赖。排除来自同一个类的调用的选项将有助于在没有“附带”调用的情况下获得结果。如果您识别了一个“死方法”,请尝试找出它是否打算在不久的将来被使用(另一个具有@德普化注释的方法的对应方法),那么请删除它。如果只在同一类中使用,请将其设置为私有/受保护。不要将此规则应用于库代码。

Plan B: If you have acceptance tests (integration test, regression test, etc.) you can run that test without running unit tests at the same time and without phpunits strict mode. This can result in a very similar code coverage result as if you had analysed your production code. But in most cases your non-unit tests are not as strong as your production code is. It depends on your discipline if this plan B is "equal enought" to production code to get a meaningful result.

计划B:如果您有验收测试(集成测试、回归测试等),您可以在不同时运行单元测试和没有phpunits严格模式的情况下运行该测试。这可能导致非常类似的代码覆盖率结果,就像您分析了您的产品代码一样。但是在大多数情况下,您的非单元测试不如您的产品代码强大。如果这个计划B与生产代码“相等”以获得有意义的结果,这取决于您的规程。

Further reading: - Book: Pragmatic Programmer - Book: Clean Code

进一步阅读:-书:实用程序员-书:干净的代码

#3


3  

This is a common question but strangely can't find a dupe on SO.

这是一个常见的问题,但奇怪的是却找不到这样的问题。

You could write unit tests for accessors but the majority of practioners do not. i.e. if the accessors do not have any custom logic, I would not write unit tests to verify if field access works. Instead I would rely on the consumers of these accessors to ensure that the accessors work. e.g. If getFoo and setFoo don't work, the callers of these method should break. So by writing unit tests for the calling methods, the accessors get verified.

您可以为访问器编写单元测试,但大多数实践者都不这样做。例如,如果访问器没有任何自定义逻辑,我就不会编写单元测试来验证字段访问是否有效。相反,我将依赖这些访问器的使用者来确保访问器工作。如果getFoo和setFoo不工作,这些方法的调用者应该会中断。因此,通过为调用方法编写单元测试,访问器将得到验证。

This also means that code coverage should not be a problem. If you find accessors that are not covered after all test suites are run, maybe they are redundant / unused. Delete them.

这也意味着代码覆盖率不应该成为问题。如果在运行所有测试套件之后发现访问器没有覆盖,那么它们可能是冗余的/未使用的。删除它们。

Try to write a test that illustrates a scenario where a client will use that accessor. e.g. The below snippet shows how the Tooltip (property) for the Pause Button toggles based on its current mode.

尝试编写一个测试来说明客户端将使用该访问器的场景。下面的代码片段显示了暂停按钮的工具提示(属性)是如何根据当前模式切换的。

[Test]
public void UpdatesTogglePauseTooltipBasedOnState()
{
    Assert.That(_mainViewModel.TogglePauseTooltip, Is.EqualTo(Strings.Main_PauseAllBeacons));

    _mainViewModel.TogglePauseCommand.Execute(null);
    Assert.That(_mainViewModel.TogglePauseTooltip, Is.EqualTo(Strings.Main_ResumeAllBeacons));

    _mainViewModel.TogglePauseCommand.Execute(null);
    Assert.That(_mainViewModel.TogglePauseTooltip, Is.EqualTo(Strings.Main_PauseAllBeacons));
}

推荐阅读
  • 深入解析动态代理模式:23种设计模式之三
    在设计模式中,动态代理模式是应用最为广泛的一种代理模式。它允许我们在运行时动态创建代理对象,并在调用方法时进行增强处理。本文将详细介绍动态代理的实现机制及其应用场景。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 本文介绍 Java 中如何使用 Year 类的 atMonth 方法将年份和月份组合成 YearMonth 对象,并提供代码示例。 ... [详细]
  • 本文深入探讨了 Java 中 LocalTime 类的 isSupported() 方法,包括其功能、语法和使用示例。通过具体的代码片段,帮助读者理解如何检查特定的时间字段或单位是否被 LocalTime 类支持。 ... [详细]
  • 并发编程 12—— 任务取消与关闭 之 shutdownNow 的局限性
    Java并发编程实践目录并发编程01——ThreadLocal并发编程02——ConcurrentHashMap并发编程03——阻塞队列和生产者-消费者模式并发编程04——闭锁Co ... [详细]
  • 本文介绍了如何通过Java代码计算一个整数的位数,并展示了多个基础编程示例,包括求和、平均分计算、条件判断等。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • 为了解决不同服务器间共享图片的需求,我们最初考虑建立一个FTP图片服务器。然而,考虑到项目是一个简单的CMS系统,为了简化流程,团队决定探索七牛云存储的解决方案。本文将详细介绍使用七牛云存储的过程和心得。 ... [详细]
  • 本文详细介绍了钩子(hook)的概念、原理及其在编程中的实际应用。通过对比回调函数和注册函数,解释了钩子的工作机制,并提供了具体的Python示例代码,帮助读者更好地理解和掌握这一重要编程工具。 ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • Java多线程实现:从1到100分段求和并汇总结果
    本文介绍如何使用Java编写一个程序,通过10个线程分别计算不同区间的和,并最终汇总所有线程的结果。每个线程负责计算一段连续的整数之和,最后将所有线程的结果相加。 ... [详细]
  • 深入解析Java多线程与并发库的应用:空中网实习生面试题详解
    本文详细探讨了Java多线程与并发库的高级应用,结合空中网在挑选实习生时的面试题目,深入分析了相关技术要点和实现细节。文章通过具体的代码示例展示了如何使用Semaphore和SynchronousQueue来管理线程同步和任务调度。 ... [详细]
  • 本题要求在一组数中反复取出两个数相加,并将结果放回数组中,最终求出最小的总加法代价。这是一个经典的哈夫曼编码问题,利用贪心算法可以有效地解决。 ... [详细]
  • 二叉树的链表实现
    本文介绍了一种使用链表结构表示二叉树的方法。通过定义节点结构和相关操作函数,可以方便地创建、插入和遍历二叉树。 ... [详细]
  • 本文探讨了C++编程中理解代码执行期间复杂度的挑战,特别是编译器在程序运行时生成额外指令以确保对象构造、内存管理、类型转换及临时对象创建的安全性。 ... [详细]
author-avatar
lovely蓝衣13
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有