【问题标题】:JUnit test with arguments带参数的 JUnit 测试
【发布时间】:2017-05-03 05:30:08
【问题描述】:

我开发了一个基于 Web 的应用程序,在某种程度上让用户只需输入值即可提交测试用例,而不是编写完整的 JUnit 测试。

我目前使用的方式是为每次提交生成一个测试类,然后编译并运行。

例如假设我们有一个像下面这样的类:

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,以及像下面这样的另一个类:

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

【问题讨论】:

  • 我使用 Zohhak 进行参数化测试:piotrturski.github.io/zohhak
  • @Dawood ibn Karim,这样参数应该在构建文件之前出现在测试类中。但是我提到的论点(参数)在运行时很快就出现了。
  • 虽然很长一段时间来自发布的答案,但从那时起我正在使用这个解决方案并且它是完美的。如果有人需要源代码示例,我也可以分享。谢谢@GhostCat。
  • @GhostCat,我想我没有明白你的真正意思。如果有什么我可以做的,请告诉我。感谢您的精彩回答。

标签: java junit arguments parameterized


【解决方案1】:

一个简单的解决方案:

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

换句话说:你用一些-Darg1:value1 值调用你的测试用例;并且您的测试用例会查找“arg1”;并将提供的值存储到一些 fields AO 和 AM 例如。

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

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

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

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

当然,这仅在您有 不同 JVM 运行不同用户请求时(很容易)起作用。含义:当您有 两个 java 运行并为每个运行提供 不同 参数时,每个单元测试都会看到 不同 值。当您有 一个 JVM 应该使用不同的参数多次运行此测试时,事情会变得更加复杂。然后,您将让该 getInt() 方法具有 list 值;并一个接一个地返回;或类似的东西。

【讨论】:

  • 这些系统属性在每个实例中是独立的吗?我的意思是如果两个测试用例同时达到这个阶段怎么办?
  • 如果我没记错的话,java的每个进程都使用不同的JVM。这是真的吗?
  • 我不知道你的设置是怎么做的。但是当你在命令行上问:“什么时候调用java”时;这会导致独立的JVM实例吗?答案很简单:是的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-19
  • 1970-01-01
相关资源
最近更新 更多