useful for ideas for implementing better testing in my code. As always, I susally pick up other things unrelated to the session that end up being more useful than the intended content. e.g. package installation/loading - I seem to be doing this all wrong!
very well pitched and comprehensive session
While intermediate, this was a great introduction to testing R code and providing plenty of things to think about and go try out
Welcome
this session is for 🌶🌶 intermediate users
you’ll need R + Rstudio / Posit Workbench / posit.cloud to follow along
Session outline
introduction: why test?
informal testing
unit testing
introduction - why automate your tests?
testthat walkthrough
Introduction: why test?
code goes wrong
functions change
data sources change
usage changes
testing guards against the commonest problems
that makes for more reliable code
more reliable code opens the way to nicer development patterns
A note
most discussions about testing come about as part of package development
we’ll also steer clear of Shiny/Rmarkdown/Quarto, as things can be a bit more tricky to test there
we also won’t talk about debugging here (although do look out for the future training session on that)
Informal testing
a real-world example: Teams transcripts
Teams transcripts can be very useful data-sources
but they’re absolutely horrible to work with:
WEBVTTQ1::>00:00:00.000 --> 00:00:14.080<v Brendan Clarke> this was the first question in the transcript00:00:14.080 --> 00:00:32.180<v Someone Else> then someone replied with this answerQ2::>00:00:32.180 --> 00:00:48.010<v Brendan Clarke> then there was another question00:00:48.010 --> 00:00:58.010<v Someone Else> and another tedious response
imagine that you’ve written a (horrible) Teams transcript parser:
how would you test this code to make sure it behaves itself?
if you want to work with vectors, there are a number of tools for checking their contents:
x <-rownames(as.matrix(eurodist, labels=TRUE)) # odd built in datasettest_that("check my vec", {expect_equal(x[1:2], c("Athens", "Barcelona"))})
Test passed 😀
you can get much more fancy with a bit of set theory (not really set theory):
y <- xtest_that("check my vec sets", {expect_success(expect_setequal(x, y)) # all x in yexpect_failure(expect_mapequal(x, y)) # same names, y is proper subset x) # all x in y)show_failure(expect_contains(x[1:19], y)) # y proper subset x)expect_success(expect_in(x, y)) # x proper subset y})
Failed expectation:
x[1:19] (`actual`) doesn't fully contain all the values in `y` (`expected`).
* Missing from `actual`: "Stockholm", "Vienna"
* Present in `actual`: "Athens", "Barcelona", "Brussels", "Calais", "Cherbourg", "Cologne", "Copenhagen", "Geneva", "Gibraltar", ...
Test passed 🥳
y <-sample(x, length(x)-2)test_that("check my vec sets", {expect_failure(expect_setequal(x, y)) # all x in yexpect_failure(expect_mapequal(x, y)) # same names, y is proper subset x) # all x in y)expect_success(expect_contains(x, y)) # y proper subset x)expect_failure(expect_in(x, y)) # x is a proper subset y})
Test passed 😀
Testing tibbles
because most of the tests are powered by waldo, you shouldn’t have to do anything fancy to test on tibbles: