测试模块化R Shiny (golem) 仪表板

3

我一直在探索和喜爱使用golem包来开发模块化的R Shiny仪表盘。但是我不知道如何测试模块化的仪表盘。

例如,在下面的repex中,如果将输入模块中的input$n_rows设置为15,那么如何测试显示模块的输出是否包含15行?

非常感谢您提供的任何支持!


library(shiny)
library(reactable)
library(dplyr)

# Import module UI
mod_import_ui <- function(id){
  
  ns <- NS(id)
  
  fluidRow(
    # Allow the user to select the number of rows to view
    numericInput(ns("n_rows"), 
                 "Select number of observations",
                 value = 10)
    
  )
}

# Import module Server
mod_import_server <- function(id){
  
  moduleServer(
    id,
    function(input, output, session){
      
      data <- reactive({
        
        # Sample the requested number of rows from mtcars and return this to the application server
        mtcars %>%
          slice_sample(n = input$n_rows)
        # [....] # Some complex formatting and transformations
        
      })
      
      return(data)
      
      
      
    }
  )}

# Display module UI
mod_display_ui <- function(id){
  
  ns <- NS(id)
  
  fluidRow(
    
    reactableOutput(ns("table"))
    
  )
}

# Display module Server
mod_display_server <- function(id, data_in){
  
  moduleServer(
    id,
    function(input, output, session){
      
      # [....] # Some more transformations and merging with data from other modules
      
      output$table <- renderReactable(reactable(data_in()))
      
    }
  )}


app_ui <- function(request) { 
  
  tagList(
  
    mod_import_ui("import_1"),
    mod_display_ui("display_1")

  )
  
  }


app_server <- function(input, output, session) { 
  
  data_in <- mod_import_server("import_1")
  mod_display_server("display_1", data_in)
  
}

shinyApp(ui = app_ui, server = app_server)


2个回答

5
我建议将应用程序的核心与用户界面分离。
{golem}框架允许在R包内构建应用程序,这意味着您可以使用从软件包构建到文档和测试代码的所有工具。 如果您按照我们在engineering-shiny.org/中的指南操作,您将看到我们建议将所有R代码从“服务器”部分提取出来,在vignette中进行测试,并将其转换为常规函数,以便您可以像使用R包一样进行测试。 因此,您的ShinyApp仅调用已记录和测试过的内部函数。采用这种方法,您可以测试应用程序中可能发生的不同情况的输出。在静态脚本中尝试不同的输入参数并验证输出,无论您在开发的下一步中更改了什么。 该书提供了很多建议。如果我必须总结它们以进行工作流程,则会是:
  1. 直接在Rmd中构建必要的代码。这样可以测试操作而无需进行所有必要的点击。我们称之为“先Rmd”方法:https://rtask.thinkr.fr/when-development-starts-with-documentation/
  2. 将此代码分解为R函数,尽可能少地放入Shiny应用程序本身。
  3. 创建您的UI部分,没有服务器(或不太多),只是为了看到一般外观
  4. 在应用程序的适当位置包含您的函数。
  5. 加强代码。可再现的示例、单元测试、文档、代码版本控制等(最好与代码同时完成)

谢谢您!我有点不确定如何在函数中包含反应性或反应性值(以在R Shiny会话之外运行)。但我想您可以将输入包装在函数中(对于反应性)或构建列表(对于反应性值)。再次感谢!#使用反应性 `trim_data <- function(data, num) { data() %>% slice_sample(n = num)}get_mt <- function(){mtcars}trim_data(get_mt, 12)``#使用反应性值 trim_data2 <- function(r, num) { r$data %>% slice_sample(n = num) }r <- list(data = mtcars)trim_data2(r, 12)` - David

4
作为 Sebastien 回答的补充,我想指出从 {shiny} v 1.5.0 开始,您可以使用 testServer 函数直接测试服务器函数,这可能是您正在寻找的内容。
以下是如何实现的示例:
library(shiny)
library(magrittr)
library(dplyr)

mod_import_server <- function(id){
  moduleServer( id, function(input, output, session){
    data <- reactive({
      mtcars %>%
        slice(n = 1:input$n_rows)
    })
    return(data)
  })
}

shiny::testServer(mod_import_server, {
  
  for (i in 1:10){
    
    session$setInputs(n_rows = i)
    testthat::expect_equal(
      data(), 
      slice(mtcars, n = 1:i)
    )
    
  }
})

在这里,你可以测试你的 reactive() 是否按照你的预期工作。

虽然这还不是完美的,但已经是一个不错的开始 :)

很难找到一种测试第二个模块行为的方法,因为它取决于作为值传递的 reactive()

Colin


谢谢 Colin!那真的很有帮助。 - David

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接