(Acest articol a fost publicat pentru prima dată pe Blogul lui Ashleyși a contribuit cu drag la R-Bloggers). (Puteți raporta problema despre conținutul de pe această pagină aici)
Doriți să vă împărtășiți conținutul pe R-Bloggers? Faceți clic aici dacă aveți un blog sau aici dacă nu.
Am lucrat la un proiect în care nu am putut să folosim {shinytest2} și, prin urmare, am avut o dependență grea de testServer
Funcționați la testarea funcționalității reactive în fiecare dintre module. În timp ce este excelent pentru verificarea logicii din partea serverului, pe baza intrărilor manechinului sau a reactiveValues Fiind actualizat, un punct de frecare a fost când un observator va actualiza o intrare, iar această intrare ar declanșa un alt eveniment. Puteți actualiza manual intrarea în test după observator, dar poate provoca o oarecare discrepanță între ceea ce ordinea observatorilor într -un modul și ceea ce se întâmplă în test.
Aici intră {shinytesters}. Acest pachet își propune să batjocorească orice funcție de actualizare în pachetul de extensie {shiny} sau shiny și să actualizeze intrarea în testServer Când este chemat într -un observator. Acest lucru va permite ordinului de rulare al observatorilor în teste să se potrivească cu ceea ce s -ar întâmpla într -o sesiune strălucitoare live, plus evitând orice nevoie de actualizare manuală a valorilor de intrare.
Funcția principală disponibilă în {shinytesters} este use_shiny_testers. Această funcție utilizează
local_mocked_bindings Funcție în pachetul {testthat}. Funcțiile de batjocură în teste sunt deosebit de utile pentru testarea funcțiilor care apelează la funcții care se conectează la API -uri, pentru a evita dependența de o conexiune la internet atunci când rulează testele. Aici este deosebit de util, deoarece nu avem o UI pentru mesajele trimise din funcțiile de actualizare și dorim să creăm o modalitate de a face acest lucru la sesiunea strălucitoare.
Fiecare funcție dintr -un pachet care conține cuvântul „actualizare” se găsește în pachet și este creată o funcție batjocoritoare pentru a extrage noua intrare care urma să fie trimisă în UI. Acest lucru a fost facilitat prin utilizarea pachetului {rlang}, fiind capabil să extragă numele argumentelor funcției, valorile apelului și orice alte informații din jurul apelului cu funcționalitate ușor de utilizat. Această funcție poate fi pusă la începutul unui test_that Expresie pentru a adăuga o versiune batjocorită a tuturor funcțiilor de actualizare într -un pachet dat.
Mai jos este un exemplu despre modul în care este implementat:
library(testthat)
library(shiny)
library(shinytesters)
test_that("Selected date updates when button is triggered", {
use_shiny_testers()
example_server_fn <- function(input, output, session) {
observeEvent(input$trigger, {
updateDateInput(
inputId = "result",
label = "New Label",
value = as.Date("2000-01-01"),
min = as.Date("1999-12-31")
)
})
}
shiny::testServer(
app = example_server_fn,
expr = {
session$setInputs(result = as.Date("2025-01-02"))
session$setInputs(trigger = 1L)
expect_identical(input$result, as.Date("2000-01-01"))
expect_identical(input$result.min, as.Date("1999-12-31"))
expect_null(input$result.max)
}
)
})
Un lucru de remarcat este faptul că nu numai că puteți vedea că intrarea a fost actualizată, dar și alte valori sunt disponibile și la intrare. Într -o intrare de dată, puteți selecta data minimă și maximă pe care un utilizator A îl poate alege, dar nu există nicio modalitate de a -l urmări testServer. Cazuri similare se întâmplă la schimbarea opțiunilor într -o intrare selectată sau la actualizarea etichetei oricărei intrări date. Acestea sunt, de asemenea, disponibile în {shinytesters} prin adăugarea argumentului la sfârșitul ID -ului de intrare, separat de o perioadă. Deci, în exemplul de mai sus, data minimă este acum disponibilă în cadrul result.min. În funcții strălucitoare, când un argument este NULLatunci nu este actualizat, acest lucru se reflectă și în {shinytesters}, astfel încât puteți verifica când atributele unei intrări s -au actualizat fără actualizarea efectivă a intrării.
Când există mai multe pachete de extensie strălucitoare într -un singur modul, atunci va trebui să apelați
use_shiny_testers De mai multe ori, unul pentru fiecare pachet.
test_that("Testing complex shiny module", {
use_shiny_testers() # By default it mocks the shiny package update function
use_shiny_testers(.package = "shinyWidgets")
...
})
Au existat unele presupuneri făcute în jurul numelor de argumente care sunt utilizate în funcțiile de actualizare, pe baza pachetului strălucitor. Acest lucru nu este întotdeauna cazul pachetelor de extensie, astfel încât următoarele pot fi actualizate, astfel încât toate să funcționeze așa cum era de așteptat:
id_argPentru a specifica argumentul ID, de exemplu „INPUT_ID” din pachetul {shiny.semantic}value_argsPentru a specifica argumentele din care poate fi atribuită valoarea de intrare. Acest lucru este diferit chiar și în pachetul {shiny} în sine, unde valorile unice sunt „valoare”, în timp ce mai multe opțiuni, cum ar fi intrarea selectată, utilizează „selectat”range_value_argsPentru a specifica argumentele din care poate fi atribuită o valoare de intrare cu 2 lungimi. Se adaugă o logică suplimentară aici atunci când acestea există în apelul funcțional pentru a vă asigura că prima și/sau ultima valoare nu sunt actualizate atunci când sunt alocateNULL
Dacă funcțiile dintr -un pachet nu conțin toate „actualizarea” cuvântului explicit, atunci există și
create_test_update_fns. Cu această funcție, orice număr de nume de funcții dintr -un anumit pachet va fi batjocorit pentru a actualiza intrările atunci când sunt apelate în scriptul de testare.
test_that("Selected date updates when button is triggered", {
local_mocked_bindings(!!!create_test_update_fns(c("updateDateInput", "updateSelectInput")))
...
})
Notă: Acest lucru va necesita {rlang} sau utilizare do.call În schimb, pentru a atribui funcțiile legăturilor batjocorite locale.
