如何用自动化框架对plotly.js图表做集成测试?Selenium遇DOM难题
嘿,我太懂你这种困扰了——用Selenium测Plotly.js的图表时,那些数据点根本不像普通DOM元素一样好找,毕竟Plotly是用SVG渲染的,很多数据都藏在JS实例里,不是直接暴露在DOM结构里。我来给你分享几个实用的方案,帮你搞定所有验证项:
Plotly.js会把每个图表的实例、数据、配置都存在全局环境里,与其费劲找DOM元素,不如直接通过Selenium执行JS代码来获取这些信息,这才是最高效的方式。
获取数据点数量和值:
每个图表实例都有data属性,里面存着所有轨迹的原始数据。比如针对你提到的折线散点图,你可以执行这段JS:// 获取页面上第一个Plotly图表实例(如果有多个,调整索引即可) const chartInstance = Plotly.d3.select('.plotly').node().__chart__; // 获取第一条轨迹的y轴数据(x轴数据用chartInstance.data[0].x) const traceYValues = chartInstance.data[0].y; // 数据点数量就是数组长度 const pointCount = traceYValues.length; // 返回结果给Selenium return { pointCount, traceYValues };在Java Selenium里,你可以用
JavascriptExecutor来执行这段代码,直接拿到数据,完全不用纠结DOM定位的问题。验证放大/缩小操作:
Plotly提供了relayout方法来修改图表布局,模拟放大缩小操作,之后还能直接读取当前的轴范围来验证:// 模拟放大x轴,把范围限定在[2, 8] Plotly.relayout('.plotly', { 'xaxis.range': [2, 8] }); // 获取当前x轴的范围,用于验证 const currentXRange = Plotly.d3.select('.plotly').node().__chart__.layout.xaxis.range; return currentXRange;
如果要验证数据点、图例的CSS样式,就得定位到SVG里的具体元素了,Plotly的SVG结构是有规律的:
数据点标记:
散点/折线图的标记一般是<circle>或<path>元素,属于对应轨迹的<g>标签,类名格式是trace trace-0(trace-0代表第一条轨迹)。你可以用XPath来定位:// 等待SVG加载完成 WebDriverWait wait = new WebDriverWait(driver, 10); wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector(".plotly svg"))); // 定位第一条轨迹的所有数据点circle元素 List<WebElement> dataPoints = driver.findElements(By.xpath("//g[contains(@class, 'trace-0')]//circle")); // 获取第一个数据点的填充颜色样式 String pointFillColor = dataPoints.get(0).getCssValue("fill");注意:如果是折线图且没显示标记,这些元素不会存在,需要确保图表配置里开启了标记显示。
图例元素:
每个图例条目都在<g class="legendgroup">标签里,里面的<path>是图例的标记,<text>是图例文本:// 定位第一个图例条目 WebElement legendItem = driver.findElement(By.xpath("//g[@class='legendgroup'][1]")); // 获取图例标记的填充样式 String legendMarkFill = legendItem.findElement(By.tagName("path")).getCssValue("fill"); // 获取图例文本内容 String legendText = legendItem.findElement(By.tagName("text")).getText();
如果需要更全面的测试(比如视觉回归验证),可以结合这些工具:
- Puppeteer:虽然是Node.js生态的,但比Selenium更灵活控制JS执行,对Plotly这类JS渲染的图表支持更好,如果你能接受跨语言的话可以试试。
- Applitools:专门做视觉测试的工具,能对比图表的像素级差异,适合验证放大缩小后的图表显示是否符合预期。
- 等待图表加载完成:Plotly是异步渲染的,一定要用
WebDriverWait等待图表初始化完成,比如检查Plotly实例是否存在:WebDriverWait wait = new WebDriverWait(driver, 10); wait.until(driver -> ((JavascriptExecutor) driver).executeScript( "return typeof Plotly !== 'undefined' && Plotly.d3.select('.plotly').node().__chart__ !== undefined;" )); - 动态元素重新定位:每次交互(比如放大)后,Plotly会重新渲染SVG元素,所以要重新定位元素,或者再次调用JS API获取最新数据。
内容的提问来源于stack exchange,提问作者neetigya goel

