首页 > 解决方案 > 如何通过 EvoSuite 生成失败的测试用例?

问题描述

在学习使用 Evosuite 的时候,我写了一些错误的方法。例如其中一个类的方法A直接调用 interface 的抽象方法B,EvoSuite 生成一个 mockB来避免 case 失败:

import org.junit.Test;
import static org.junit.Assert.*;
import static org.evosuite.shaded.org.mockito.Mockito.*;
import MockTest.A;
import MockTest.B;
import org.evosuite.runtime.EvoRunner;
import org.evosuite.runtime.EvoRunnerParameters;
import org.evosuite.runtime.ViolatedAssumptionAnswer;
import org.junit.runner.RunWith;

@RunWith(EvoRunner.class) @EvoRunnerParameters(useVNET = true, separateClassLoader = true, useJEE = true) 
public class A_ESTest extends A_ESTest_scaffolding {

  @Test(timeout = 4000)
  public void test0()  throws Throwable  {
      A a0 = new A();
      B b0 = mock(B.class, new ViolatedAssumptionAnswer());
      doReturn((String) null).when(b0).get(anyInt());
      String string0 = a0.test(b0);
      assertNull(string0);
  }
}

对于可能发生被零除的方法,EvoSuite 生成的测试用例甚至会捕获异常以确保测试用例通过:

import org.junit.Test;
import static org.junit.Assert.*;
import static org.evosuite.runtime.EvoAssertions.*;
import org.evosuite.runtime.EvoRunner;
import org.evosuite.runtime.EvoRunnerParameters;
import org.junit.runner.RunWith;
import test.Case2;

@RunWith(EvoRunner.class) @EvoRunnerParameters(useVNET = true, separateClassLoader = true, useJEE = true) 
public class Case2_ESTest extends Case2_ESTest_scaffolding {

  @Test(timeout = 4000)
  public void test8()  throws Throwable  {
      Case2 case2_0 = new Case2();
      // Undeclared exception!
      try { 
        case2_0.add(6, 0);
        fail("Expecting exception: ArithmeticException");

      } catch(ArithmeticException e) {
         //
         // / by zero
         //
         verifyException("test.Case2", e);
      }
  }
}

EvoSuite 自动生成的测试用例是否总是通过,就像这些示例一样?如何让 EvoSuite 生成可能失败的测试用例,从而让开发人员直接使用?

标签: javaevosuite

解决方案


EvoSuite 自动生成的测试用例是否总是通过,就像这些示例一样?

EvoSuite 站点提供了描述该软件的理论和操作的大量出版物列表。然而,将其归结为最简单的术语,该软​​件会生成测试用例来检测被测软件中的突变,这些突变会改变其行为并且不会被现有测试捕获。因此,被测软件的实际行为是基线,因此在未修改的软件上生成的测试都不应该失败。

如何让 EvoSuite 生成可能失败的测试用例,从而让开发人员直接使用?

我看不出任何软件怎么可能做到这一点。EvoSuite 应该如何将软件的任何特定行为识别为不正确,从而生成失败案例?考虑您的除零示例。被测方法显然会ArithmeticException在其第二个参数为 0 时抛出一个。EvoSuite 应该如何知道这不是该方法应该执行的操作?

如果软件能够先验地识别被测代码应该做什么,那么更好地应用这一非凡壮举将是让它(重新)编写实际代码。

但这并不意味着开发人员不能使用 EvoSuite 测试。开发人员至少可以通过以下方式使用它们:

  1. 开发人员可以分析生成的测试,以检测被测软件表现出的意外行为。这是一件非常酷且有价值的事情,但也许它不适合您“直接”使用测试。

  2. 许多测试将正确地断言预期的行为,并且这些可以在软件的测试套件中按原样使用。生成的整体套件将提供比许多软件更好的回归保护。

  3. 即使是断言不正确行为的测试也可能有用,它不是用于提前检测缺陷,而是用于在通过其他方式检测到缺陷后对其进行表征。例如,假设您从字段中得到一个报告,该方法widget.frob()抛出了一个意想不到的UpYoursException,但导致它的情况尚不清楚。您的 EvoSuite 测试很有可能已经显示了至少一种从受影响的方法中引发此异常的方法。这可能不符合“直接”使用测试的条件,但它是不试图提前清除不正确的自动测试用例的理由(也没有修复被测代码)。

底线:EvoSuite 提供了对手写测试用例的补充,而不是替代它们。


推荐阅读