Subscribe to my newsletter
Unlike python unittesting framework in databricks where
- we had to create testsuite explicitely using unittest
- use xmlrunner to generate xml reports
- and use coverage package internally,
in R things are pretty much straightforward.
Below templates can be used to get started, to implement r unittest framework. We can still use databricks as development environment. The R notebooks can be used as r scripts on non-databricks env (jenkins server) to trigger unittesting.
1. Folder structure
Typical R project structure is advisable. Only folders we will be concerned about during unittesting are,
- R (for R scripts)
- tests (for unittest scripts)
- inst (misc intermediate files, mock data for tests)
2. R Module Notebook
Some module
#./R/somecode.R
f1 <- function(n, ...) {
rnorm(n = n, ...)
}
3. Unit test script using testthat
#./tests/test_framework.R
context("ashish tests r!")
#the very first line has to be a context,
#context here is converted into testsuite in Junit xml
#notice, we can have multiple testsuites within the same script
#underneath they can have multiple test cases
#Good thing about this template is,
# we can still develop this code in a databricks notebook,
#you can run this test_that function in a cell,
#and it will give you results in databricks
#to see if the written tests are functioning as expected.
#once done, the notebook as is can be converted into a script.
library(testthat)
#source("C:/Users/mv792/desktop/testrframework/R/somecode.R")
#this is path where somecode.R is kept on databricks
#notice, this path can be relative from working dir,
#this has to be absolute path
source('/dbfs/mv792/testrframework/R/somecode.R')
test_that("Random tests", {
tmp1 <- f1(20)
testthat::expect_type(tmp1, "double")
#testthat::expect_equal(length(tmp1), 20)
})
#second test suite
context("ashish tests r again!")
test_that("Random tests 1", {
tmp1 <- f1(20)
testthat::expect_type(tmp1, "double")
testthat::expect_equal(length(tmp1), 20)
})
4. triggering the unit test
#trigger.R
#Set the working directory
#notice the paths in below script can be relative
#setwd('C:/users/mv792/Desktop/testrframework/')
library(testthat)
library(covr)
#to trigger single unittest script use test_file function
#another reporter #testthat::JunitReporter$new()
#the Junit compatible xml will be generated in the working dir.
options(testthat.output_file = "test-out-file.xml")
test_file("./tests/test_framework.R", reporter = "junit")
#to trigger all unittest scripts under tests folder,
#use test_dir function
#another reporter #testthat::JunitReporter$new()
options(testthat.output_file = "test-out-dir.xml")
test_dir("./tests/", reporter = "junit")
#for coverage report, we can use relative paths
#report will be generated in the working dir
res <- file_coverage("./R/somecode.R", "./tests/test_framework.R")
report(res, file = './report.html')
Few more things
In databricks, 5.5 LTS runtime, ‘testthat’ and ‘covr’ libraries are not available by default. we need to install those explicitly.
while running function test_file() or test_dir() you might get an error for ‘DT’ library not found, please install that as well explicitely. If the installation failes (likely), while installing use the repo as specific MRAN snapshot ‘https://mran.microsoft.com/snapshot/2018-11-01’
- generated xml report
- generated coverage report