当前位置: 首页 > 知识库问答 >
问题:

使用cucumber junit平台引擎和Selenium WebDriver运行测试会打开太多线程

潘安平
2023-03-14

我曾尝试配置一个现有的Maven项目,以使用cucumber junit平台引擎运行。

我用这份回购协议作为灵感。

我添加了所需的Maven依赖项,就像使用spring boot starter父版本2.4.5和cucumber jvm版本6.10.4的链接项目一样。

我设置junit-Platform属性如下:

cucumber.execution.parallel.enabled=true
cucumber.execution.parallel.config.strategy=fixed
cucumber.execution.parallel.config.fixed.parallelism=4

在runner类中使用注释@Cucumber,在带有步骤定义的类中使用注释@springbootest

我正在使用一个CucumberHooks类在场景前后添加逻辑,我猜它会干扰运行程序,因为我正在使用注释:

import java.util.List;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.Scenario;
import io.cucumber.plugin.ConcurrentEventListener;
import io.cucumber.plugin.event.EventHandler;
import io.cucumber.plugin.event.EventPublisher;
import io.cucumber.plugin.event.TestRunFinished;
import io.cucumber.plugin.event.TestRunStarted;
import io.github.bonigarcia.wdm.WebDriverManager;

public class CucumberHooks implements ConcurrentEventListener {

@Autowired
private ScenarioContext scenarioContext;

@Before
public void beforeScenario(Scenario scenario) {
    scenarioContext.getNewDriverInstance();
    scenarioContext.setScenario(scenario);
    LOGGER.info("Driver initialized for scenario - {}", scenario.getName());
    ....
    <some business logic here>
    ....
}

@After
public void afterScenario() {
    Scenario scenario = scenarioContext.getScenario();
    WebDriver driver = scenarioContext.getDriver();

    takeErrorScreenshot(scenario, driver);
    LOGGER.info("Driver will close for scenario - {}", scenario.getName());

    driver.quit();
}

private void takeErrorScreenshot(Scenario scenario, WebDriver driver) {
    if (scenario.isFailed()) {
        final byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
        scenario.attach(screenshot, "image/png", "Failure");
    }
}

@Override
public void setEventPublisher(EventPublisher eventPublisher) {
    eventPublisher.registerHandlerFor(TestRunStarted.class, beforeAll);
}

private EventHandler<TestRunStarted> beforeAll = event -> {
    // something that needs doing before everything
    .....<some business logic here>....
    WebDriverManager.getInstance(DriverManagerType.CHROME).setup();
};

}

我试着从io中替换@Before标签。cucumberjava@beforeach来自组织。朱尼特。木星api,它不起作用。

我该如何解决这个问题?

共有1个答案

空正豪
2023-03-14

所以事实证明,parallism主要是一个建议。Cucumber使用JUnit5sForkJoinPool HierarchycalTestExecutorService,它构建了一个ForkJoinPool

ForkJoinpool上的文档:

对于需要单独或自定义池的应用程序,可以使用给定的目标并行级别构造ForkJoinPool;默认情况下,等于可用处理器的数量。池试图通过动态添加、挂起或恢复内部工作线程来维护足够的活动(或可用)线程,即使某些任务在等待加入其他任务时被暂停。然而,面对阻塞的I/O或其他非托管同步,不保证进行此类调整。

所以在一个ForkJoinpool内,当曾经有一个线程阻塞时,例如因为它开始与web驱动程序异步通信,另一个线程可以被启动以保持并行性。

由于所有线程都等待,因此会向池中添加更多线程,并启动更多web驱动程序。

这意味着你需要依靠ForkJoinpool来限制你必须自己完成的网络驱动程序的数量。你可以使用像ApacheCommons pool这样的库,或者使用计数信号量来实现一个基本的池。

@Component
@ScenarioScope
public class ScenarioContext {

    private static final int MAX_CONCURRENT_WEB_DRIVERS = 1;
    private static final Semaphore semaphore = new Semaphore(MAX_CONCURRENT_WEB_DRIVERS, true);

    private WebDriver driver;

    public WebDriver getDriver() {
        if (driver != null) {
            return driver;
        }

        try {
            semaphore.acquire();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        try {
            driver = CustomChromeDriver.getInstance();
        } catch (Throwable t){
            semaphore.release();
            throw t;
        }
        return driver;
    }

    public void retireDriver() {
        if (driver == null) {
            return;
        }

        try {
            driver.quit();
        } finally {
            driver = null;
            semaphore.release();
        }
    }
}    

 类似资料:
  • 有没有任何一个测试REST API的使用硒网络驱动程序Maven TestNG。请分享信息或样本项目

  • Apache ShardingSphere 提供了完善的测试引擎。 它以 XML 方式定义 SQL,每个引擎分别为 MySQL、PostgreSQL、SQLServer 和 Oracle 数据库运行测试用例。 为了方便上手,测试引擎无需修改任何 Java 代码,只需修改相应的配置文件即可运行断言。

  • 我创建了maven项目,它由junit和spock测试组成。两个测试的代码。 在我的本地机器中,当我运行mvn测试时,它会欺骗两个测试类。我在git仓库上部署了项目,并为maven项目配置了jenkins。我推这个项目的存储库和执行作业,但是詹金斯只检测JUnit测试的AppTest类。我已经改变了pom.xml并添加了文件regadring到。我的项目结构。 文件组织的内容。spockframe

  • 我创建了一个多线程步骤,最大线程限制为10; 在处理了200万条记录文件后,我可以在日志文件中看到创建的线程太多,即使我将限制设置为10个线程。你能告诉我为什么吗?非常感谢。 2019-07-02T17:02:298968129857信息[batch-thread35348]com。db。wmdl。价格档案。工作一批听众。PriceFileReaderListener([])-PriceFileR

  • 多平台开发 一个网站或应用不仅能运行在各种台式机, 笔记本电脑, 平板和手机, 还能运行于少部分其它设备(手表, 温控器, 电冰箱等等). 你将怎么决定支持哪些平台和为支持这些平台, 怎么去开发, 这被称为多平台开发策略. 接下来, 我会列出常见的多平台开发策略: 创建 响应式 Web 设计 (RWD) 网站/APP 创建 RESS (基于服务端组件的响应式 Web 设计) 网站/APP 创建 自

  • 我有一个带有静态ConcurrentQueue的类。一个类接收消息并将其放入队列中,而这个类上的另一个线程从该队列中读取消息并一次处理一个。使用cancellationtoken中止该方法。 清空队列的方法如下所示: 我的测试方法如下: 因此,我在自己的线程中启动我的出列方法,并使用一个新的取消令牌。然后我将一些消息排队,给进程一秒钟时间来处理它们,然后使用源代码。Cancel(false)结束线