我对测试驱动开发有点陌生,正在尝试确定我的单元测试方法是否有问题。
我有几个单元测试(我们称它们为 A 组(来测试我的方法的返回是否符合预期。
我还有一个单元测试"B",其通过条件是当我的方法被赋予无效输入时抛出IllegalArgumentException
。
当方法被赋予无效输入时,组 A 中的单元测试失败,因为该方法需要有效的输入才能正确返回。
如果我捕获异常,单元测试"B"将失败,但如果我没有捕获异常,则组 A 中的测试将失败。
是否可以让单元测试以这种方式失败,或者我可以以某种方式修改代码以使所有测试始终通过?
我做错了TDD吗?
为了更清楚起见,以下是我的代码的概念:
public class Example{
public static String method(String inputString, int value){
if(badInput){
throw new IllegalArgumentException();
}
//do some things to inputString
return modifiedInputString;
}
}
public class ExampleTests{
@Test
public void methodReturnsIllegalArgumentExceptionForBadInput(){
assertThrows(IllegalArgumentException.class, ()->{Example.method(badInput,badValue);})
}
//"Group A" tests only pass with valid input. Bad input causes IllegalArgumentException
@Test
public void methodReturnsExpectedType(){
assertTrue(actual == expected);
}
@Test
public void methodReturnsExpectedValue(){
assertTrue(actual == expected);
}
@Test
public void methodReturnsExpectedStringFormat(){
assertTrue(actual == expected);
}
}
正如您在评论中正确指出的那样,问题在于测试设置太宽泛和测试太隐式。
当测试在业务级别自包含时,它们的可读性要高得多。常见的测试设置应侧重于设置技术细节,但所有业务设置都应在每个测试本身内。
案例的示例(概念示例,必须重新设计以匹配实现的详细信息(:
@Test
public void givenWhatever_whenDoingSomething_methodReturnsExpectedType(){
given(someInputs);
Type result = executeSut(); //rename executeSut to actual function under test name
assertTrue(result == expected);
}
这样,通过查看测试,读者就知道正在测试的场景。常见的测试设置和辅助功能(如given
抽象出技术细节,因此读者在第一次检查时不会分心。如果他们感兴趣,详细信息始终可用 - 但通常不太重要,可以隐藏。