rstudio / shinytest2

https://rstudio.github.io/shinytest2/
Other
100 stars 16 forks source link

Documentation: show example of how to test modules and the return value from a module #297

Open daattali opened 1 year ago

daattali commented 1 year ago

In the entire documentation I couldn't find any reference to shiny modules. It'd be great if there was an example showing how to teset them. I've run into a few issues, there's a good chance it's my fault so I won't open them as issues, but it would be useful in general to have an example.

schloerke commented 1 year ago

{shinytest2} is for whole-app testing. It does not provide any direct support for module testing.

I'd recommend looking into https://shiny.rstudio.com/articles/server-function-testing.html#testing-shiny-modules using the shiny:: testServer(mod, expr) function. However, this is for reactive testing only. This will not test the UI.

daattali commented 1 year ago

I do have some module testing with testServer(), but it is very basic. It's ok to not be able to test the UI, but worse than that because it cannot test update functions, it's very limited in how useful it can be.

For more rigorous testing I was hoping to use shinytest2. I understand there's no direct support for testing a module (although I'd argue that would be very useful in the future, since every real app is composed of many modules, and by nature a module should be isolated so it should be testable in isolation!). But I should be able to test a module by wrapping it in a proper shiny app, and I seem to have troubles with that as well. For example, here's an extremely simple module that I can't seem to get to work with shinytest2:

library(shiny)

my_mod_ui <- function(id) {
  ns <- NS(id)
  tagList(
    textInput(ns("text"), "text", "text"),
    textOutput(ns("up"))
  )
}

my_mod_server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$up <- renderText(toupper(input$text))
  })
}

ui <- fluidPage(
  my_mod_ui("foo")
)

server <- function(input, output, session) {
  my_mod_server("foo")
}

app <- shinyApp(ui, server)

This app works. Trying to call expect_values() on it results in an error:

driver <- shinytest2::AppDriver$new(app)
driver$expect_values()
Error in `app_expect_values()`:
! Shiny server returned 404 for values URL: http://127.0.0.1:3383/session/6cfc9f8cee8b21fcb17f085a029083ba/dataobj/shinytest?w=&nonce=a8eddebe3&input=1&output=1&export=1&format=json&sortC=1
ℹ Is `shiny::runApp(test.mode = TRUE)` enabled?
daattali commented 1 year ago

Looking into the error logs of the driver object, I see:

 could not find function "my_mod_server"

So the shiny server, when wrapped in AppDriver, cannot see the function defined in the globalenv

It looks like this might be a similar issue to #296 and #303

LDSamson commented 5 months ago

For anyone interested: I am using module testing with shinytest2 for shiny app in a package, using the Golem framework. It works after installing the package, as long as the module functions are exported.