Run a Shiny app without HTTP server?

For testing a Shiny app, I'd like to run the server() function without actually spawning an HTTP server:

library(shiny)

input <- reactiveValues()
output <- reactiveValues()
session <- shiny:::ShinySession$new(...)

server(input, output, session)

input$control1 <- "some value"
while (...) shiny:::serviceApp()
stopifnot(output$... == "...")

My plan is to set input values and check output values. This looks like an easier approach to testing than shinytest or Selenium. Seems like I "only" need to fill in the ... .

Is this approach feasible at all, or would it involve major changes to shiny internals? I'd appreciate any pointers.

I'm not sure it's a good idea, but you can do something like this using shiny:::flushReact() and isolate:

library(shiny)

server <- function(input, output, session) {
  output$sum <- renderText(
    input$x + input$y
  )
}

input <- reactiveValues()
output <- reactiveValues()

input$x <- 1
input$y <- 2

server(input, output)

shiny:::flushReact()

cat(isolate(output$sum())) # Prints 3

input$y <- 3
shiny:::flushReact()

cat(isolate(output$sum())) # Prints 4

Thanks. This does look promising. I need to see how useful this is for actually testing a Shiny app.

What's the best way to mock a ShinySession object (I'm using update...() functions in my server())?

I don't know off-hand the best way to mock the ShinySession object, but I'd look in Shiny to find out. I ran the approach by Joe and he had the following thoughts in Slack:

This almost works. In order to handle the outputs correctly, you potentially need a little more than that.
Some of the output functions (i.e. output$sum(…)) expect additional parameters, like the output name and the session
Some of the outputs like plot outputs expect some other implicit inputs, like width/height/visibility
So to do this right, you really want more official scaffolding. We had a work item to do this for the longest time, but it never made it to the top.
The output also shouldn’t be a list like that, but rather something that creates an observer each time something is assigned to it.
Basically there’s at least a couple of weeks of work to do this right. But yeah, very worthwhile idea.

1 Like

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.