ska*_*man 167
我会说不.
@Will说你应该瞄准100%的代码覆盖率,但在我看来这是一个危险的分心.您可以编写具有100%覆盖率的单元测试,但绝对没有测试.
单元测试用于以一种富有表现力和有意义的方式测试代码的行为,而getter/setter只是达到目的的手段.如果你测试使用getters/setters来实现测试"真实"功能的目标,那就足够了.
另一方面,如果你的getter和setter做的不仅仅是获取和设置(即它们是正确的复杂方法),那么是的,它们应该进行测试.但是,不要仅仅为了测试吸气剂或定位器来编写单元测试用例,这是浪费时间.
Izh*_*aki 35
注意:这个答案不断得到提升,尽管可能是一个糟糕的建议.要了解原因,请看下面的小妹妹.
有争议的,但我认为任何对这个问题回答'不'的人都缺少TDD的基本概念.
对我来说,如果你遵循TDD ,答案是肯定的.如果你不是,那么不是一个看似合理的答案.
TDD经常被引用为具有主要益处.
作为程序员,将属性视为重要的东西,将getter和setter视为某种开销是非常诱人的.
但属性是一个实现细节,而setter和getter是实际使程序工作的契约接口.
拼写对象应该更重要:
允许其客户更改其状态
和
允许其客户端查询其状态
那么这个状态实际上是如何存储的(属性是最常见的,但不是唯一的方式).
一个测试,如
(The Painter class) should store the provided colour
Run Code Online (Sandbox Code Playgroud)
对TDD 的文档部分很重要.
当你编写测试时,你应该不知道最终实现是微不足道的(属性)并且没有防御好处这一事实.
系统开发领域的一个关键问题是缺乏 往返工程1 - 系统的开发过程被分割成脱节的子流程,其中的工件(文档,代码)经常不一致.
1 Brodie,Michael L."John Mylopoulos:缝合概念造型的种子." 概念建模:基础和应用.Springer Berlin Heidelberg,2009.1-9.
它是TDD 的文档部分,可确保系统规范及其代码始终保持一致.
在TDD中,我们首先编写失败的验收测试,然后编写允许它们通过的代码.
在更高级别的BDD中,我们首先编写场景,然后让它们通过.
为什么要排除setter和getter?
从理论上讲,在TDD中完全可以让一个人编写测试,而另一个人则可以实现使其通过的代码.
所以问问自己:
为一个班级编写测试的人是否应该提到吸气剂和二传手.
由于getter和setter是类的公共接口,因此答案显然是肯定的,或者无法设置或查询对象的状态.但是,这样做的方法不一定是单独测试每个方法,请参阅我的其他答案.
显然,如果你先编写代码,答案可能就不那么明确了.
azh*_*kov 33
Roy Osherove在他的着名着作"单位测试的艺术"中说:
属性(Java中的getter/setter)是通常不包含任何逻辑的代码的良好示例,并且不需要测试.但请注意:一旦在属性中添加任何检查,您将需要确保正在测试逻辑.
Sle*_*led 22
tl; dr: 是的,你应该和OpenPojo一样,这是微不足道的.
您应该在getter和setter中进行一些验证,以便进行测试.例如,setMom(Person p)不应该允许任何比自己更年轻的人作为他们的母亲.
即使你现在没有做任何这样的事情,你将来会遇到的可能性很大,那么对于回归分析来说这将是一个好处.如果你想允许设置母亲,null你应该测试一下,如果有人稍后改变,这将加强你的假设.
一个常见的错误就是void setFoo( Object foo ){ foo = foo; }它应该存在的地方void setFoo( Object foo ){ this.foo = foo; }.(在第一种情况下,foo正被写入到是参数 不所述foo的上字段对象).
如果要返回数组或集合,则应测试getter是否将在返回之前执行传入setter的数据的防御性副本.
否则,如果你有最基本的setter/getter,那么对它们进行单元测试最多可能每个对象增加大约10分钟,那么损失是多少?如果添加行为,您已经进行了骨架测试,并且您可以免费获得此回归测试.如果你使用的是Java,那么因为有OpenPojo就没有任何借口.您可以启用一组现有规则,然后使用它们扫描整个项目,以确保它们在您的代码中始终如一地应用.
从他们的例子:
final PojoValidator pojoValidator = new PojoValidator();
//create rules
pojoValidator.addRule( new NoPublicFieldsRule () );
pojoValidator.addRule( new NoPrimitivesRule () );
pojoValidator.addRule( new GetterMustExistRule () );
pojoValidator.addRule( new SetterMustExistRule () );
//create testers
pojoValidator.addTester( new DefaultValuesNullTester () );
pojoValidator.addTester( new SetterTester () );
pojoValidator.addTester( new GetterTester () );
//test all the classes
for( PojoClass pojoClass : PojoClassFactory.getPojoClasses( "net.initech.app", new FilterPackageInfo() ) )
pojoValidator.runValidation( pojoClass );
Run Code Online (Sandbox Code Playgroud)
Izh*_*aki 17
请允许我详细说明:
从与遗留代码1 有效合作:
单元测试一词在软件开发方面有着悠久的历史.大多数单元测试概念的共同之处在于,它们是独立于软件各个组件的测试.什么是组件?定义各不相同,但在单元测试中,我们通常关注系统的大多数原子行为单元.在程序代码中,单元通常是功能.在面向对象的代码中,单元是类.
请注意,使用OOP,您可以找到getter和setter,单位是类,不一定是单独的方法.
所有要求和测试都遵循Hoare逻辑的形式:
{P} C {Q}
哪里:
{P}是先决条件(给定)C是触发条件(何时){Q}是后置条件(然后)格言是:
测试行为,而不是实现
这意味着你不应该测试如何C实现后置条件,你应该检查是否{Q}是结果C.
说到OOP,C是一堂课.所以你不应该测试内部效果,只测试外部效果.
getter和setter可能涉及一些逻辑,但是这么长时间这个逻辑没有外部效应 - 使它们成为bean访问器2)测试必须查看对象内部,这不仅违反封装而且还测试实现.
所以你不应该孤立地测试bean getter和setter.这是不好的:
Describe 'LineItem class'
Describe 'setVAT()'
it 'should store the VAT rate'
lineItem = new LineItem()
lineItem.setVAT( 0.5 )
expect( lineItem.vat ).toBe( 0.5 )
Run Code Online (Sandbox Code Playgroud)
虽然if setVAT会抛出异常,但相应的测试是合适的,因为现在有一个外部效应.
如果这种变化对外界没有影响,即使后来出现这样的影响,也几乎没有必要改变对象的内部状态.
所以对二传手和吸气剂的测试应该关注这些方法的外部效应,而不是内部效应.
例如:
Describe 'LineItem class'
Describe 'getGross()'
it 'should return the net time the VAT'
lineItem = new LineItem()
lineItem.setNet( 100 )
lineItem.setVAT( 0.5 )
expect( lineItem.getGross() ).toBe( 150 )
Run Code Online (Sandbox Code Playgroud)
你可能会想到自己:
等一下,我们在
getGross()这里测试没有setVAT().
但是,如果setVAT()测试失败,那么同样失败.
1 Feathers,M.,2004.有效地使用遗留代码.Prentice Hall专业.
2 Martin,RC,2009.清洁代码:敏捷软件工艺手册.皮尔逊教育.
bry*_*ook 13
虽然对于属性有合理的理由,但是有一个共同的面向对象设计的信念,即通过属性暴露成员状态是糟糕的设计.罗伯特马丁关于开放封闭原则的文章通过声明属性鼓励耦合并因此限制关闭类的修改能力来扩展这一点 - 如果修改属性,类的所有消费者也需要改变.他认为暴露成员变量不一定是糟糕的设计,它可能只是糟糕的风格.但是,如果属性是只读的,那么滥用和副作用的可能性就会降低.
我可以为单元测试提供的最佳方法(这可能看起来很奇怪)是尽可能多地保护或内部属性.这将阻止耦合,同时阻止为吸气剂和制定者编写愚蠢的测试.
应该使用读/写属性的明显原因,例如绑定到输入字段的ViewModel属性等.
更实际的是,单元测试应该通过公共方法驱动功能.如果您正在测试的代码恰好使用这些属性,则可以免费获得代码覆盖率.如果事实证明这些属性永远不会被代码覆盖突出显示,那么很可能:
如果您为getter和setter编写测试,则会产生错误的覆盖感,并且无法确定属性是否实际被功能行为使用.
一个幽默但明智的作品:Testivus之路
"今天就写出你的测试"
如果您是一位经验丰富的测试人员并且这是一个小项目,那么测试getter/setter可能会过度.但是,如果您刚刚开始学习如何进行单元测试,或者这些getter/setter可能包含逻辑(如@ ArtB的setMom()示例)那么编写测试将是一个好主意.
| 归档时间: |
|
| 查看次数: |
64448 次 |
| 最近记录: |