December 11, 2019
Testing is a crucial component to any software package. Testing makes sure that your code does what you expect it to do; and importantly, makes it safer to make changes moving forward because a good test suite will tell you if a change has broken existing functionality. Our recent community call on testing is a nice place to get started with testing.
One way to make testing even harder is through including HTTP requests. This adds complexity for many reasons:
To make testing easier for R packages that do HTTP requests we’ve been working on two packages: webmockr and vcr (introduced on this blog in February 2018 and May 2018, respectively). There’s been a lot of changes since those two blog posts, making testing R packages with HTTP requests easier than ever.
webmockr is a general purpose library for mocking HTTP requests, built to work with any HTTP client in R (exception: curl, for good reason). Use cases include:
Let’s run through a simple example. First, load and enable webmockr:
library(webmockr)
webmockr::enable()
Then create a stub with stub_request()
. Here, we stub a request based on
HTTP method and URL only.
stub_request("get", "https://httpbin.org/get")
Now make a “request”. If the request matches the stub, a real HTTP request will NOT be made, but instead webmockr returns the same object you’ get with a real HTTP request, but with whatever you told webmockr to return (in this case nothing).
library("crul")
x <- HttpClient$new(url = "https://httpbin.org")
x$get('get')
#> <crul response>
#> url: https://httpbin.org/get
#> request_headers:
#> User-Agent: libcurl/7.54.0 r-curl/4.3 crul/0.9.0
#> Accept-Encoding: gzip, deflate
#> Accept: application/json, text/xml, application/xml, */*
#> response_headers:
#> status: 200
v0.5
)
fixed an issue where we weren’t mocking httr simple authentication.v0.5
is support for writing to disk. Both crul and httr allow
users to write to disk as part of the HTTP request. HTTP clients in some other languages
I’m familiar with (e.g., Ruby) don’t do this; you’d have to write to disk yourself. Anyway,
the point is that supporting writing to disk (here and in vcr) was not super easy; it’s
a complicated thing to support. There will probably be edge cases that will break;
open an issue if you run into problems
mocking HTTP requests that write to disk.Check out the release notes for all webmockr changes
vcr leverages webmockr to handle matching requests, but instead of just mocking requests, vcr records real requests and plays them back (hence the name).
Let’s run through a simple example. First, load vcr:
library(vcr)
library(crul)
The main interface in vcr is vcr::use_cassette()
. Pass a code block to use_cassette
as the second argument and vcr will allow a real HTTP request the first time the block
is run, and record the request and response to a file. Any subsequent running of the
same code will use the cached data.
For example, here we make a request to https://httpbin.org
use_cassette(name = "helloworld", {
req1 = crul::HttpClient$new(url = "https://httpbin.org")$get("get")
})
Which makes a real HTTP request and records the request and response to a
file helloworld.yml
. The second call to the same block
use_cassette(name = "helloworld", {
req2 = crul::HttpClient$new(url = "https://httpbin.org")$get("get")
})
uses the helloworld.yml
file - a real HTTP request is not done on subsequent calls.
And we can test that the returned response is the same in both code blocks above
testthat::compare(req1, req2)
#> Equal
?mocking-disk-writing
to get started.?lightswitch
to get started.crul
for now. Ignoring means
that the real HTTP request you want to ignore will be allowed, while all other requests
will be handled by vcr. You can right now ignore certain hosts (e.g., google.com
)
and all localhost requests; in the future we hope to support ignoring any specific
request via user defined functions. See the vcr configuration vignette for
discussion and examples.Open an issue if you run into problems with any of the above features.
Check out the release notes for all vcr changes
We’ve also been working on a book: HTTP mocking and testing in R. The book is intended as a detailed guide for HTTP mocking and testing in R code and packages. The book aims to introduce the reader to leveraging webmockr and vcr in their test suites, going into detail with both packages.
We’ve got some new content in the book and we have more planned. We’d love any feedback on the book; let us know by opening an issue.