Search code examples
rtestthat

Providing a sensitive API key to testthat


I'm attempting to setup mocking of an API to increase the test coverage of an API package I maintain (https://github.com/condwanaland/scrobbler)

Installable with

remotes::install_github("condwanaland/scrobbler")

I've used httptest to record the results of hitting the API

library(httptest)

capture_requests({
  download_scrobbles(.limit1 = TRUE)
})

capture_requests stores the result of this request in json files. The mock then loads this file in place of making the actual request

In download_scrobbles(), the API username and key are loading via environment variables

Sys.getenv('LASTFM_API_USERNAME'); Sys.getenv('LASTFM_API_KEY')

However, I then have setup a snapshot test to check that the output remains the same

library(httptest)
library(testthat)

with_mock_api(
  {
    test_that("Output is producted correctly", {
      local_edition(3)
      expect_snapshot_value(
        download_scrobbles(.limit1 = TRUE),
        style = "deparse")
    })
  }
)

However, since testthat doesn't have access to my .Renviron file it fails with

'LASTFM_API_USERNAME' and/or 'LASTFM_API_KEY' environment variables are not set.
         Set them with 'Sys.setenv() or pass these variables explicitly.

I cant pass these parameters explicitly because then they would get checked into git and reveal the username and api key.

How can I either:

  1. Give testthat access to my local .Renviron file when run interactively (I'll skip the test when non-interactive), or
  2. Provide a .Renviron file to testthat in a way that doesn't require checking something into git or being built by R CMD BUILD, or
  3. Any other option I haven't considered?

Solution

  • I was able to find an answer to this. If you just supply a fake password to the test it throws an error because it cant find the mocked files:

    with_mock_api(
      {
        test_that("Output is producted correctly", {
          local_edition(3)
          expect_snapshot_value(
            download_scrobbles("condwanaland", "mocked", .limit1 = TRUE),
            style = "deparse")
        })
      }
    )
    
    Error: GET http://ws.audioscrobbler.com/2.0/?method=user.getRecentTracks&user=condwanaland&limit=1000&api_key=mocked&format=json&page=1&from=0 
    (ws.audioscrobbler.com/2.0-699785.json)
    

    However, the last part of that error (ws.audioscrobbler.com/2.0-699785.json) tells you the file name that httptest is looking for. By renaming the existing json file to match the expected one, the test passes.