使用 Selenium 和 Chrome 开发工具的浏览器内存泄漏自动化

Posted

技术标签:

【中文标题】使用 Selenium 和 Chrome 开发工具的浏览器内存泄漏自动化【英文标题】:Browser memory leak automation using Selenium and Chrome Dev Tools 【发布时间】:2019-07-09 16:05:20 【问题描述】:

我们已有使用 selenium-chrome-driver 用 Ja​​va 编写的 Web 测试用例。 现在我们要在执行这些测试后检查浏览器内存泄漏。

手动,我使用 Chrome 开发工具 - 内存选项卡来完成。进行堆转储,在我开始测试之前,执行测试,然后再次进行堆转储。比较这两个提供堆增量的堆转储。

我找不到 selenium-chrome-dev-tools API,我可以使用它启动 Chrome Dev Tool 内存分析器(可能还有其他一些工具),运行我的 WebDriver 测试(实例化 Chrome 浏览器实例,操作 DOM 元素等),然后停止分析器,然后检查分析器的结果以查看是否有任何内存泄漏。

这个概念是否可行,或者我可以出去吃午饭了吗?为什么/为什么不?

另一方面,我遇到了 https://github.com/samccone/drool 使用 which,我可以获得此信息,但问题是我将不得不用 javascript 重写所有现有的 java selenium 测试,除非我可以集成 drool与现有的硒测试。

请提出建议。

注意:Chrome Dev Tools API & Selenium WebDriver 下已经提出了类似的问题,但我还没有看到太多有用的答案,所以再次发布更多详细信息。

【问题讨论】:

您的内存泄漏测试是针对较小规模的应用程序用户负载还是较大规模的应用程序用户负载?我习惯于使用 Jmeter 和 Gatling 等负载和性能测试工具来测试内存泄漏。根据您监控的性能计数器,生成的报告可以告诉您更多关于内存泄漏的信息。 要求我们推荐或查找书籍、工具、软件库、教程或其他场外资源的问题对于 Stack Overflow 来说是无关紧要的,因为它们往往会吸引固执己见的答案和垃圾邮件。相反,describe the problem 以及迄今为止为解决它所做的工作。 这听起来像是 X-Y 问题。 【参考方案1】:

由于 drool 是开源的,你可以在 https://github.com/samccone/drool/blob/master/lib/index.js 看到他们的实现,并在 Java 中做类似的事情:

    ChromeOptions options = new ChromeOptions();

    // Enable performance logging
    LoggingPreferences logPrefs = new LoggingPreferences();
    logPrefs.enable(LogType.PERFORMANCE, Level.ALL);
    options.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);

    // Enable timeline tracing
    Map<String, Object> chromeOptions = new HashMap<>();
    Map<String, String> perfLoggingPrefs = new HashMap<>();
    perfLoggingPrefs.put(
        "traceCategories", "v8,blink.console,disabled-by-default-devtools.timeline");
    chromeOptions.put("perfLoggingPrefs", perfLoggingPrefs);
    options.setCapability(ChromeOptions.CAPABILITY, chromeOptions);

    WebDriver driver = new ChromeDriver(options);

...

    LogEntries performanceLogsBefore = driver.manage().logs().get("performance");

...

    LogEntries performanceLogsAfter = driver.manage().logs().get("performance");


然后过滤“V8.GCScavenger”、“V8.GCIncrementalMarking”、“MajorGC”和“MinorGC”条目的性能日志。

【讨论】:

感谢 Jens 的建议,我找到了一些更简单的方法,我将在此处发布作为答案。【参考方案2】:

Selenium 支持org.openqa.selenium.JavascriptExecutor。在测试的任何阶段,我们都可以得到window.performance.memory.usedJSHeapSize的值。下面是代码。

  public static void reportMemoryUsage(WebDriver webDriver, String message) 
    ((JavascriptExecutor) webDriver).executeScript("window.gc()");
    try 
        TimeUnit.SECONDS.sleep(2);
     catch (InterruptedException e) 
        LOGGER.error(e.getLocalizedMessage());
    
    Double usedJSHeapSize = (Double) ((JavascriptExecutor) webDriver)
            .executeScript("return window.performance.memory.usedJSHeapSize/1024/1024");
    LOGGER.info("Memory Usage at " + message + " - " + usedJSHeapSize + " MB ");
 

从您的测试套件中调用此方法,一个在测试开始时调用,一个在测试结束时调用。 两个 usedJSHeapSize 值之间的差异会导致内存泄漏。

我在使用 usedJSHeapSize 之前强制进行垃圾收集,以确保没有收集到垃圾信息。要在窗口上启用 gc 功能,您必须设置 -js-flags=--expose-gc 选项。

ChromeOptions options = new ChromeOptions();
options.addArguments("-js-flags=--expose-gc");
WebDriver webDriver = new ChromeDriver(options);

【讨论】:

这行得通,在我的情况下确实降低了内存利用率! 我很高兴听到这个消息 我现在可以报告堆大小了。但是对于 chrome 92 和 selenium 3.141.59,我似乎无法强制进行垃圾收集。如上所述,我添加了 chrome 选项参数来公开垃圾收集,并使用建议的 javascript ((JavascriptExecutor) webDriver).executeScript("window.gc()"); 调用它。但堆大小似乎一直在增长。还有什么建议吗?

以上是关于使用 Selenium 和 Chrome 开发工具的浏览器内存泄漏自动化的主要内容,如果未能解决你的问题,请参考以下文章

Golang使用selenium操作Chrome

长时间 Selenium 执行后 Chrome 关闭

如何在 Python 中使用 Selenium 打开 chrome 开发者控制台?

使用 Selenium Webdriver 控制 Chrome Devtools

在 URL 中嵌入凭据不适用于 selenium 和 chrome

自动化测试selenium+python+chrome 连接测试