(Acest articol a fost publicat pentru prima dată pe Rtaskș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.
Puteți citi postarea originală în formatul său original pe site -ul RTASk de Thinkr aici: Mock -le toate: Simulați -vă pentru a testa mai bine cu Testthat
Testarea unităților în R. Știți, acele mici funcții care vă asigură că codul dvs. funcționează perfect – chiar și atunci când sunteți în vacanță sau scrieți noi module la 2 dimineața
Dar să fim sinceri: când vine vorba de testarea interacțiunilor utilizatorilor sau a resurselor externe, lucrurile se pot transforma rapid într -o durere de cap.
Ce faceți atunci când codul dvs. necesită un dialog de selecție a fișierelor sau o conexiune la o API care durează pentru totdeauna pentru a răspunde?
În niciun caz nu doriți să blocați totul doar pentru un test!
În aceste cazuri, este timpul să devii deștept. Ideea nu este de a renunța la testare, ci de a ocoli inteligent ceea ce este problematic. Acolo vine o tehnică cunoscută: mocking
.
Din fericire, R și testthat
Pachetul oferă instrumente doar pentru acest lucru.
Mocking
înseamnă înlocuirea temporară a unei funcții sau a unei resurse cu o versiune falsă, controlată, care simulează comportamentul așteptat.
Intrigat? Să ne scufundăm.
Arta lui Pretending
: Simularea interacțiunilor utilizatorului
Imaginează -ți o funcție care solicită utilizatorului să selecteze un fișier.
Dacă ar trebui să testați această funcție cu o casetă de dialog reală, ar fi o pierdere totală de timp – ca să nu menționați imposibil de automatizat cu ușurință într -un mediu CI.
Acolo este magia mocking
intră.
Iată un exemplu al unei astfel de funcții:
select_file <- function() { file_path <- choose.files() # Cette fonction ouvre une boîte de dialogue cat("You have chosen the file :", file_path) }
Nu doriți să selectați manual un fișier de fiecare dată când executați testul.
Cu with_mocked_bindings()
din {testthat}
pachet, puteți înlocui choose.files
cu o versiune care returnează pur și simplu o cale predefinită.
Acest lucru evită orice interacțiune și face testul instantaneu:
test_that("select_file works without a dialog box", { with_mocked_bindings( code = { expect_output(select_file(), "You have chosen the file : C:/fakedir/fakefile.txt") }, choose.files = function() {"C:/fakedir/fakefile.txt"} ) })
Și asta este! Testați funcția ca și cum utilizatorul a selectat deja un fișier – nici o casetă de dialog implicată.
Când simularea devine esențială: testarea resurselor externe
Testele unitare sunt adesea utilizate pentru a verifica funcțiile care se bazează pe resurse externe, cum ar fi API -uri, baze de date sau interacțiuni de rețea.
Imaginează -ți o funcție care preia datele dintr -o API.
Apelarea API -ului în timpul fiecărui test ar fi lent, costisitor și complet inutil.
În schimb, puteți simula răspunsul API. Iată cum:
fetch_data <- function() { response <- httr::GET("https://api.exemple.com/data") content <- httr::content(response) return(content) }
Pentru a testa această funcție fără a efectua un apel real API, puteți batjocori răspunsul folosind with_mocked_bindings
.
Iată un exemplu în care apelul API este înlocuit cu un răspuns realizat manual:
Acum testezi funcția fără să lovești vreodată API -ul real și ai un control complet asupra a ceea ce a revenit.
Puteți simula diferite situații (răspuns de succes, eroare, timeout etc.) fără a depinde de starea API reală.
⚠️ Nu totul poate fi batjocorit: limitările
Unele funcții nu pot fi batjocorite direct, de exemplu:
Sys.time() Sys.getenv()
Încercând să le înlocuiesc cu with_mocked_bindings()
Rezultate în:
Error in `local_mocked_bindings(...)`: Can't find binding for `Sys.time`
De ce? Pentru că anumite funcții precum Sys.time()
şi Sys.getenv()
sunt funcții primitive în R.
Sunt profund încorporate în nucleul limbajului și nu sunt obiecte R obișnuite, puteți trece cu ușurință ca funcții definite de utilizator.
🩹 Soluția: încapsulează comportamentul
Soluția: creați o funcție de înveliș în codul dvs. mock
.
Exemplu:
# Dans votre package get_current_time <- function() { Sys.time()} say_hello <- function() { if (format(get_current_time(), "%H") == "12") { "Time for lunch!" } else { "Just a little longer..." } }
Testele ET DANS VOS:
test_that("say_hello correctly detects noon", { with_mocked_bindings( code = expect_equal(say_hello(), "Time for lunch!"), get_current_time = function() as.POSIXct("2025-04-25 12:00:00") ) })
🚪 În rezumat
with_mocked_bindings()
Vă permite să simulați funcțiile al căror comportament variază în funcție de intrarea utilizatorului, de starea de sistem sau de timp, într -un mod elegant;- Unele funcții nu pot fi batjocorite direct (cum ar fi
Sys.time
,Sys.getenv
): înfășurați -le într -o funcție separată; - Este o modalitate excelentă de a crea teste rapide, fiabile, non-interactive.
Această postare este mai bine prezentată pe site -ul său original Thinkr aici: batjocorește -le pe toate: Simulați -vă pentru a testa mai bine cu Testthat