我未能实现 ArchUnit 测试,该测试旨在防止编写以“失败”工作作为其方法名称的一部分来命名的测试用例。
为此,我使用
ImportOption.OnlyIncludeTests.class
导入选项,使用测试用例注释之一检查所有方法注释,以便我最终可以检查名称是否与模式匹配:
@RunWith(ArchUnitRunner.class)
@AnalyzeClasses(packages = "com.example", importOptions = {
ImportOption.OnlyIncludeTests.class,
ImportOption.DoNotIncludePackageInfos.class,
ImportOption.DoNotIncludeArchives.class
})
public class TestConventionsTest {
@ArchTest
private final ArchRule noTestCaseMethodsWithANameUsingUndesiredWordFailed
= Conventions.DO_NOT_USE_THE_UNDESIRED_WORD_FAILED_IN_TEST_METHOD_NAMES;
}
约定是这样实现的:
public class Conventions {
/**
* Test methods named with the word "failed" in their names make it harder to spot actually failed
* tests in the test run output of pipeline runs. Use phrases like "not successful" or "failing" instead.
*/
public static final ArchRule DO_NOT_USE_THE_UNDESIRED_WORD_FAILED_IN_TEST_METHOD_NAMES =
noMethods()
.that().areAnnotatedWith(org.junit.Test.class)
.or().areAnnotatedWith(org.junit.jupiter.api.Test.class)
.or().areAnnotatedWith(org.junit.jupiter.params.ParameterizedTest.class)
.or().areAnnotatedWith(com.tngtech.archunit.junit.ArchTest.class)
.should().haveNameMatching("/failed/i");
}
运行时的结果是:
java.lang.AssertionError:规则“没有用@Test注释或用@Test注释或用@ParameterizedTest注释或用@ArchTest注释的方法应该具有与'/failed/i'匹配的名称”未能检查任何类。这意味着要么根本没有类传递到规则,要么没有传递到规则的类与
子句匹配。要允许在不检查任何类的情况下评估规则,您可以在单个规则上使用that()
或设置配置属性ArchRule.allowEmptyShould(true)
以全局更改行为。archRule.failOnEmptyShould = false
在我看来,好像没有任何类实际上被输入到测试用例中。我试图通过暂时消除谓词来排除未找到谓词匹配的可能性,但这不会改变任何事情。我未能在我的设置中发现任何可能排除测试类被检查的内容。
我的问题是:为什么没有将测试类输入到测试中,因此找不到命中?
看起来我现在得到了(部分)解决方案,尽管我仍然有兴趣了解为什么我的第一种方法没有成功......
这似乎按预期工作:
@RunWith(ArchUnitRunner.class) @AnalyzeClasses(packages = "com.example")
public class TestConventionsTest {
public static void main(String[] args) {
JavaClasses classes = new ClassFileImporter().importPackages("com.example");
noTestCaseMethodsWithANameUsingUndesiredWordFailed.check(classes);
}
@ArchTest
private static final ArchRule noTestCaseMethodsWithANameUsingUndesiredWordFailed
= Conventions.DO_NOT_USE_THE_UNDESIRED_WORD_FAILED_IN_TEST_METHOD_NAMES;
}
这里是约定:
public static final ArchRule DO_NOT_USE_THE_UNDESIRED_WORD_FAILED_IN_TEST_METHOD_NAMES =
methods()
.that().areAnnotatedWith(org.junit.Test.class)
.or().areAnnotatedWith(org.junit.jupiter.api.Test.class)
.or().areAnnotatedWith(org.junit.jupiter.params.ParameterizedTest.class)
.or().areAnnotatedWith(com.tngtech.archunit.junit.ArchTest.class)
.should(new ArchCondition<>("not have the undesired word 'failed' in their name") {
@Override
public void check(JavaMethod method, ConditionEvents events) {
if (method.getName().toLowerCase().contains("failed")) {
String message = String.format("Method %s in class %s contains 'failed' in its name",
method.getName(), method.getOwner().getName());
events.add(SimpleConditionEvent.violated(method, message));
}
}
});