【发布时间】:2014-10-17 21:05:00
【问题描述】:
我目前正在阅读一本关于使用 testNG 和 Mockito 进行测试的书,以提高我使用这些工具的技能、拓宽我对一般测试的了解并提高我创建的代码的质量。
在第 4 章“测试驱动开发”之后,我应该做很多练习来巩固我刚刚学到的 TDD 知识并养成循环红色测试 -> 实施代码 -> 绿色测试 -> 的习惯重构。其中之一称为“PasswordValidator”,它应该可以验证密码的强度。
推荐的此类开发方法之一是从最简单的测试开始,然后逐步编写更复杂的测试用例,实现更复杂的功能。说实话,通常我会通过编写一个适当的正则表达式来解决这个问题(例如这个:https://stackoverflow.com/a/5142164/2576122),编写一些测试来涵盖我可能想象的任何边界情况并完成。
在这里,我首先创建 PasswordValidatorTest 类并在其中进行测试,例如:
@Test
public void returnsTrueWhenPasswordIsAtLeastEightCharsLong() {
assertTrue(atLeastEightCharactersLong(EIGHT_CHARACTERS_LONG_PASSWORD));
}
我检查它是否失败,在 PasswordValidator 中实现逻辑:
public static boolean atLeastEightCharactersLong(String passwordToValidate) {
if (passwordToValidate.length() >= 8) {
return true;
} else {
return false;
}
}
我检查它是绿色的,然后我重构:
public static boolean atLeastEightCharactersLong(String passwordToValidate) {
return (passwordToValidate.length() >= 8);
}
包含数字、特殊符号等的测试也是如此。在这样的过程的某个时刻,我最终得到了一个最终测试:
@Test
public void shouldReturnTrueIfPasswordIsValid() {
assertTrue(PasswordValidator.isValid(VALID_PASSWORD_EXAMPLE));
}
实现的目的:
public static boolean isValid(String passwordToValidate) {
return atLeastEightCharactersLong(passwordToValidate) && containsAtLeastTwoDigits(passwordToValidate) &&
containsAtLeastOneSpecialSign(passwordToValidate);
}
然后在测试为绿色之后,我可以清楚地看到,所有早期测试的方法从一开始就应该是私有的。
在编码 TDD 中最初有用的一些测试被删除的情况是否经常发生并且是否被接受?因为有一件事是肯定的——这些方法根本不应该暴露给那个类用户,所以像“让它们受到保护”这样的回答对我没有吸引力。
或者我的方法从一开始就无效,我应该只为 isValid() 方法编写一个测试来测试 API 的行为?如果我这样做了,那么这样的测试将过于笼统,并且不允许我在开发时检查所有边界情况,或者我可能全都错了?在要测试的内容和根本不应该测试的内容之间是否存在界限?粒度应该是多少?
【问题讨论】:
-
IMO,你的第一个测试应该测试验证器应该拥有的唯一公共方法(
isValid())并且是isValidShouldReturnFalseIfPasswordIsLessThan8CharactersLong()。您对isValid()(return true;) 的首次实现将无法通过此测试,直到您实际实现长度验证。
标签: java unit-testing tdd