带参数的 JUnit 测试

JUnit test with arguments

我开发了一个基于 Web 的应用程序,它可以让用户通过输入值而不是编写完整的 JUnit 测试来提交测试用例。

我现在使用的方法是为每次提交生成一个测试class,然后编译它并运行。

例如假设我们有一个 class 如下所示:

public class CalculatorO
{    
    public  boolean isPrime( int n )
    {
        if (n < 2) {
            return false;
        }
        int count = 0;
        for (int i = 1; i <= n; i++) {
            if (n % i == 0) {
                count++;
            }
        }
        if (count == 2) {
            return true;
        } else {
            return false;
        }
    }
}

作为 oracle,另一个 class 如下所示:

public class CalculatorM0
{    
    public  boolean isPrime( int n )
    {
        if (n < 2) {
            return false;
        }
        int count = 0;
        for (int i = 1; i <= n; i++) {
            if (n * i == 0) {
                count++;
            }
        }
        if (count == 2) {
            return true;
        } else {
            return false;
        }
    }    
}

作为测试对象。然后我生成一个测试模板如下:

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertArrayEquals;
import static org.unitils.reflectionassert.ReflectionAssert.assertReflectionEquals;
import org.junit.Test;

public class {{TestClassName}} {
  @Test
  public void {{MethodName}}() {
    int AO = {{valueA}};


    int AM = {{valueA}};

    {{OriginalClassName}} {{OriginalClassNameLower}} = new {{OriginalClassName}}();
    {{MutantClassName}} {{MutantClassNameLower}} = new {{MutantClassName}}();

    {{MethodReturnType}} resultO = {{OriginalClassNameLower}}.{{MethodName}}(AO);
    {{MethodReturnType}} resultM = {{MutantClassNameLower}}.{{MethodName}}(AM);

    assertEquals(resultO, resultM);     
  }
}

然后例如当用户提交数字 3 作为输入值时,我会像这样操作测试模板:

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertArrayEquals;
import static org.unitils.reflectionassert.ReflectionAssert.assertReflectionEquals;
import org.junit.Test;

public class CalculatorOCalculatorM0Test30099 {
  @Test
  public void isPrime() {
    int AO = 3;     
    int AM = 3;

    CalculatorO calculatorO = new CalculatorO();
    CalculatorM3 calculatorM3 = new CalculatorM3();

    boolean resultO = calculatorO.isPrime(AO);
    boolean resultM = calculatorM3.isPrime(AM);

    assertEquals(resultO, resultM);     
  }
}

然后我编译测试用例并运行它。

主要问题是这个循环经常发生,并且由于服务器的负载强加,由于正在创建和编译文件,服务器面临内存不足的问题并且经常崩溃。

我正在寻找一种方法来一次创建测试用例并构建一次,然后 运行 为每个带参数的输入构建它。

我的意思是这样的:

java -cp .;../../JUnitLibs/junit-4.12.jar;../../JUnitLibs/hamcrest-core-1.3.jar org.junit.runner.JUnitCore CalculatorOCalculatorM0Test30099 > CalculatorOCalculatorM0Test30099Result -input 3

一个简单的解决方案:

  • 我会使用 properties 在命令行中传递这些参数
  • 将 @BeforeClass 方法添加到您的测试用例...然后您转到属性,并从那里读取所有必需的值。

换句话说:你用一些 -Darg1:value1 值调用你的测试用例;并且您的测试用例确实查找 "arg1";并将提供的值存储到一些 字段 例如 AO 和 AM 中。

当然,您必须稍微修改一下代码;棘手的部分可能与此处的变量类型有关(属性都是字符串;但您可能需要 int、float ……变量)。更进一步,您可以简单地创建一个助手 class 来提供如下方法:

public static class PropertyWrapper {
  int getInt(String propertyName) { ...

然后你将你的模式替换成类似

的东西
int AO = PropertyWrapper.getInt({{valueAPropertyName}});

当然,只有当您有 不同的 JVM 运行 不同的用户请求时,这才(容易)起作用。意思是:当你有 two java 运行s,并且给每个 different args 时,每个单元测试都会看到不同 值。当您有 one JVM 应该 运行 使用不同的参数多次进行此测试时,事情就会变得更加复杂。然后你会让 getInt() 方法有一个 list 的值; return一个接一个;或类似的东西。