参数化单元测试套件 [英] Parameterized unit test suites

查看:133
本文介绍了参数化单元测试套件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试设置一些参数化的测试套件,遗憾的是到目前为止没有任何运气。
我有两组参数,我想用所有可能的组合运行多个测试用例(它们在不同的类中)。我尝试用JUnit4来做,但我无法正确设置它。这将是我的基本想法:

I am trying to set up some parameterized test suites, unfortunately without any luck so far. I have two set of parameters, and I would like to run multiple test cases (they are in different classes) with all possible combinations. I tried to do it with JUnit4, but I am unable to set it up correctly. This would be my basic idea:


  1. TestSuite1.class 设置一组参数,然后它开始 TestSuite2.class

  2. TestSuite2.class sets在第二组参数上,然后它启动将使用这两个参数的实际测试。

  1. TestSuite1.class sets up one set of parameters, then it starts TestSuite2.class.
  2. TestSuite2.class sets up the second set of parameters, then it starts the actual test(s) that will use both parameters.

同时似乎无法同时设置 Suite.class 同时 RunWith 注释中的 Parameterized.class (根据google,参数化扩展套件,如果我使用,我通常会发现没有找到可运行的方法消息。)

Meanwhile it seems it is not possible to set up both Suite.class and Parameterized.class in the RunWith annotation at the same time (according to google, Parameterized extends Suite, I get usually "no runnable method found" message if I use.)

这就是我的代码基本上是这样的:

This is how my code looks like basically:

TestSuite1.class:

TestSuite1.class:

@RunWith(Parameterized.class)
@Parameterized.SuiteClasses({TestSuite2.class})
//I have tried with @RunWith(Suite.class) and
//@Suite.SuiteClasses({TestSuite2.class}) annotations also - all combinations
public class TestSuite1{

  public TestSuite1(int number) {
    Params.first = number;
  } 

  @Parameters
  public static Collection<Object[]> parameters(){
    Object[][] data = new Object[][] { { 1 }, { 2 }, { 3 }, { 4 } };
    return Arrays.asList(data);
  }
}

TestSuite2.class 看起来与 TestSuite1.class 相同,只是我已将 TestCase1.class 添加到套件中而不是 TestSuite2 ,并且它在 Params 中设置另一个变量。

TestSuite2.class looks the same as TestSuite1.class, except that I have added TestCase1.class to the suite instead of TestSuite2, and that it sets another variable in Params.

TestCase1.class:

TestCase1.class:

public class TestCase1 {    
  @Test
  public void test1(){
    System.out.println("first: "+Params.first+" second: "+Params.second);
    Assert.assertTrue(true);
  }
}

我对所有想法持开放态度 - 即使使用TestNG也是如此例。我也试过了(虽然今天是我第一次看到它),但是我注意到套件与JUnit有点不同。我不想在测试之前设置XML文件,我想以编程方式解决所有设置。

I am open to all ideas - even with TestNG for example. I have tried it also (although today was the first time I saw it), but as I noticed the suites are a bit different than in JUnit. I would prefer not to set up XML files before testing, I would like to solve all set up programmatically.

我想用任何框架实现什么?

Is what I am trying to achieve possible with any framework?

更新:使用TestNG我有以下代码:

Update: With TestNG I have the following code:

Start.class:

Start.class:

public class Start {

public static void main(String[] args){
    TestListenerAdapter tla = new TestListenerAdapter();
    TestNG testng = new TestNG();
    testng.setTestClasses(new Class[] { FirstTest.class, SecondTest.class });
    testng.addListener(tla);
    testng.run();
}
}

Params.class:

Params.class:

public class Params {
@DataProvider(name = "param")
public static Object[][] createData() {
    Object[][] data = new Object[][] { { 1 }, { 2}, { 3}, { 4} };
    return data;
  }
}

FirstTest.class:

FirstTest.class:

public class FirstTest {

@Test(dataProvider = "param", dataProviderClass = Params.class)
public static void printIt(int number){
    System.out.println("FirstTest: "+number);
}

}

SecondTest .class FirstTest.class 相同。如果我运行它,它运行 FirstTest 4次,然后运行 SecondTest 4次。我想一次运行 FirstTest ,并且还使用第一组参数运行 SecondTest 一次。然后我想运行 FirstTest SecondTest 一次,使用第二组参数等。

SecondTest.class is the same as FirstTest.class. If I run this, it runs FirstTest 4 times, then it runs SecondTest 4 times. I would like to run FirstTest one time, and SecondTest one time also with the first set of parameters. Then I would like to run FirstTest and SecondTest one time, with the second set of parameters, etc.

我试图设置setPreserveOrder(true),并尝试了所有setParallel选项。然而,在这种方式上,结果是随机顺序。

I have tried to set setPreserveOrder(true), and tried all setParallel options also. On this way however the results are in kind of random order.

(这将是一些硒测试。我知道测试不应该相互依赖,但仍然这将是我想要的方式)

(It would be some selenium test. I am aware that tests should not depend on each other, but still it would be my desired way for this)

推荐答案

这里有一些其他建议似乎更灵活: @ RunWith(Enclosed.class)

Here some other suggest that seems to be much more flexible: @RunWith(Enclosed.class)

简而言之:
而不是 @ Suite.SuiteClasses(...),只需使用 @RunWith(Enclosed.class)并扩展你的测试类

In short: Instead of @Suite.SuiteClasses(...), just use @RunWith(Enclosed.class) and extend your Test Classes

@RunWith(Enclosed.class)
public class FastTest {

    public static class Test1FirstAppInit extends AppInitTest {    }

    public static class Test2Download extends DownloadTest{    }

    public static class Test3OtherTest extends OtherTest {    }
}

现在使用Para计量:

Now with Parameterized:

@RunWith(Enclosed.class)
public class FastTest {

    private static Iterable<? extends Object> mAllLocale = Arrays.asList(Locale.ENGLISH, Locale.GERMAN);
    private static Iterable<? extends Object> mSingleLocale = Arrays.asList(Locale.ENGLISH);

    /*
    Run test class for all Locale
     */
    @RunWith(Parameterized.class)
    public static class Test1FirstAppInit extends AppInitTest {
        @Parameterized.Parameter
        public Locale mLocale;

        @Parameterized.Parameters
        public static Iterable<? extends Object> data() {
            return mAllLocale;
        }

        @Override
        public Locale getLocale() {
            return mLocale;
        }

        @Override
        public void test001ResetAll {
            assumeTrue(false); // skip test completedly
        }


        @Override
        public void test002ClearAppData() {
            // replace existing test
            if (getLocale() != Locale.ENGLISH) {
                /*
                should run only on first Locale
                skip test on following Parameter runs
                 */
                assumeTrue(false); // skip test
            }
            else {
                super.test000ClearAppData();
            }
        }
    }

    /*
    Run test class only for one Locale
     */
    @RunWith(Parameterized.class)
    public static class Test2Download extends DownloadTest{
        @Parameterized.Parameter
        public Locale mLocale;

        @Parameterized.Parameters
        public static  Iterable<? extends Object> data(){
            return mSingleLocale;
        }

        @Override
        public Locale getLocale() {
            return mLocale;
        }

        @Override
        public void test900Delete() {
            assumeTrue(false); // skip test
        }
    }

    /*
    Test not Parameterized
     */
    public static class Test3OtherTest extends OtherTest {    }
}

参数化测试的测试类如下所示:

Your Test Classes for Parameterized tests look like this:

@RunWith(AndroidJUnit4.class)
@LargeTest
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class DownloadTest {

    public Locale getLocale() {
        // will be overwritten in @RunWith(Enclosed.class)
        // but we are still able to run test class separatedly
        return Locale.ENGLISH;
    }

    @Test
    public void test900Delete() {
        ....
    }
    ....
}

完全匹配我搜索的内容。我可以创建不同的测试场景(完整测试,快速测试......)。只需创建不同的@RunWith(Enclosed.class)类并扩展您想要包含的测试。

Matches exactly what I was searching for. I can create different Test scenarios (full test, fast test,...). Just create different @RunWith(Enclosed.class) classes and extend the tests that you want to include.

只有侧点似乎是Enclosed.class不关心排序顺序(如果对您很重要)。
我通过更换附件来解决它:

Only side point seems to be that Enclosed.class does not care about sort order (if important to you). I solved it by replacing Enclosed:

public class SortedEnclosed extends Suite {

    public SortedEnclosed(Class<?> klass, RunnerBuilder builder) throws Throwable {
        super(builder, klass, filterAbstractClasses(klass.getClasses()));
    }

    protected static Class<?>[] filterAbstractClasses(final Class<?>[] classes) {
        final List<Class<?>> filteredList= new ArrayList<Class<?>>(classes.length);

        for (final Class<?> clazz : classes) {
            if (!Modifier.isAbstract(clazz.getModifiers())) {
                filteredList.add(clazz);
            }
        }
        // this is new (there may be better way with own "@FixClassOrder"...):
        Collections.sort(filteredList, new Comparator<Class<?>>() {
            @Override
            public int compare(Class<?> o1, Class<?> o2) {
                return o1.getSimpleName().compareTo(o2.getSimpleName());
            }
        });
        //  
        return filteredList.toArray(new Class<?>[filteredList.size()]);
    }
}

然后使用 @RunWith (SortedEnclosed.class)

这篇关于参数化单元测试套件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆