还发现有好帖: JUnit 5 简介,第 1 部分
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);
}
启动分为如下几步:
- 构造LauncherDiscoveryRequest指定测试类的查找和过滤规则
2. 通过 LauncherFactory.create() 来获取Launcher默认实现
-
通过添加TestExecutionListener来进行测试结果的监听
-
执行launcher.execute(req)方法启动测试
简单来说就是扫描注定的文件夹或找到指定类名的类,经过Filter过滤后交给TestEngine去执行 启动过程中涉及的类 DiscoverySelector 负责定义哪些资源可以被TestEngine用来寻找测试类,比如指定java类名或者指定目录路径
Filter 作为TestEngine的过滤器,过滤DiscoverySelector发现的资源 LauncherDiscoveryRequest 使用不同的Filter定义了Launcher和TestEngine以及测试类的过滤规则,使用DiscoverySelector发现测试类 TestEngine 作为发现和执行符合LauncherDiscoveryRequest规则的测试的主要组件,对不同的编程模型可以实现自己的TestEngine,比如JupiterTestEngine
TestEngine在创建Launcher的时候通过JAVA SPI发现具体实现,JUnit5中有两种实现 :JupiterTestEngine 和 VintageTestEngine
TestExecutionListener 定义了测试执行期间发生的事件类型,注册到Launcher的实现类将会在事件发生时得到通知
DefaultLauncher 做为Launcher的默认实现,持有TestEngine和TestExecutionListener集合,它们通过JAVA SPI发现,负责执行TestEngine来启动测试
各步骤详解
- 构造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);
-
执行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构造和启动流程图
———————————————— 版权声明:本文为CSDN博主「Oo此岸花开oO」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/hqq2023623/article/details/78464877
来源:oschina
链接:https://my.oschina.net/u/2963604/blog/3166978