java - 在 TDD 过程中删除单元测试

标签 java unit-testing tdd

我目前正在阅读一本关于使用 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);
}

然后在测试为绿色之后我可以清楚地看到,所有早期测试的方法从一开始就应该是私有(private)方法。

在编码过程中,TDD 中的一些最初有用的测试被删除的情况是否经常发生并且被接受?因为可以肯定的一件事 - 这些方法根本不应该暴露给该类用户,所以像“保护它们”这样的回答对我没有吸引力。

或者也许我的方法从一开始就是无效的,我应该只为 isValid() 方法编写一个测试,以测试 API 的行为?如果我这样做的话,这样的测试会太笼统,并且不允许我在开发时检查所有边界情况,或者我可能完全错了?测试什么和根本不应该测试什么之间有界限吗?粒度应该是多少?

最佳答案

Or maybe my approach from the very beginning is invalid and I should have only written a test for isValid() method

是的,这个。

所以你写这样的东西作为起点:

public static boolean isValid(String passwordToValidate) {
    return false;
}

然后你可以编写你的第一个测试:

@Test
public void returnsTrueWhenPasswordIsAtLeastEightCharsLong() {
    assertTrue(isValid(EIGHT_CHARACTERS_LONG_PASSWORD));
}

哪个会失败:RED。

因此,您对被测代码进行了最简单的更改以使其通过:

public static boolean isValid(String passwordToValidate) {
    return true;
}

然后测试将通过:绿色。

但是您还没有完全测试 8 个字符的限制:

@Test
public void returnsFalseWhenPasswordIsLessThanEightCharsLong() {
    assertFalse(isValid(SEVEN_CHARACTERS_LONG_PASSWORD));
}

这将失败——红色——因为被测试的方法现在总是返回真。

所以你做出最小的改变来使所有测试通过:

public static boolean isValid(String passwordToValidate) {
    return passwordToValidate.length() >= 8;
}

你又变绿了。

然后您继续这样做,添加其他测试,并且每次都尽可能少地更改您正在测试的代码以使测试通过。

您可能会发现在某个阶段通过将 isValid 方法拆分为您调用的一些私有(private)方法来重构它很有用。没关系:它是重构步骤的一部分,而且您的测试应该仍然通过,因为公共(public)接口(interface)没有改变。

关于java - 在 TDD 过程中删除单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25473626/

相关文章:

javascript - 当我的单元测试失败时回调被调用两次

c++ - 单元测试变量的真假

windows-phone-7 - Windows Phone 的单元测试状态

android - Android 的测试驱动开发

javascript - Maven 存储库上的 JQuery 可用性

java - 如何在 CDH 上查看 Avro 版本?

java - 将 MySQL 数据显示到 JTextField

java - 用于权限异常的内置java异常类型

ios - 如何运行 iOS 工作区的所有单元测试?

ruby - ruby 中 TDD/BDD 的书籍/教程?