Search code examples
rplotlytestthat

Test Plotly objects equality using testthat


Using testthat, I want to check if two plotly objects are the same.

Reproducible data:

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

I am searching for a code equivalent to testthat::expect_equivalent in priority (should be similar for testthat::expect_equal and testthat::expect_identical functions.

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

I have found a way to test for equality of the mismatch component.

I overwrite components that are equal (visdat here) and have random ids in the plotly object, then test for equality.

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)

Testthat code of plotly package does not help https://rdrr.io/cran/plotly/src/tests/testthat/test-plotly.R

Is there a more straightforward way to check if two plotly objects are equivalent?

Thanks a lot for any help


Solution

  • I find it hard to keep up with what is current and what is deprecated in testthat, but I believe currently testthat::expect_equal will call waldo::compare to compare the two objects.

    The waldo::compare function will make use of a compare_proxy method on the object to remove unimportant differences before making the comparison. So what you need to do is to find or write a compare_proxy.plotly method. It only sees one object at a time, so you can't transfer names from one to the other, but you can put in standard names or remove the names completely.

    For example, the proxy below works on your example. A more extensive example might need other modifications:

    library(waldo)
    library(plotly)
    #> Loading required package: ggplot2
    #> 
    #> Attaching package: 'plotly'
    #> The following object is masked from 'package:ggplot2':
    #> 
    #>     last_plot
    #> The following object is masked from 'package:stats':
    #> 
    #>     filter
    #> The following object is masked from 'package:graphics':
    #> 
    #>     layout
    
    p1 <- plot_ly(economics, x = ~pop)
    p2 <- plot_ly(economics, x = ~pop)
    
    compare_proxy.plotly <- function(x, path = "x") {
      names(x$x$visdat) <- "proxy"
      e <- environment(x$x$visdat$proxy)
      
      # Maybe we should follow the recursion, but not now.
      e$p <- NULL
      
      e$id <- "proxy"
      
      x$x$cur_data <- "proxy"
      names(x$x$attrs) <- "proxy"
      
      list(object = x, path = paste0("compare_proxy(", path, ")"))
    }
    
    waldo::compare(p1, p2)
    #> ✔ No differences
    
    testthat::local_edition(3)
    testthat::expect_equal(p1, p2)
    
    # Use a different but identical dataset
    
    economics2 <- economics
    p3 <- plot_ly(economics2, x = ~pop)
    testthat::expect_equal(p1, p3)
    
    # Use a slightly different dataset
    
    economics2$pce[1] <- 0
    p4 <- plot_ly(economics2, x = ~pop)
    
    testthat::expect_equal(p1, p4)
    #> Error: `p1` (`actual`) not equal to `p4` (`expected`).
    #> 
    #> environment(compare_proxy(actual)$x$visdat$proxy)$data vs environment(compare_proxy(expected)$x$visdat$proxy)$data
    #>                                                                       pce
    #> - environment(compare_proxy(actual)$x$visdat$proxy)$data[1, ]       506.7
    #> + environment(compare_proxy(expected)$x$visdat$proxy)$data[1, ]       0.0
    #>   environment(compare_proxy(actual)$x$visdat$proxy)$data[2, ]       509.8
    #>   environment(compare_proxy(actual)$x$visdat$proxy)$data[3, ]       515.6
    #>   environment(compare_proxy(actual)$x$visdat$proxy)$data[4, ]       512.2
    #> 
    #> environment(compare_proxy(actual)$x$visdat$proxy)$data$pce[1:4] vs environment(compare_proxy(expected)$x$visdat$proxy)$data$pce[1:4]
    #> - 507
    #> + 0
    #>   510
    #>   516
    #>   512
    #> 
    #> environment(compare_proxy(actual)$x$visdat$proxy)$plotlyVisDat vs environment(compare_proxy(expected)$x$visdat$proxy)$plotlyVisDat
    #>                                                                               pce
    #> - environment(compare_proxy(actual)$x$visdat$proxy)$plotlyVisDat[1, ]       506.7
    #> + environment(compare_proxy(expected)$x$visdat$proxy)$plotlyVisDat[1, ]       0.0
    #>   environment(compare_proxy(actual)$x$visdat$proxy)$plotlyVisDat[2, ]       509.8
    #>   environment(compare_proxy(actual)$x$visdat$proxy)$plotlyVisDat[3, ]       515.6
    #>   environment(compare_proxy(actual)$x$visdat$proxy)$plotlyVisDat[4, ]       512.2
    #> 
    #> environment(compare_proxy(actual)$x$visdat$proxy)$plotlyVisDat$pce[1:4] vs environment(compare_proxy(expected)$x$visdat$proxy)$plotlyVisDat$pce[1:4]
    #> - 507
    #> + 0
    #>   510
    #>   516
    #>   512
    

    Created on 2023-01-25 with reprex v2.0.2