锁定老帖子 主题:什么是“测试驱动开发”
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2006-04-25
实际上私有方法可能出现的情形有很多:
比如封装循环 比如一段有语义关系的顺序执行语句 比如封装对其他 比如按某种既定方式修改对象的状态 而且,很多情况下,私有方法根本不和依赖对象发生关系 |
|
返回顶楼 | |
发表时间:2006-04-25
firebody 写道 charon 写道 看了这个代码。基本确认我们说的不是一个事情。 如果只是要验证comp2.logic3的传入参数,不必费那么大劲。因为EasyMock默认的就是equals方式的参数匹配。在外面构造好合适的result,result2不就行了。不理解为什么要自己构造IArgumentMatcher的实例(之前的不理解主要就在这里,不了解构造这个的必要性) 而要验证doSomeInternalLogic之类方法对状态的影响,这是间接方式。太琐碎了。而且不能应付大多数情况。 嗯,我也有这种感觉。 从测试代码来看,是比较evil的。 跟AssertEquals之类比起来确实没法比。 不过,不大理解的是,在私有方法改变状态的逻辑 上,除了改成protected和抽取出另外一个组件之外,似乎也就只有这么一个办法了。 我要验证doSomeInternalLogic的逻辑,就只能构造那两个ArgumentMatcher来进行验证。 还是不理解。你这里是通过验证comp2.logic3的输入参数来间接验证doSomeInternalLogic的,根本不需要构造ArgumentMatcher. 如果在某些场合下真的需要,那也只是需要合理实现被match对象的equals方法,而不是通过构造IArgumentMatcher的实例 |
|
返回顶楼 | |
发表时间:2006-04-25
charon 写道 实际上私有方法可能出现的情形有很多:
比如封装循环 比如一段有语义关系的顺序执行语句 比如封装对其他 比如按某种既定方式修改对象的状态 而且,很多情况下,私有方法根本不和依赖对象发生关系 是啊,TDD怎么能够反映这种被私有化了的方法逻辑的设计意图呢? 这就是我提出我得那个doSOmeLogicInternal的根本意图啊,就是疑惑啊,TDD的测试代码里面如果没有反映这个被私有的逻辑的话,怎么能够完整的反映设计意图呢? |
|
返回顶楼 | |
发表时间:2006-04-25
charon 写道 firebody 写道 charon 写道 看了这个代码。基本确认我们说的不是一个事情。 如果只是要验证comp2.logic3的传入参数,不必费那么大劲。因为EasyMock默认的就是equals方式的参数匹配。在外面构造好合适的result,result2不就行了。不理解为什么要自己构造IArgumentMatcher的实例(之前的不理解主要就在这里,不了解构造这个的必要性) 而要验证doSomeInternalLogic之类方法对状态的影响,这是间接方式。太琐碎了。而且不能应付大多数情况。 嗯,我也有这种感觉。 从测试代码来看,是比较evil的。 跟AssertEquals之类比起来确实没法比。 不过,不大理解的是,在私有方法改变状态的逻辑 上,除了改成protected和抽取出另外一个组件之外,似乎也就只有这么一个办法了。 我要验证doSomeInternalLogic的逻辑,就只能构造那两个ArgumentMatcher来进行验证。 还是不理解。你这里是通过验证comp2.logic3的输入参数来间接验证doSomeInternalLogic的,根本不需要构造ArgumentMatcher. 如果在某些场合下真的需要,那也只是需要合理实现被match对象的equals方法,而不是通过构造ArgumentMatcher 我也不理解你的说法,你写写伪代码吧。 |
|
返回顶楼 | |
发表时间:2006-04-25
所以我这里所有稍微有点意义的内务方法,都是protected。
而且,我的理解,这个不是TDD的需要,而是测试安全的需要。 至于TDD的推动开发,解决的不应当是个体方法的设计。这个层次的事情,很多方式都搞得定。TDD中广泛使用mock,使得大家能够在不预先实现想象中的对象就能搞定手头的事情,这是分治方法的一个非常好的表现。 |
|
返回顶楼 | |
发表时间:2006-04-25
firebody 写道 我也不理解你的说法,你写写伪代码吧。
按照你附件里面的那个例子,我一般是这样做的: public class MockTest extends TestCase { private static String TESTNAME1 = "aa"; private static String TESTNAME2 = "b2"; private static String TESTNAME2 = "fuck"; A a; static Bean argB1; private void changeState(Bean b);{ b.name = "changed"; } public void logic(); { Bean b = new Bean(name:TESTNAME1);; Bean b2 = new Bean(name:TESTNAME2);; a.test(b,b2);; a.test(b,b2);; this.changeState(b);; } public void test(); { A aMock = createMock(A.class);; MockTest test = new MockTest();; test.a = aMock; aMock.test(new Bean(name:TESTNAME1);,new Bean(name:TESTNAME2););; aMock.test(new Bean(name:TESTNAME3);,new Bean(name:TESTNAME2););; replay(aMock);; test.logic();; verify(aMock);; } } |
|
返回顶楼 | |
发表时间:2006-04-25
此时,要求Bean实现的equals方法中按照name判等
|
|
返回顶楼 | |
发表时间:2006-04-25
charon 写道 此时,要求Bean实现的equals方法中按照name判等
你这个更不通用了,在简单的bean还行,因为equals就可以搞定。 万一我得bean的状态比较复杂呢? 还需要实现一个对应的equals方法? 而且,为了测试需要写一个符合测试规则的equals方法,感觉也不好吧。 |
|
返回顶楼 | |
发表时间:2006-04-25
firebody 写道 charon 写道 此时,要求Bean实现的equals方法中按照name判等
你这个更不通用了,在简单的bean还行,因为equals就可以搞定。 万一我得bean的状态比较复杂呢? 还需要实现一个对应的equals方法? 而且,为了测试需要写一个符合测试规则的equals方法,感觉也不好吧。 那个bean是自己构造出来的,想要是什么状态就可以设置什么状态。 其实,那个equals不是一个符合测试规则的equals方法,而是一个一般的equals方法。而且,对象状态的判等,必须是可观测状态的判等,而且必须和equals的语义是一致的。这个和测试不测试没关系 在这个例子中,Bean实际上是不需要equals方法的,因为默认的够用了。 如果在构造状态比较多的bean对象的时候,适当注意那些引用对象的使用,默认的也够用了。 |
|
返回顶楼 | |
发表时间:2006-04-25
charon 写道 firebody 写道 charon 写道 此时,要求Bean实现的equals方法中按照name判等
你这个更不通用了,在简单的bean还行,因为equals就可以搞定。 万一我得bean的状态比较复杂呢? 还需要实现一个对应的equals方法? 而且,为了测试需要写一个符合测试规则的equals方法,感觉也不好吧。 那个bean是自己构造出来的,想要是什么状态就是什么状态。 其实,那个equals不是一个符合测试规则的equals方法,而是一个一般的equals方法。 在这个例子中,Bean实际上是不需要equals方法的,因为默认的够用了。 如果在构造状态比较多的bean对象的时候,适当注意那些引用对象的使用,默认的也够用了。 呵呵,一般的equals我是不写的。除非有明确的需求。 |
|
返回顶楼 | |