Java JUnit3.x中的参数化测试用例类

Java JUnit3.x中的参数化测试用例类,java,junit,Java,Junit,我有一个JUnit3.x测试用例,我希望能够参数化它。我想参数化整个测试用例(包括夹具)。但是,TestSuite.addTestSuite()方法不允许be传递TestCase对象,只允许传递一个类: TestSuite suite = new TestSuite("suite"); suite.addTestSuite(MyTestCase.class); 我希望能够将参数(字符串)传递给MyTestCase实例,该实例是在测试运行时创建的。现在,我必须为每个参数值创建一个单独

我有一个JUnit3.x测试用例,我希望能够参数化它。我想参数化整个
测试用例
(包括夹具)。但是,
TestSuite.addTestSuite()
方法不允许be传递
TestCase
对象,只允许传递一个类:

   TestSuite suite = new TestSuite("suite");
   suite.addTestSuite(MyTestCase.class);
我希望能够将参数(字符串)传递给MyTestCase实例,该实例是在测试运行时创建的。现在,我必须为每个参数值创建一个单独的类

我尝试将其传递给任意子类:

   MyTestCase testCase = new MyTestCase() {
       String getOption() {
           return "some value";
       }
   }

   suite.addTestSuite(testCase.getClass());
但是,该断言失败:

   ... MyTestSuite$1 has no public constructor TestCase(String name) or TestCase()`

有什么想法吗?我是否错误地攻击了这个问题?< /p> < p>如果这是java 5或更高,你可能想考虑切换到JUnit 4,它支持内置的参数化测试用例。

< P>而不是为你想要测试的多个/不同的后端创建参数化的测试用例,我会考虑使我的测试用例抽象化。API的每个新实现都需要提供一个实现TestCase类

如果您当前有一个类似的测试方法

public void testSomething() {
   API myAPI = new BlahAPI();
   assertNotNull(myAPI.something());
}
只需向TestCase添加一个抽象方法,该方法返回要使用的特定API对象

public abstract class AbstractTestCase extends TestCase {
    public abstract API getAPIToTest();

    public void testSomething() {
       API myAPI = getAPIToTest();
       assertNotNull(myAPI.something());
    }

    public void testSomethingElse() {
       API myAPI = getAPIToTest();
       assertNotNull(myAPI.somethingElse());
    }
}
然后,要测试的新实现的TestCase只需实现AbstractTestCase并提供API类的具体实现:

public class ImplementationXTestCase extends AbstractTestCase{

    public API getAPIToTest() {
        return new ImplementationX();
    }
}

然后,在抽象类中测试API的所有测试方法都将自动运行。

好的,下面是JUnit4如何运行参数化测试的快速模型,但在JUnit3.8.2中完成

基本上,我正在子类化并严重劫持TestSuite类,以便根据testMethods和参数的叉积填充测试列表

不幸的是,我不得不从TestSuite本身复制几个helper方法,一些细节并不完美,例如IDE中的测试名称在参数集上是相同的(JUnit 4.x附加了
[0]
[1]
,…)

尽管如此,在JUnit附带的文本和AWT
TestRunner
s以及Eclipse中,这似乎运行良好

这里是ParameterizedTestSuite,下面是一个使用它的参数化测试的(愚蠢的)示例

(最后一点注意:我写这篇文章时考虑到了Java5,如果需要的话,适应1.4应该很简单)

ParameterizedTestSuite.java:

包junit.parameterized;
导入java.lang.reflect.Constructor;
导入java.lang.reflect.InvocationTargetException;
导入java.lang.reflect.Method;
导入java.lang.reflect.Modifier;
导入java.util.ArrayList;
导入java.util.Collection;
导入junit.framework.Test;
导入junit.framework.TestCase;
导入junit.framework.TestSuite;
公共类ParameteredTestSuite扩展了TestSuite{
公共参数化测试套件(
最后一堂课(第二堂课){
字符串名称=m.getName();
if(name.contains(name))
返回;
如果(!isPublicTestMethod(m)){
如果(isTestMethod(m))
addTest(警告(“测试方法不是公共的:+m.getName()));
返回;
}
名称。添加(名称);
}
私有布尔isPublicTestMethod(方法m){
返回isTestMethod(m)和&Modifier.isPublic(m.getModifiers());
}
私有布尔isTestMethod(方法m){
字符串名称=m.getName();
类[]参数=m.getParameterTypes();
类returnType=m.getReturnType();
return parameters.length==0&&name.startsWith(“test”)&&returnType.equals(Void.TYPE);
}
私有void addConstructionException(异常e){
addTest(警告(“测试用例实例化失败”)
+e.getClass().getName()+“”+e.getMessage());
}
}
ParameterizeTest.java:

包junit.parameterized;
导入java.util.array;
导入java.util.Collection;
导入junit.framework.Test;
导入junit.framework.TestCase;
导入junit.parameterized.ParameterizedTestSuite;
公共类ParameteredTest扩展了TestCase{
私有最终整数值;
私营国家;
公共静态集合参数(){
返回数组.asList(
新对象[]{1},
新对象[]{2},
新对象[]{-2}
);
}
公共参数化测试(最终整数值){
这个值=值;
}
公共void testMathPow(){
最终整数平方=值*值;
最终int-powSquare=(int)Math.pow(值,2)+状态;
assertEquals(方形、方形);
状态++;
}
公开无效测试div(){
最终int div=值/值;
资产质量(1,部门);
}
公共静态测试套件(){
返回新的ParameteredTestSuite(ParameteredTest.class,parameters());
}
}
注意:
evilState
变量仅用于显示所有测试实例都应该是不同的,并且它们之间没有共享状态

一些细节并不完美,例如IDE中的测试名称在参数集之间是相同的(JUnit 4.x附录[0]、[1]、…)

要解决此问题,只需覆盖getName()并更改测试用例类中的构造函数:

 private String displayName;

 public ParameterizedTest(final int value) {
     this.value = value;
     this.displayName = Integer.toString(value);
 }

 @Override
 public String getName() {
     return super.getName() + "[" + displayName + "]";
 }

对于Android项目,我们编写了一个称为测试参数化的库。比如说

public class ParameterizedTest extends TestCase {
  enum Drink { COKE, PEPSI, RC_COLA }

  private final Drink drink;

  // Nullary constructor required by Android test framework
  public ConstructorTest() {
    this(null);
  }

  public ConstructorTest(Drink drink) {
    this.drink = drink;
  }

  public void testSomething() {
    assertNotNull(drink);
  }
}

因为你没有使用Android,所以这并不是对你问题的回答,但是很多仍然使用JUnit 3的项目都是这样做的,因为Android的测试框架需要JUnit 3,所以我希望其他一些读者会觉得这很有帮助。

是的,我知道。不幸的是,Ant构建文件导出不支持JUnit 4.x,所以我必须选择automated builds和JUnit 4.x:-(我说的是Eclipse,我忘了说。啊,好吧。我们这里不使用Ant,但我们使用Eclipse和JUnit 4.x。我的情况相同,除了Android。Android只支持JUnit 3。回答“我攻击了吗?”
 private String displayName;

 public ParameterizedTest(final int value) {
     this.value = value;
     this.displayName = Integer.toString(value);
 }

 @Override
 public String getName() {
     return super.getName() + "[" + displayName + "]";
 }
public class ParameterizedTest extends TestCase {
  enum Drink { COKE, PEPSI, RC_COLA }

  private final Drink drink;

  // Nullary constructor required by Android test framework
  public ConstructorTest() {
    this(null);
  }

  public ConstructorTest(Drink drink) {
    this.drink = drink;
  }

  public void testSomething() {
    assertNotNull(drink);
  }
}