带参数的 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一个接一个;或类似的东西。
我开发了一个基于 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一个接一个;或类似的东西。