You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用testthat测试两个plotly对象是否等价?

如何用testthat简便验证两个plotly对象等价

问题场景

我想用testthat检查两个plotly对象是否等价,测试代码如下:

library(plotly)
p1 <- plot_ly(economics, x = ~pop)
p2 <- plot_ly(economics, x = ~pop)

当调用testthat::expect_equivalent(p1, p2)时,出现以下报错:

Error: p1 not equivalent to p2.
Component “x”: Component “visdat”: Component 1: Component “id”: 1 string mismatch
Component “x”: Component “visdat”: Component 1: Component “p”: Component “cur_data”: 1 string mismatch
Component “x”: Component “cur_data”: 1 string mismatch

我自己实现了一种 workaround:先验证核心组件的一致性,再覆盖掉含随机ID的字段后再做等价性检查:

testthat::expect_equal(
  object = p2$x$visdat[[1]](),
  expected = p1$x$visdat[[1]]()
)

p2$x$visdat[1] <- p1$x$visdat[1]
names(p2$x$visdat) <- names(p1$x$visdat)
    
p2$x$cur_data <- p1$x$cur_data
testthat::expect_equivalent(p1, p2)

但这个方法比较繁琐,想知道有没有更简便的方式。

简便解决方案

方案1:转换为JSON后对比

plotly提供的toJSON()函数会将对象序列化为仅包含图表核心配置和数据的JSON字符串,自动忽略内部生成的随机ID、cur_data这类非核心字段,直接对比JSON即可验证等价性:

library(testthat)
library(plotly)

p1 <- plot_ly(economics, x = ~pop)
p2 <- plot_ly(economics, x = ~pop)

expect_equal(toJSON(p1), toJSON(p2))

方案2:自定义testthat期望函数

如果需要更灵活的字段控制,可以编写一个专门处理plotly对象的自定义期望函数,自动清理掉随机生成的无关字段后再做对比:

library(testthat)
library(plotly)

expect_plotly_equal <- function(object, expected, ...) {
  # 清理plotly对象中的随机标识字段
  clean_plotly <- function(p) {
    # 清理visdat中的随机id和cur_data
    if (!is.null(p$x$visdat)) {
      p$x$visdat <- lapply(p$x$visdat, function(vis) {
        vis$id <- NULL
        if (!is.null(vis$p)) vis$p$cur_data <- NULL
        vis
      })
    }
    # 清理顶层的cur_data
    p$x$cur_data <- NULL
    p
  }
  # 对比清理后的对象
  expect_equal(clean_plotly(object), clean_plotly(expected), ...)
}

# 使用示例
p1 <- plot_ly(economics, x = ~pop)
p2 <- plot_ly(economics, x = ~pop)
expect_plotly_equal(p1, p2)

报错原因

每次创建plotly对象时,内部会自动生成随机的id和cur_data字段,这些是plotly用于内部状态跟踪的标识,不属于图表的核心配置或数据内容,因此直接使用expect_equivalent这类严格对比函数会因这些随机值不匹配而报错。

内容的提问来源于stack exchange,提问作者Clemsang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 10:15:33