(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
