网站后台更新后主页没有变化,郸城县做网站,怎么样做钓鱼网站,网站域名解析设置JUnit 5令人印象深刻#xff0c;尤其是当您深入研究扩展模型和体系结构时 。 但是从表面上讲#xff0c;编写测试的地方#xff0c;开发的过程比革命的过程更具进化性 – JUnit 4上没有杀手级功能吗#xff1f; 幸运的是#xff0c;至少有一个#xff1a;参数化测试。 JU… JUnit 5令人印象深刻尤其是当您深入研究扩展模型和体系结构时 。 但是从表面上讲编写测试的地方开发的过程比革命的过程更具进化性 – JUnit 4上没有杀手级功能吗 幸运的是至少有一个参数化测试。 JUnit 5对参数化测试方法具有本机支持并且具有允许使用同一主题的第三方变体的扩展点。 在本文中我们将研究如何编写参数化测试-创建扩展将留待将来使用。 总览 这篇文章是有关JUnit 5的系列文章的一部分 设定 基本 建筑 移民 动态测试 参数化测试 扩展模型 条件 参数注入 … 本系列基于预发行版本Milestone 4并且在发布新的里程碑或GA版本时会进行更新。 另一个很好的来源是《 JUnit 5用户指南》 。 您可以在GitHub上找到所有代码示例。 在整个这篇文章中我将大量使用terms 参数和自变量 其含义并不相同。 根据维基百科 术语参数通常用于指代在函数定义中找到的变量而参数指代传递的实际输入。 您好参数化世界 参数化测试入门非常容易但是在开始乐趣之前您必须向项目添加以下依赖项 群组ID org.junit.jupiter 工件ID junit-jupiter-params 版本 5.0.0-M4 然后通过在ParameterizedTest而不是Test上声明带有参数和拍击的测试方法开始 ParameterizedTest
// somethings missing - where does word come from?
void parameterizedTest(String word) {assertNotNull(word);
} 看起来不完整– JUnit如何知道参数字应采用哪些参数 好吧因为您为其定义了零参数所以该方法将被执行零次并且实际上JUnit报告了该方法的Empty测试套件。 为了使事情发生您需要提供参数您可以从中选择各种来源。 可以说最简单的方法是ValueSource ParameterizedTest
ValueSource(strings { Hello, JUnit })
void withValueSource(String word) {assertNotNull(word);
} 确实现在测试执行了两次一次是“ Hello”一次是“ JUnit”。 在IntelliJ中如下所示 这就是开始进行参数化测试所需的一切 对于现实生活中的使用您应该了解ParamterizedTest的来龙去脉例如如何命名其他参数来源包括如何创建自己的以及到目前为止的更多知识。有点神秘的功能称为参数转换器。 我们现在将研究所有这些。 参数化测试的来龙去脉 使用ParameterizedTests创建测试很简单但是要充分利用该功能您需要了解一些细节。 测试名称 从上面的IntelliJ屏幕截图可以看出参数化的测试方法显示为带有每个调用的子节点的测试容器。 这些节点的名称默认为“ [{index}] {arguments}”但可以使用ParameterizedTest设置其他名称 ParameterizedTest(name run #{index} with [{arguments}])
ValueSource(strings { Hello, JUnit })
void withValueSource(String word) { } 只要修剪后的字符串不为空就可以将其用作测试的名称。 可以使用以下占位符 {index}从1开始计数测试方法的调用 此占位符被替换为当前调用的索引 {arguments}被方法的n个参数替换为{0}{1}…{n}到目前为止我们仅看到带有一个参数的方法 {i}被当前调用中第i个参数具有的参数替换 我们将在一分钟内介绍替代资源因此暂时忽略CsvSource的详细信息。 只需看看可以通过这种方式构建的出色测试名称尤其是与DisplayName一起使用 DisplayName(Roman numeral)
ParameterizedTest(name \{0}\ should be {1})
CsvSource({ I, 1, II, 2, V, 5})
void withNiceName(String word, int number) { } 非参数化参数 不管参数化测试如何JUnit Jupiter都已经可以将参数注入测试方法中 。 只要将每次调用中变化的参数排在首位这可以与参数化测试结合使用 ParameterizedTest
ValueSource(strings { Hello, JUnit })
void withOtherParams(String word, TestInfo info, TestReporter reporter) {reporter.publishEntry(info.getDisplayName(), Word: word);
} 与以前一样此方法被调用两次两次参数解析器都必须提供TestInfo和TestReporter的实例。 在这种情况下这些提供程序已内置在Jupiter中但是自定义提供程序例如用于模拟也将同样有效。 元注释 最后但并非最不重要的一点是ParameterizedTest以及所有源代码可以用作元注释来创建自定义扩展和注释 Params
void testMetaAnnotation(String s) { }Retention(RetentionPolicy.RUNTIME)
ParameterizedTest(name Elaborate name listing all {arguments})
ValueSource(strings { Hello, JUnit })
interface Params { }参数来源 三种成分进行参数化测试 有参数的方法 ParameterizedTest批注 参数值即参数 参数由源提供可以为测试方法使用任意数量的参数但至少应有一个否则测试将根本不会执行。 存在一些特定的资源但是您也可以自由创建自己的资源。 要理解的核心概念是 每个源都必须为所有测试方法参数提供参数因此第一个参数不能有一个源第二个参数不能有另一个源 该测试将对每组参数执行一次 价值来源 您已经看到了ValueSource的实际应用。 它使用起来非常简单并且可以为几种基本类型输入安全类型。 您只需应用注释然后从以下元素之一也可以是其中一个中进行选择 String [] strings int [] ints long [] longs double [] doubles 之前我向您展示了字符串–在这里您已经花费了很长时间 ParameterizedTest
ValueSource(longs { 42, 63 })
void withValueSource(long number) { } 有两个主要缺点 由于Java对有效元素类型的限制 它不能用于提供任意对象尽管对此有一种补救方法-请等到阅读有关参数转换器的信息之后 它只能用于具有单个参数的测试方法 因此对于大多数非平凡的用例您将不得不使用其他来源之一。 枚举来源 这是一个非常具体的资源您可以使用它为一个枚举或其子集的每个值运行一次测试 ParameterizedTest
EnumSource(TimeUnit.class)
void withAllEnumValues(TimeUnit unit) {// executed once for each time unit
}ParameterizedTest
EnumSource(value TimeUnit.class,names {NANOSECONDS, MICROSECONDS})
void withSomeEnumValues(TimeUnit unit) {// executed once for TimeUnit.NANOSECONDS// and once for TimeUnit.MICROSECONDS
} 直截了当吧 但是请注意 EnumSource只为一个参数创建参数这与源必须为每个参数提供参数的事实相结合这意味着它只能在单参数方法上使用。 方法来源 ValueSource和EnumSource非常简单并且在一定程度上受到了限制–一般方法的另一端是MethodSource。 它只是简单地命名将提供参数流的方法。 从字面上看 ParameterizedTest
MethodSource(names createWordsWithLength)
void withMethodSource(String word, int length) { }private static Stream createWordsWithLength() {return Stream.of(ObjectArrayArguments.create(Hello, 5),ObjectArrayArguments.create(JUnit 5, 7));
} Argument是一个包装对象数组的简单接口ObjectArrayArguments.createObject…args从提供给它的varargs创建它的实例。 支持注释的类完成了其余工作并且withMethodSource这样执行了两次一次用word “ Hello” / length 5一次用word “ JUnit 5” / length 7。 MethodSource命名的方法必须是静态的并且可以是私有的。 他们必须返回一种集合该集合可以是任何Stream包括原始的特殊性IterableIterator或数组。 如果源仅用于单个参数则可能空白返回此类实例而不将其包装在Argument中 ParameterizedTest
MethodSource(names createWords)
void withMethodSource(String word) { }private static Stream createWords() {return Stream.of(Hello, Junit);
} 就像我说的那样 MethodSource是Jupiter提供的最通用的资源。 但这会招致声明方法和将参数组合在一起的开销这对于较简单的情况来说有点多。 最好使用两个CSV来源。 CSV来源 现在它变得非常有趣。 能够在那时和那里为几个参数定义少数参数集而不必通过声明方法来很好吗 输入CsvSource 使用它您可以将每次调用的参数声明为以逗号分隔的字符串列表并将其余参数留给JUnit ParameterizedTest
CsvSource({ Hello, 5, JUnit 5, 7, Hello, JUnit 5!, 15 })
void withCsvSource(String word, int length) { } 在此示例中源标识了三组参数从而导致了三个测试调用然后继续将它们放在逗号上并将其转换为目标类型。 看到“HelloJUnit 515”中的单引号吗 这是使用逗号的方式而不会在该位置将字符串切成两半。 将所有参数都表示为字符串会引起一个问题即如何将它们转换为正确的类型。 我们待会儿会谈但是在我想快速指出之前如果您有大量输入数据则可以将它们自由存储在外部文件中 ParameterizedTest
CsvFileSource(resources word-lengths.csv)
void withCsvSource(String word, int length) { } 请注意资源可以接受多个文件名并将一个接一个地处理它们。 CsvFileSource的其他元素允许指定文件的编码行分隔符和定界符。 自定义参数来源 如果JUnit内置的源代码无法满足您的所有用例则可以自由创建自己的用例。 我将不赘述-足以说明您必须实现此接口… public interface ArgumentsProvider {Stream? extends Arguments provideArguments(ContainerExtensionContext context) throws Exception;} …然后将您的源代码与ArgumentsSourceMySource.class或自定义注释一起使用 。 您可以使用扩展上下文访问各种信息例如调用源的方法以便知道它有多少个参数。 现在开始转换这些参数 参数转换器 除了方法源之外参数源只能提供非常有限的类型类型字符串枚举和一些基元。 当然这不足以编写全面的测试因此需要一条通往更丰富的类型环境的道路。 参数转换器就是那条路 ParameterizedTest
CsvSource({ (0/0), 0, (0/1), 1, (1/1), 1.414 })
void convertPointNorm(ConvertPoint Point point, double norm) { } 让我们看看如何到达那里…… 首先一般观察无论所提供的参数和目标参数具有哪种类型都将始终要求转换器将其转换为另一种。 但是只有前面的示例声明了一个转换器那么在所有其他情况下会发生什么 默认转换器 Jupiter提供了一个默认转换器如果未应用其他转换器则将使用它。 如果参数和参数类型匹配则转换为空操作但如果参数为字符串则可以将其转换为多种目标类型 char或Character如果字符串的长度为1如果您使用UTF-32字符如表情符号因为它们包含两个Java字符则可能会使您失望 其他所有原语及其包装类型以及它们各自的valueOf方法 通过使用字符串和目标枚举调用Enum :: valueOf来获取任何枚举 一堆时间类型例如InstantLocalDateTime等OffsetDateTime等ZonedDateTimeYear和YearMonth及其各自的解析方法 这是一个简单的示例其中显示了其中一些操作 ParameterizedTest
CsvSource({true, 3.14159265359, JUNE, 2017, 2017-06-21T22:00:00})
void testDefaultConverters(boolean b, double d, Summer s, Year y, LocalDateTime dt) { }enum Summer {JUNE, JULY, AUGUST, SEPTEMBER;
} 受支持的类型的列表可能会随着时间的推移而增长但是很明显它不能包括特定于您的代码库的类型。 这是定制转换器输入图片的地方。 定制转换器 使用自定义转换器您可以将源发出的参数通常是字符串转换为要在测试中使用的任意类型的实例。 创建它们很容易–您所需要做的就是实现ArgumentConverter接口 public interface ArgumentConverter {Object convert(Object input, ParameterContext context)throws ArgumentConversionException;} 输入和输出是无类型的这有点令人讨厌但是因为Jupiter知道两者都不是所以在更具体的方面确实没有用。 您可以使用参数上下文获取有关要为其提供参数的参数的更多信息例如参数的类型或最终将在其上调用测试方法的实例。 对于已经具有静态工厂方法例如“1/0”的Point类convert方法非常简单 Override
public Object convert(Object input, ParameterContext parameterContext)throws ArgumentConversionException {if (input instanceof Point)return input;if (input instanceof String)try {return Point.from((String) input);} catch (NumberFormatException ex) {String message input is no correct string representation of a point.;throw new ArgumentConversionException(message, ex);}throw new ArgumentConversionException(input is no valid point);
} Point的第一个检查输入实例有点麻木为什么它已经是一个点了但是一旦我开始打开类型就无法让自己忽略这种情况。 随时判断我。 现在您可以使用ConvertWith应用转换器 ParameterizedTest
ValueSource(strings { (0/0), (0/1),(1/1) })
void convertPoint(ConvertWith(PointConverter.class) Point point) { } 或者您可以创建一个自定义批注以使其看起来不那么技术 ParameterizedTest
ValueSource(strings { (0/0), (0/1),(1/1) })
void convertPoint(ConvertPoint Point point) { }Target({ ElementType.ANNOTATION_TYPE, ElementType.PARAMETER })
Retention(RetentionPolicy.RUNTIME)
ConvertWith(PointConverter.class)
interface ConvertPoint { } 这意味着通过使用ConvertWith或自定义注释对参数进行注释JUnit Jupiter将传递提供给转换器的源的任何参数。 通常您会将其应用于发出字符串的ValueSource或CsvSource之类的源以便随后将其解析为您选择的对象。 反射 那是一个很大的旅程所以让我们确保我们拥有一切 我们首先添加了junit-jupiter-params工件然后将ParameterizedTest应用于带有参数的测试方法。 在研究了如何命名参数化测试之后我们开始讨论参数的来源。 第一步是使用 ValueSource MethodSource或CsvSource之类的源来为该方法创建参数组。 每个组都必须具有所有参数的参数参数解析器中的参数除外并且每个组将调用该方法一次。 可以实现自定义源并将其与ArgumentsSource一起应用。 由于源通常仅限于几种基本类型因此第二步是将它们转换为任意类型。 默认转换器对原语枚举和某些日期/时间类型执行此操作。 定制转换器可以与ConvertWith一起应用。 这使您可以轻松地使用JUnit Jupiter参数化您的测试 但是这种特定机制很可能无法满足您的所有需求。 在这种情况下您会很高兴听到它是通过扩展点实现的可用于创建您自己的参数化测试的变体–我将在以后的文章中进行研究敬请期待。 翻译自: https://www.javacodegeeks.com/2017/06/junit-5-parameterized-tests.html