繁体   English   中英

如何参数化junit Test Suite

[英]How to parameterize junit Test Suite

可以在junit 4中参数化TestSuite吗?

为了将类声明为测试套件,我需要注释@RunWith(Suite.class) ,但是也需要相同的注释来将测试声明为参数化: @RunWith(Parameterized.class)所以我不能将它们都添加到同一个类中。

我在这个网站上发现了一个类似的问题并没有多大帮助。 到目前为止,我发现的所有示例都解释了如何参数化简单的单元测试,而不是完整的测试。

我相信基本答案是否,因为正如你所说,@ RunsWith只接受一个参数。 我找到了一篇博文,在如何处理这种情况方面有点创意

我们不使用参数化测试,但您可以创建一个单独的套件,就像我们那样只列出测试类,参数化测试可能是其中的一部分。 我修改了我们的测试套件,将参数化测试类包含在套件的一部分中,并且运行正常。 我们创建了我们的套件,如下所示PrimeNumberCheckerTest是一个简单的我从网上拉出来的。

package com.jda.portfolio.api.rest.server;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({  com.mycompany.api.rest.server.resource.TestCartResourceJava.class, 
                 com.mycompany.api.rest.server.resource.TestCustomerResource.class,
                 com.mycompany.api.rest.server.resource.TestWizardProfileResource.class,
                 com.mycompany.api.rest.server.interceptor.TestBaseSearchInterceptor.class, 
                 com.mycompany.api.rest.server.resource.TestQueryParameters.class, 
                 com.mycompany.api.rest.server.expression.TestCartExpressionGenerator.class, 
                 com.mycompany.api.rest.server.expression.TestPreferenceExpressionGenerator.class, 
                 com.mycompany.api.rest.server.PrimeNumberCheckerTest.class, 
                 })
public class AllTests {}

这是参数化测试用例的来源;

package com.jda.portfolio.api.rest.server:

import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Parameterized.class)
@SuiteClasses({PrimeNumberCheckerTest.class})
public class PrimeNumberCheckerTest {
  private Integer inputNumber;
  private Boolean expectedResult;
  private PrimeNumberChecker primeNumberChecker;

  @Before
  public void initialize() {
     primeNumberChecker = new PrimeNumberChecker();
  }

  // Each parameter should be placed as an argument here
  // Every time runner triggers, it will pass the arguments
  // from parameters we defined in primeNumbers() method
  public PrimeNumberCheckerTest(Integer inputNumber, 
     Boolean expectedResult) {
     this.inputNumber = inputNumber;
     this.expectedResult = expectedResult;
  }

  @Parameterized.Parameters
  public static Collection primeNumbers() {
     return Arrays.asList(new Object[][] {
        { 2, true },
        { 6, false },
        { 19, true },
        { 22, false },
        { 23, true }
     });
  }

  // This test will run five times since we have as many parameters defined
  @Test
  public void testPrimeNumberChecker() {
     System.out.println("Parameterized Number is : " + inputNumber);
     assertEquals(expectedResult, 
     primeNumberChecker.validate(inputNumber));
  }

我能够参数化测试套件并在套件的测试类成员中使用其数据,如下所示:

在JUTsuite:

@RunWith(Suite.class)
@Suite.SuiteClasses({ 
    JUT_test1.class,
})

public class JUTSuite{  
    // Declare all variables/objects you want to share with the test classes, e.g.
    protected static List<Fx> globalFxs;
    // This is the data list we'll use as parameters
    protected static List<Dx> globalDxs;

    @Parameters
    public static Collection<Object[]> data(){
        // Instantiate object list for parameters.  
        // Note: you must do it here and not in, say, @BeforeClass setup()
        // e.g.
        globalDxs=new ArrayList<Dx>(serverObj.values());

        Collection<Object[]> rows=new ArrayList<Object[]>();
        for(Dx d:globalDxs) {
            rows.add(new Object[]{d});
        }
        return rows;
    }

    @BeforeClass
    public static void setUp() throws Exception {
        // Instantiate/initialize all suite variables/objects to be shares with test classes
        // e.g. globalFxs=new ArrayList<Fx>();
    }

    @AfterClass
    public static void tearDown() throws Exception {
        // Clean up....
    }
}

接下来,在测试类中:

@RunWith(Parameterized.class)
public class JUT_test1 {
    // declare local names (if desired) for suite-wide variable/objects 
    // e.g. 
    private static List<Fx> globalFxs;

    // This is the test parameter:      
    private Dx d;

    public JUT_test1(Dx d){
        this.d=d;
    }

    @Parameters
    public static Collection<Object[]> data(){
    // Note: we're calling the suite's data() method which has already executed.
        return JUTSuite.data();
    }

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
    // (If desired)initialize local variables by referencing suite variables.
    // e.g.globalFxs=JUTSuite.globalFxs;
    }
}

我同意,使用提供的课程是不可能的,但有一些解决方法可以帮助你完成大部分工作,比如@ mikemil。

我花了一些时间来扩展Suite并委托参数化,取得了部分成功; 可以构建满足您需要的运行器,并且代码在这两个类中或多或少地为您编写。 这些类交互的方式(特别是Parameterized#getChildren()的定义)使得难以扩展或委托给那些类来完成你需要的东西,但创建一个全新的类而不是扩展ParentRunner并从其他两个中ParentRunner代码会很容易的。

我会试着花更多的时间再回到这里。 如果你在我开始之前建立一个新跑步者,请将其作为答案发布,我很乐意自己使用它。

你是对的: SuiteParameterized都是Runners,一次只能运行一个Runner来运行测试。 标准JUnit 4不提供组合的Runner。

您可以实现自己的Runner,也可以查看这个随时可用的库,它提供了一个ParameterizedSuite Runner: https//github.com/PeterWippermann/parameterized-suite

参数化测试套件如下所示:

@RunWith(ParameterizedSuite.class)
@SuiteClasses({OneTest.class, TwoTest.class})
public class MyParameterizedTestSuite {
    @Parameters(name = "Parameters are {0} and {1}")
    public static Object[] params() {
        return new Object[][] {{'A',1}, {'B',2}, {'C',3}};
    }

最好的解决方案是,将套装类别分别保留在空白类中。 例如,我将登录测试为参数化测试并放入套装(用于导航性能测量)

     @RunWith(Suite.class)
@Suite.SuiteClasses({
            LoginPageTest.class,
            HomePageTests.class})
    public class PerformanceTests {
    }

和LoginPageTest实际上是参数化测试

@RunWith(Parameterized.class)
public class LoginPageTest
{...}

如前所述,不可能使用JUnit 4提供的运行程序来参数化测试套件。

无论如何,我不建议让你的测试类依赖于一些外部提供的状态。 如果你想运行一个测试类怎么办?

我建议你制作单独的测试类@Parameterized并使用实用程序类来提供参数:

@RunWith(Suite.class)
@SuiteClasses({ Test1.class, Test2.class })
public class TestSuite {
    // suite
}

@RunWith(Parameterized.class}
public class Test1 {
    public Test1(Object param1) { /* ... */ }

    @Parameters
    public static Collection<Object[]> data() {
        return TestParameters.provideTestData()
    }

    @Test
    public void someTest() { /* ... */ }
}

@RunWith(Parameterized.class}
public class Test2 {
    public Test2(Object param1) { /* ... */ }

    @Parameters
    public static Collection<Object[]> data() {
        return TestParameters.provideTestData()
    }

    @Test
    public void someOtherTest() { /* ... */ }
}

class TestParameters {
    public static Collection<Object[]> provideTestData() {
        Collection<Object[]> data = new ...;
        // build testdata
    return data;
}

也许这个答案有帮助: 参数化的单元测试套件

它使用@RunWith(Enclosed.class)并且似乎解决了这个问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM