概述
Launcher概述
Launcher是JUnit5的启动类,也是对启动进行扩展的主要入口,扩展通过实现自定义的TestEngine来自定义测试类的发现和执行逻辑以达到定制化测试的目的
Launcher启动示例代码
public static void main(String[] args) {
//设置搜索和过滤规则
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(
selectPackage("zj"),
selectClass(*MyTest.class)
)
.filters(
includeClassNamePatterns(".*Tests")
)
.build();
Launcher launcher = LauncherFactory.create();
// Register a listener of your choice
//通过监听器来监听获取执行结果
TestExecutionListener listener = new SummaryGeneratingListener();
launcher.registerTestExecutionListeners(listener);
launcher.execute(request);
}
启动分为如下几步:
1. 构造LauncherDiscoveryRequest指定测试类的查找和过滤规则
简单来说就是扫描注定的文件夹或找到指定类名的类,经过Filter过滤后交给TestEngine去执行2. 通过 LauncherFactory.create() 来获取Launcher默认实现
3. 通过添加TestExecutionListener来进行测试结果的监听
4. 执行launcher.execute(req)方法启动测试
启动过程中涉及的类
DiscoverySelector
负责定义哪些资源可以被TestEngine用来寻找测试类,比如指定java类名或者指定目录路径
Filter
LauncherDiscoveryRequest
TestEngine
作为发现和执行符合LauncherDiscoveryRequest规则的测试的主要组件,对不同的编程模型可以实现自己的TestEngine,比如JupiterTestEngine
TestEngine在创建Launcher的时候通过JAVA SPI发现具体实现,JUnit5中有两种实现 :JupiterTestEngine 和 VintageTestEngine
TestExecutionListener
定义了测试执行期间发生的事件类型,注册到Launcher的实现类将会在事件发生时得到通知
DefaultLauncher
做为Launcher的默认实现,持有TestEngine和TestExecutionListener集合,它们通过JAVA SPI发现,负责执行TestEngine来启动测试
各步骤详解
1. 构造LauncherDiscoveryRequest指定测试类的查找和过滤规则
public LauncherDiscoveryRequest build() {
LauncherConfigurationParameters launcherConfigurationParameters = new LauncherConfigurationParameters(
this.configurationParameters);
return new DefaultDiscoveryRequest(this.selectors, this.engineFilters, this.discoveryFilters,
this.postDiscoveryFilters, launcherConfigurationParameters);
}
2.利用LauncherFactory创建DefaultLauncher
public static Launcher create() throws PreconditionViolationException {
Launcher launcher = new DefaultLauncher(new ServiceLoaderTestEngineRegistry().loadTestEngines());
for (TestExecutionListener listener : new ServiceLoaderTestExecutionListenerRegistry().loadListeners()) {
launcher.registerTestExecutionListeners(listener);
}
return launcher;
}
这里利用JAVA SPI来发现TestEngine和TestExecutionListener的实现集合,保存在Launcher中
3. 通过添加TestExecutionListener来进行测试结果的监听
TestExecutionListener listener = new SummaryGeneratingListener();
launcher.registerTestExecutionListeners(listener);
4. 执行launcher.execute(req)方法启动测试
public void execute(LauncherDiscoveryRequest discoveryRequest, TestExecutionListener... listeners) {
Preconditions.notNull(discoveryRequest, "LauncherDiscoveryRequest must not be null");
Preconditions.notNull(listeners, "TestExecutionListener array must not be null");
Preconditions.containsNoNullElements(listeners, "individual listeners must not be null");
execute(discoverRoot(discoveryRequest, "execution"), discoveryRequest.getConfigurationParameters(), listeners);
}
4.1 调用discoveryRoot()来执行TestEngine的过滤器,过滤的结果通过类Root返回,Root持有TestEngine的map集合
private Root discoverRoot(LauncherDiscoveryRequest discoveryRequest, String phase) {
Root root = new Root();
for (TestEngine testEngine : this.testEngines) {
// @formatter:off
boolean engineIsExcluded = discoveryRequest.getEngineFilters().stream()
.map(engineFilter -> engineFilter.apply(testEngine))
.anyMatch(FilterResult::excluded);
// @formatter:on
if (engineIsExcluded) {
logger.debug(() -> String.format(
"Test discovery for engine '%s' was skipped due to an EngineFilter in phase '%s'.",
testEngine.getId(), phase));
continue;
}
logger.debug(() -> String.format("Discovering tests during Launcher %s phase in engine '%s'.", phase,
testEngine.getId()));
Optional<TestDescriptor> engineRoot = discoverEngineRoot(testEngine, discoveryRequest);
engineRoot.ifPresent(rootDescriptor -> root.add(testEngine, rootDescriptor));
}
root.applyPostDiscoveryFilters(discoveryRequest);
root.prune();
return root;
}
4.2 继续调用execute(Root ...)
private void execute(Root root, ConfigurationParameters configurationParameters,
TestExecutionListener... listeners) {
TestExecutionListenerRegistry listenerRegistry = buildListenerRegistryForExecution(listeners);
TestPlan testPlan = TestPlan.from(root.getEngineDescriptors());
TestExecutionListener testExecutionListener = listenerRegistry.getCompositeTestExecutionListener();
testExecutionListener.testPlanExecutionStarted(testPlan);
ExecutionListenerAdapter engineExecutionListener = new ExecutionListenerAdapter(testPlan,
testExecutionListener);
for (TestEngine testEngine : root.getTestEngines()) {
TestDescriptor testDescriptor = root.getTestDescriptorFor(testEngine);
execute(testEngine, new ExecutionRequest(testDescriptor, engineExecutionListener, configurationParameters));
}
testExecutionListener.testPlanExecutionFinished(testPlan);
}
主要逻辑就是构造监听器、TestDescriptor和ExecutionRequest的构造以及TestEngine的执行
Launcher构造和启动流程图
最后
以上就是聪慧钻石为你收集整理的JUnit5的启动 - Launcher启动过程中涉及的类DiscoverySelectorFilterLauncherDiscoveryRequestTestEngineDefaultLauncher的全部内容,希望文章能够帮你解决JUnit5的启动 - Launcher启动过程中涉及的类DiscoverySelectorFilterLauncherDiscoveryRequestTestEngineDefaultLauncher所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复