参数化单元测试套件 [英] Parameterized unit test suites
问题描述
我正在尝试设置一些参数化的测试套件,遗憾的是到目前为止没有任何运气。
我有两组参数,我想用所有可能的组合运行多个测试用例(它们在不同的类中)。我尝试用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:
-
TestSuite1.class
设置一组参数,然后它开始TestSuite2.class
。 -
TestSuite2.class
sets在第二组参数上,然后它启动将使用这两个参数的实际测试。
TestSuite1.class
sets up one set of parameters, then it startsTestSuite2.class
.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屋!