Literate Testing in R
Posted on October 26, 2013
This past summer I attended the French R meeting in Lyon. But that’s secondary for this story. The important part happened while I was on the train on my way to Lyon.
As I was reviewing a couple of my functions, I noticed that I was getting sick. Not from motion sickness but from the way I was validating the arguments of the functions. One of the functions required a positive integer as an input.
R has the function is.integer(x)
to check if x
is an integer. The problem is
that if you type is.integer(1)
you would get FALSE
as an answer. The reason
is because 1 is not stored as an integer in R, but as a double. If you want an integer
then you should use 1L. Now, if you type is.integer(1L)
the answer is TRUE
.
So, what does this have to do with my story? Well, if I want to validate whether a given
object x
is a positive integer, I could write the following line:
# check if x is a positive integer
if (mode(x) == "numeric" && x > 0 && x %% 1 == 0) TRUE else FALSE
What if I could simply write something like this:
# test if x is a positive integer
is_positive_integer(x)
Isn’t this much better and simpler, not to mention more understandable? Hell yes! So why
not to have more functions like is_positive_integer(x)
to test specific features
of some common R objects?
I spent the rest of my ride to Lyon, and the next couple of days creating tester, an R package that provides a wide range of functions that will allow you to test characteristics of common R objects … in a more human readable way following the so called Literate Programming paradigm of Donald Knuth.
To give you a better idea of tester
, here are some of the functions that you can
find to make your life easier when testing the behavior of different R objects. The main
goal is to provide tools for checking arguments of functions in a more human readable way.
Testing numbers
Some of the functions related to different types of numbers:
is_positive()
is_negative()
is_integer()
is_natural()
is_odd()
is_even()
is_decimal()
is_scalar()
Testing vectors
Some of the functions related to vectors:
is_vector()
is_numeric_vector()
is_string_vector()
is_logical_vector()
is_not_vector()
Testing matrices
Some of the functions related to matrices:
is_matrix()
is a matrixis_numeric_matrix()
is a numeric matrixis_string_matrix()
is a character matrixis_logical_matrix()
is a logical matrixis_not_matrix()
is not a matrixis_square_matrix()
is a square matrixis_diagonal()
is a diagonal matrixis_triangular()
is a triangular matrix
Testing data frames
Some of the functions related to data frames:
is_dataframe()
is_numeric_dataframe()
(is a numeric data frame)is_string_dataframe()
(is a character data frame)is_not_dataframe()
Testing matrices and data frames
Some of the functions related to both matrices and data frames:
is_tabular()
(is a matrix or data frame)is_not_tabular()
(is not matrix neither a data frame)has_dimension()
lacks_dimension()
is_one_dim()
has_rownames()
lacks_rownames()
has_colnames()
lacks_colnames()
In summary
As you can tell, tester
offers you several functions with simple memorable names
that are easy for us (human beings) to understand what the computer is doing. If you are
interested in the package, let me tell you that there are many more functions, and you
can also find an introductory
vignette.
Let us change our traditional attitude to the construction of programs: Instead of imaging that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.
Donald Knuth, Literate Programming