Java 如何使用不同的测试数据多次运行同一个JUnit测试?

Java 如何使用不同的测试数据多次运行同一个JUnit测试?,java,unit-testing,junit,Java,Unit Testing,Junit,我刚刚开始单元测试。我从tutorial points网站的pdf文件中编写了junit教程。所以我的问题是,我想测试我的调车场算法和RPNEvaluator 构造函数(以及帮助您处理上下文的任何其他变量)如下所示: 调车场.java: private ArrayList<String> tokens = new ArrayList<String>(); public ShuntingYard(ArrayList<String> tokens) { t

我刚刚开始单元测试。我从tutorial points网站的pdf文件中编写了junit教程。所以我的问题是,我想测试我的调车场算法和RPNEvaluator

构造函数(以及帮助您处理上下文的任何其他变量)如下所示:

调车场.java:

private ArrayList<String> tokens = new ArrayList<String>();
public ShuntingYard(ArrayList<String> tokens) {
    this.tokens = tokens;
}
private ArrayList tokens=new ArrayList();
公共调车场(ArrayList代币){
this.tokens=代币;
}
RPNEvaluator.java:

private Queue<String> polishExpression;
public RPNEvaluator(Queue<String> exp) {
    polishExpression = exp;
}
专用队列压缩;
公共RPNEvaluator(队列扩展){
PoliHexPression=exp;
}
java有一个名为toRpn()的方法,该方法将获取一个ArrayList,并在一些处理之后返回一个队列

RPNEvaluator有一个名为evaluate的方法,该方法将采用队列类型并在某些处理后返回double

对于Junit,我正在尝试编写一些单元测试,我想知道这是否是最好的开始方式:

package testSuite;

import static org.junit.Assert.fail;

import java.util.ArrayList;

import org.junit.Before;
import org.junit.Test;

public class ExpressionEvaluationTest {

    /**
     * Initialise the lists to be used
     */
    @Before
    public void beforeTest() {
        ArrayList<String> exprOne = new ArrayList<String>();
        exprOne.add("3");
        exprOne.add("+");
        exprOne.add("4");
        exprOne.add("*");
        exprOne.add("2");
        exprOne.add("/");
        exprOne.add("(");
        exprOne.add("1");
        exprOne.add("-");
        exprOne.add("5");
        exprOne.add(")");
        exprOne.add("^");
        exprOne.add("2");
        exprOne.add("^");
        exprOne.add("3");

        ArrayList<String> exprTwo = new ArrayList<String>();
        exprTwo.add("80");
        exprTwo.add("+");
        exprTwo.add("2");

        ArrayList<String> exprThree = new ArrayList<String>();
        exprThree.add("2");
        exprThree.add("/");
        exprThree.add("1");
        exprThree.add("*");
        exprThree.add("4");

        ArrayList<String> exprFour = new ArrayList<String>();
        exprFour.add("11");
        exprFour.add("-");
        exprFour.add("(");
        exprFour.add("2");
        exprFour.add("*");
        exprFour.add("4");
        exprFour.add(")");

        ArrayList<String> exprFive = new ArrayList<String>();
        exprFive.add("120");
        exprFive.add("/");
        exprFive.add("(");
        exprFive.add("10");
        exprFive.add("*");
        exprFive.add("4");
        exprFive.add(")");

        ArrayList<String> exprSix = new ArrayList<String>();
        exprSix.add("600");
        exprSix.add("*");
        exprSix.add("2");
        exprSix.add("+");
        exprSix.add("20");
        exprSix.add("/");
        exprSix.add("4");
        exprSix.add("*");
        exprSix.add("(");
        exprSix.add("5");
        exprSix.add("-");
        exprSix.add("3");
        exprSix.add(")");

    }

    @Test
    public void test() {

    }

}
包测试套件;
导入静态org.junit.Assert.fail;
导入java.util.ArrayList;
导入org.junit.Before;
导入org.junit.Test;
公共类表达式评估测试{
/**
*初始化要使用的列表
*/
@以前
测试前公共无效(){
ArrayList exprOne=新的ArrayList();
解释添加(“3”);
exprOne.添加(“+”);
解释添加(“4”);
exprOne.添加(“*”);
解释添加(“2”);
exprOne.添加(“/”);
解释添加(“(”);
解释添加(“1”);
解释添加(“—”);
解释添加(“5”);
exprOne.添加(“)”;
解释添加(“^”);
解释添加(“2”);
解释添加(“^”);
解释添加(“3”);
ArrayList exprTwo=新的ArrayList();
exprTwo.添加(“80”);
exprTwo.添加(“+”);
exprTwo.添加(“2”);
ArrayList exprtTree=新的ArrayList();
exprtree.添加(“2”);
exprtree.添加(“/”);
exprtree.添加(“1”);
exprtree.添加(“*”);
exprtree.添加(“4”);
ArrayList exprFour=新的ArrayList();
新增四项(“11”);
exprFour.添加(“-”);
exprFour.添加(“”);
添加四个解释(“2”);
exprFour.add(“*”);
添加四个解释(“4”);
exprFour.add(“)”;
ArrayList exprFive=新的ArrayList();
解释添加(“120”);
exprFive.添加(“/”);
exprFive.添加(“(”);
解释添加(“10”);
exprFive.添加(“*”);
解释添加(“4”);
exprFive.添加(“)”;
ArrayList exprSix=新的ArrayList();
解释添加(“600”);
exprSix.添加(“*”);
解释添加(“2”);
exprSix.添加(“+”);
解释添加(“20”);
exprSix.添加(“/”);
解释添加(“4”);
exprSix.添加(“*”);
exprSix.添加(“(”);
解释添加(“5”);
exprSix.添加(“-”);
解释添加(“3”);
exprSix.添加(“)”;
}
@试验
公开无效测试(){
}
}
我将把它放在before()方法中: 调车场sy=新调车场(/arraylist here/)

然后在测试中,将列表传递给算法。我的问题是,我想我已经做了很长一段时间了,有一个参数化的注释并将这些列表作为参数列表传递会更好吗

还有一个问题:如果对任何ArrayList的测试通过,那么我确信我可以对RPNEvaluator求值方法执行后续测试。我希望我没有模棱两可


非常感谢您的帮助。

我会以不同的方式处理。不只是创建几组测试数据,每次调用同一个测试,而是将其分解成有意义的内容。不要编写一个名为
test()
的测试,而是为
调车场的每个方面编写几个单独的测试。例如:

@Test public void 
itDoesntDivideByZero()
{
    ArrayList<String> divideByZeroExpression = Arrays.asList("5", "0", "/");
    // Add code to call your method with this data here
    // Add code to verify your results here
}

@Test public void 
itCanAdd()
{
    ArrayList<String> simpleAdditionExpression = Arrays.asList("1", "2", "+");
    // Add code to call your method with this data here
    // Add code to verify your results here
}
您可能会得到一个测试套件,该套件如下所示:

@Test public void
itAddsOne()
{
    int numberToAddTo = 1;
    int result = new Adder().addOneTo(numberToAddTo);
    assertEquals("One plus one is two", 2, result);
}

@Test(expected="NullPointerException.class") public void
itChokesOnNulls()
{
   new Adder().addOneTo((Integer)null);
}

@Test public void
itDoesntOverflow()
{
    int result = new Adder().addOneTo(Integer.MAX_VALUE);
    // do whatever here to make sure it worked correctly
}

依此类推。

我的看法会有点不同。不只是创建几组测试数据,每次调用同一个测试,而是将其分解成有意义的内容。不要编写一个名为
test()
的测试,而是为
调车场的每个方面编写几个单独的测试。例如:

@Test public void 
itDoesntDivideByZero()
{
    ArrayList<String> divideByZeroExpression = Arrays.asList("5", "0", "/");
    // Add code to call your method with this data here
    // Add code to verify your results here
}

@Test public void 
itCanAdd()
{
    ArrayList<String> simpleAdditionExpression = Arrays.asList("1", "2", "+");
    // Add code to call your method with this data here
    // Add code to verify your results here
}
您可能会得到一个测试套件,该套件如下所示:

@Test public void
itAddsOne()
{
    int numberToAddTo = 1;
    int result = new Adder().addOneTo(numberToAddTo);
    assertEquals("One plus one is two", 2, result);
}

@Test(expected="NullPointerException.class") public void
itChokesOnNulls()
{
   new Adder().addOneTo((Integer)null);
}

@Test public void
itDoesntOverflow()
{
    int result = new Adder().addOneTo(Integer.MAX_VALUE);
    // do whatever here to make sure it worked correctly
}

等等。

Mike B的建议非常好,试着在每个行为/功能的一个测试中分离您的测试思维

为了使您的测试更具可读性,我可能会为接收字符串的类ShutchingYard编写一个静态构造函数,然后您可以编写:

调车场添加=调车场。CreateFromExpression(“2+2”); 断言(addition.getRpn().evaluate(),为(4))

您可以进行更多重构,并以类似的方式结束:

资产(评估(“2+2”)为(4))

这很容易理解,也很容易阅读,此外,在不同的场景中编写更多的测试,只需一行代码

另一个选择是编写参数化测试,一个例子:,但在我看来,它们真的很难看。此测试通常称为“数据驱动测试”,当您希望使用不同的输入值测试同一代码时,可以使用此测试


对于这个数据驱动的测试,更好的选择是使用spock之类的东西,这是一个groovy测试框架,允许您编写难以置信的语义测试,当然您也可以使用它来测试java代码,请查看:

Mike B的建议非常好,试着在每个行为/功能的一个测试中分离您的测试思维

为了使您的测试更具可读性,我可能会为接收字符串的类ShutchingYard编写一个静态构造函数,然后您可以编写:

调车场添加=调车场。CreateFromExpression(“2+2”); 断言(addition.getRpn().evaluate(),为(4))

您可以进行更多重构,并以类似的方式结束:

资产(评估(“2+2”)为(4))

易于理解和阅读,