Java 如何测试所有坏参数的组合?

Java 如何测试所有坏参数的组合?,java,exception,junit,Java,Exception,Junit,让我们假设一个简单的方法抛出一个IndexOutOfBoundsException 对于无效的索引对(2d数组) 我如何测试,是否为所有坏消息组合引发异常 指数 (当然,如果 一个调用引发一个异常) 有没有一种通用的测试方法 方法参数的变化?在您的情况下,我将参数化我的单元测试,以使用相同的测试更多信息测试所有组合 在您的情况下,它将如下所示: @RunWith(Parameterized.class) public class MyTest { @Parameterized.Param

让我们假设一个简单的方法抛出一个
IndexOutOfBoundsException
对于无效的索引对(2d数组)

我如何测试,是否为所有坏消息组合引发异常 指数

(当然,如果 一个调用引发一个异常)

有没有一种通用的测试方法
方法参数的变化?

在您的情况下,我将
参数化
我的单元测试,以使用相同的测试更多信息测试所有组合

在您的情况下,它将如下所示:

@RunWith(Parameterized.class)
public class MyTest {
    @Parameterized.Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][] {
            { 0, -1 }, { -1, 0 }
        });
    }

    @Parameterized.Parameter
    public int row;

    @Parameterized.Parameter(value = 1)
    public int col;

    @Test(expected = IndexOutOfBoundsException.class)
    public void validateIndices(){
        check(row, col);
    }
}
@RunWith(参数化的.class)
公共类MyTest{
@参数化。参数化
公共静态收集数据(){
返回Arrays.asList(新对象[][]{
{ 0, -1 }, { -1, 0 }
});
}
@参数化
公共int row;
@参数化。参数(值=1)
公共int col;
@测试(预期=IndexOutOfBoundsException.class)
公共void validateIndices(){
检查(行、列);
}
}

好的,如果索引都是
整数
值,则可以使用带有try-catch语句的for循环:

for (int i = iBegin; i < iEnd; i++) {
  for (int j = jBegin; j < jEnd; j++) {
    try { check(i, j); }
    catch (Exception e) { iList.add(i); jList.add(j); }
  }
}
for(inti=iBegin;i

(在本例中,iList和jList是某种类型的
集合
;iBegin、jBegin、iEnd和jEnd是整数值,它们给出了变化的界限)

其他答案当然是正确的,因为它们满足了您的要求,但它们在概念上有一个很大的缺点:它们只能检查错误条件。。。您必须手动指定

意思:这种测试只能证明您的“测试中的代码”对那些定义良好的情况做了预期的事情

将其与编程模型进行比较,在编程模型中,您会告诉环境:“这就是我期望函数的行为方式”;然后那个环境会试图找到输入。。。函数在其上中断


如果你觉得有趣的话,你应该去看看。虽然不是真正的Java“本机”,也肯定不是现在的“主流”。。。也许值得一试。

除了@Nicolas\u Filotto答案,您还可以使用。它更具可读性,与参数化的
不同,它将使用所有可能的参数组合执行测试

@RunWith(Theories.class)
public class MyTest {
    @DataPoints("cols")
    public static int[] rowValues(){
        return new int[]{0, -1, 1, 2};
    }
    @DataPoints("rows")
    public static int[] colValues(){
        return new int[]{0, -1, 4, 5};
    }

    @Theory
    public void upperBoundIsChecked(@FromDataPoints("cols") int col,
                                    @FromDataPoints("rows") int row){
        assumeTrue(row >= ROWS || col >= COLS);
        try {
            check(col, row);
            fail("Should have thrown IllegalArgumentException");
        } catch (IllegalArgumentException ignore){}
    }

    @Theory
    public void lowerBoundIsChecked(@FromDataPoints("cols") int col,
                                    @FromDataPoints("rows") int row){
        assumeTrue(row < 0 || col < 0);
        try {
            check(col, row);
            fail("Should have thrown IllegalArgumentException");
        } catch (IllegalArgumentException ignore){}
    }

    @Theory
    public void validIndicesNoException(@FromDataPoints("cols") int col,
                                        @FromDataPoints("rows") int row){
        assumeTrue(row >= 0 && col >= 0 && row < ROWS && col < COLS);
        try {
            check(col, row);
        } catch (Exception e){
            fail("Should not have thrown an exception: " + e.getMessage());
        }
    }

}

就像大多数关于单元测试的基本教程一样:每个测试方法测试一个条件。所以你的四次检查至少需要四次。@Tom重复四次不是很重复吗?“重复四次不是很重复吗?”那又怎样?这取决于你。您需要一个失败的
validateIndices
方法,并且您必须手动检查这些调用中的哪些失败,您有专门的方法,如
testCheck\u invalidSecondArgument
,因此,我们将确切地看到哪一个失败。@Jam我希望您的
检查
方法实际上没有抛出
异常
expect
最具体的异常,因为否则,您捕获的异常可能与您认为正在测试的内容完全无关。理论对于测试数据点组合上的广泛行为非常有用。未提及的一个好处是,如果理论失败,junit结果将显示导致理论失败的特定值组合。
@RunWith(Theories.class)
public class MyTest {
    @DataPoints("cols")
    public static int[] rowValues(){
        return new int[]{0, -1, 1, 2};
    }
    @DataPoints("rows")
    public static int[] colValues(){
        return new int[]{0, -1, 4, 5};
    }

    @Theory
    public void upperBoundIsChecked(@FromDataPoints("cols") int col,
                                    @FromDataPoints("rows") int row){
        assumeTrue(row >= ROWS || col >= COLS);
        try {
            check(col, row);
            fail("Should have thrown IllegalArgumentException");
        } catch (IllegalArgumentException ignore){}
    }

    @Theory
    public void lowerBoundIsChecked(@FromDataPoints("cols") int col,
                                    @FromDataPoints("rows") int row){
        assumeTrue(row < 0 || col < 0);
        try {
            check(col, row);
            fail("Should have thrown IllegalArgumentException");
        } catch (IllegalArgumentException ignore){}
    }

    @Theory
    public void validIndicesNoException(@FromDataPoints("cols") int col,
                                        @FromDataPoints("rows") int row){
        assumeTrue(row >= 0 && col >= 0 && row < ROWS && col < COLS);
        try {
            check(col, row);
        } catch (Exception e){
            fail("Should not have thrown an exception: " + e.getMessage());
        }
    }

}
@RunWith(Theories.class)
public class MyTest {

   @DataPoints
   public static int[] values(){
      return new int[]{0, -1};
   }
   @Theory
   public void validateIndices(int col, int row){
      check(col,row);
   }
}