我应该测试(复制)数据,还是仅测试行为?

Pio*_*ler 8 java junit automated-tests unit-testing

从设计的角度来看,我想知道我应该测试数据,特别是如果它是一个通常已知的数据(不是非常可配置的) - 这可以适用于流行的文件扩展名,特殊的IP地址等.

假设我们有一个紧急电话号码分类器:

public class ContactClassifier {

    public final static String EMERGENCY_PHONE_NUMBER = "911";

    public boolean isEmergencyNumber(String number) {
        return number.equals(EMERGENCY_PHONE_NUMBER);
    }
}
Run Code Online (Sandbox Code Playgroud)

我应该这样测试("911"重复):

@Test
public testClassifier() {
    assertTrue(contactClassifier.isEmergencyNumber("911"));
    assertFalse(contactClassifier.isEmergencyNumber("111-other-222"));
}
Run Code Online (Sandbox Code Playgroud)

或(测试是否正确识别"已配置"号码):

@Test
public testClassifier() {      
    assertTrue(contactClassifier.isEmergencyNumber(ContactClassifier.EMERGENCY_PHONE_NUMBER));
    assertFalse(contactClassifier.isEmergencyNumber("111-other-222"));
}
Run Code Online (Sandbox Code Playgroud)

或者在构造函数中注入"911",这看起来对我来说是最合理的,但即使我这样做 - 如果组件用适当的值实例化,我应该为"应用程序粘合剂"编写一个测试吗?如果有人可以在数据(代码)中输入拼写错误,那么我认为没有人可以在测试案例中输入拼写错误(我打赌这样的数据会被复制粘贴)

And*_*kov 5

什么是点的测试数据,你可以测试?该常数实际上是常数吗?它已经在代码中定义了。Java确保该值实际上是该值,因此不必理会。

如果正确与否,则在单元测试中应该执行的是测试实施。要测试不正确的行为,请使用在测试内部定义的,标记为错误的数据,然后将其发送给方法。要测试数据是否正确,请在测试期间输入它(如果它不是众所周知的边界值),或者如果已经在某个地方定义了它们,则使用应用程序范围内的已知值(接口内部的常量)。

让您感到困扰的是,应该让每个人都知道的数据已经过测试,而且根本不正确。您可以做的是将其移至界面级别。这样,通过设计,您可以将应用程序已知的数据设计为合同的一部分,并且Java编译器会检查其正确性。

众所周知的值不应该被检查,而应该由某种接口处理以维护它们。是的,进行更改很容易,是的,并且在更改期间测试不会失败,但是为了避免发生意外,您应该具有合并请求,复审和与之相关的任务。如果有人确实更改了它,那么您可以在代码检查中找到它。如果您将所有东西都花在掌握上,那么比双重定义的常量要麻烦得多。

现在,在其他方式困扰您的部分上:

1)如果有人可以在数据(代码)中打错字,那么我认为没有理由有人可以在测试用例中打错字(我敢打赌这些数据将被复制粘贴)

实际上,如果有人更改了数据值然后继续开发,则在某个时候他将运行全新安装并看到那些失败的测试。那时他可能会更改/忽略测试以使其通过。如果您有一个随机更改数据的人,那么您会遇到更大的问题;如果没有,并且更改是由任务定义的,则您让某人进行了两次更改(至少?)。没有优点,也有很多缺点。

2)担心别人犯错通常是不道德的行为。您无法使用代码捕获它。代码审查是为此目的而设计的。但是,您可能会担心有人无法正确使用您定义的界面。

3)我应该这样测试吗:

@Test
public testClassifier() {
    assertTrue(contactClassifier.isEmergencyNumber(ContactClassifier.EMERGENCY_PHONE_NUMBER));
    assertFalse(contactClassifier.isEmergencyNumber("111-other-222"));
}
Run Code Online (Sandbox Code Playgroud)

也不是这样。这不是测试,而是测试批次,即同一方法中的多个测试。应该是这种方式(惯例-s):

@Test
public testClassifier_emergencyNumberSupplied_correctnessConfirmed() {
    assertTrue(contactClassifier.isEmergencyNumber(ContactClassifier.EMERGENCY_PHONE_NUMBER));
}


@Test
public testClassifier_incorrectValueSupplied_correctnessNotConfirmed() {
    assertFalse(contactClassifier.isEmergencyNumber("111-other-222"));
}
Run Code Online (Sandbox Code Playgroud)

4)正确命名方法不是必需的,但是如果方法足够长,则可以考虑在测试中命名值。例如

@Test
public testClassifier_incorrectValueSupplied_correctnessNotConfirmed() {
    String nonEmergencyNumber = "111-other-222";
    assertFalse(contactClassifier.isEmergencyNumber(nonEmergencyNumber));
}
Run Code Online (Sandbox Code Playgroud)