当您需要在许多不同的输入值或配置上运行同一组测试时,动态测试生成很有用。 可以使用参数化测试或使用理论来实现。
当您有大量数据用作参数并想对所有组合进行测试时,这些理论非常有用。 您得到的控制较少,但是您不必自己编写合并和迭代的代码。 关于理论如何工作的基础知识在Java代码极客 (最初出现在Java出现日历 )上进行了解释,因此,本文重点关注参数化测试。
当您需要对输入值进行良好控制时,例如,带有用作输入的文件的目录或有意义的参数组合列表,则参数化测试会更好。
参数化测试
参数化测试是一种测试用例,能够接受参数以及您希望其运行的所有参数组合的列表。 JUnit遍历参数列表,使用每个参数初始化测试用例,然后运行其所有测试方法。
然后,GUI和Maven运行程序都将每个参数化的测试运行解释为单独的测试。 如果其中一些失败,则立即清楚哪些失败了,有多少失败了。
示例用例
Less4j对于css编译器来说较少,因此其每个测试都由一个较少输入的文件和一个预期CSS文件定义。 编译器在输入文件上运行,并将其输出与预期CSS进行比较。 如果它们匹配,则测试通过。
所有.less文件都存储在目录中。 参数化的测试用例读取该目录,并为每个文件创建一个jUnit测试。 因此,我们可以通过创建新的.less和.css添加新测试,通过“全部运行”按钮运行测试,并在所有报告中查看新测试。
如何使用它
参数化的测试用例必须具有以下内容:
-
@RunWith(Parameterized.class)
类注释, - 接受测试用例参数的构造函数,
- 带有
@Parameters
注释的静态方法以生成参数, - 在构造函数中提供的参数上运行的测试方法。
建设者
参数化的构造函数必须至少具有一个参数。 例如,编译器测试用例可以将较少的输入作为第一个参数,而将预期的已编译css作为第二个参数。 第三个参数name
将被忽略,稍后将进行说明:
@RunWith(Parameterized.class)
public class ParametrizedTest {public ParametrizedTest(String less, String expectedCss, String name) {this.less = less;this.expectedCss = expectedCss;}}
参量
生成参数的静态方法必须返回Iterable
接口的实现。 迭代器返回包含参数集的数组。 每个数组用于创建一个测试用例实例,其中的对象用作构造函数参数。
例如,以下方法返回两个数组,从而导致两个测试用例实例:
@Parameters(name="Name: {2}")
public static Iterable<Object[]> generateParameters() {List<Object[]> result = new ArrayList<Object[]>();result.add(new Object[] {"less", "css", "pass"});result.add(new Object[] {"less", "error", "fail"});return result;
}
name
注释参数是可选的。 其值将在GUI或maven报告中显示为测试用例名称。 {n}
是第n个数组值的占位符。 它们从0开始索引,因此第一个测试用例将被命名为Name: pass
,第二个测试用例将被命名为Name: fail
。
测试方法
参数化的测试用例可以具有任意数量的测试,并且必须使用@Test
批注进行批注:
@Test
public void testCss() { //dummy test methodString actualCss = compile(less);assertEquals(expectedCss, actualCss);
}@Test
public void testSourceMap() { //another test methodString actualCss = compile(less);assertEquals(expectedCss, actualCss);
}private String compile(String less) { //dummy compile methodreturn "css";
}
输出量
如果运行上面的测试类,则JUnit视图将显示以下结构:
[F] com.github.sommeri.jUnit4Examples.ParametrizedTest
[ ] |-- [Name: pass]
[ ] |---------------- testCss[Name: pass]
[ ] |---------------- testSourceMap[Name: pass]
[F] |-- [Name: fail]
[F] |---------------- testCss[Name: fail]
[F] |---------------- testSourceMap[Name: fail]
完整的测试案例
@RunWith(Parameterized.class)
public class ParametrizedTest {private String less;private String expectedCss;public ParametrizedTest(String less, String expectedCss, String name) {this.less = less;this.expectedCss = expectedCss;}@Parameters(name="Name: {2}")public static Iterable<Object[]> generateParameters() {List<Object[]> result = new ArrayList<Object[]>();result.add(new Object[] {"less", "css", "pass"});result.add(new Object[] {"less", "error", "fail"});return result;}@Testpublic void testCss() {String actualCss = compile(less);assertEquals(expectedCss, actualCss);}@Testpublic void testSourceMap() {String actualCss = compile(less);assertEquals(expectedCss, actualCss);}//dummy compile methodprivate String compile(String less) {return "css"; }
}
翻译自: https://www.javacodegeeks.com/2014/08/this-is-stuff-junit-dynamic-tests-generation.html