Test API-wrapping R packages with OAuth Tokens

This took me all evening to figure out. OK, here goes. I think it’s right. My package build is failing for different reasons now.

  1. Create your OAuth token file

    I’m using Oliver Keyes’s driver package to grab documents from Google drive in my rchie package. So I use his driver_connect() function to create an OAuth token with and save it to disk in mytests/testthat/ directory.

    d_token  = driver_connect(drive.app, drive.secret)
    saveRDS(d_token, "tests/testthat/token_file.rds")

    Note that drive.app and drive.secret are keys I’ve created by creating an app with the Drive API.

    You can do the same with httr::oauth2.0_token() to create your token for other APIs.

  2. Write a test

    In tests/testthat/, I also have a file called test_google_doc.R which contains this test:

    context('Online Services')
    test_that("google doc imported correctly",  {
      d_token = readRDS("token_file.rds")
      library(driver, quietly=TRUE)
      archie_test_id = '16WHsVRyCM6dHVHTvFYsTbNaIl1vavGPp8GU3OnUS7oE'
      meta_d = file_metadata(d_token, archie_test_id)
      tmp = tempfile()
      download_file(d_token, meta_d, 'text/plain', tmp)

    The important thing here is that the test reads in the token file, then uses it to access a google doc via file_metadata() and download_file(). Use your token for whatever purposes you wantin your package. This test should work on your local machine with devtools::test() or the “Test” button in RStudio.

  3. Encode your token file

    First, you need the travis CLI. Get it with

    gem install travis

    You need to be logged in to your Travis account. Do this with

    travis login

    Note you’ll use you GitHub password for this. There are other login options, which are described when you run this command.

    Now encrypt your token:

    travis encrypt-file tests/testthat/token_file.rds --add

    --add will automatically add a decrypt command to your .travis.yml file.

  4. Ignore and commit.

    Put tests/testthat/token_file.rds in your .gitignore

    Put tests/testthat/token_file.rds.enc in your .Rbuildignore

    Do not mix these up. You don’t want your token file on GitHub, and you don’t want the encoded version being distributed into everyone’s libraries. If you put token_file.rds in your .Rbuildignore, it will not be copied over into the package.rcheck directory when Travis runs R CMD CHECK, and your tests will fail. Over and over. As you bang your desk trying to figure out what’s wrong.

    Commit tests/testthat/token_file.rds.enc and your updated .travis.yml and push to GitHub. The tests should run on Travis!

Now, can someone tell me how to write the test so it runs on Travis-CI, but not on CRAN?


Hmn; does the token not expire over time? (I really need to have a “reauthenticate” function. Then you could, at the beginning of the test, make a test query for something you don’t care about, in a tryCatch blob, and reauthenticate if it fails)

I’m not sure about the Travis-not-CRAN but I’d love to hear what others have. And I’d love to see you turn this into a blog post once it’s finished!

Just discovered testthat::skip_on_cran(). Easy-peasy.

Also, most times I run the tests, I get this message:

Auto-refreshing stale OAuth token

Which I assume is some Hadley magic preventing the token from expiring.

1 Like

Now, can someone tell me how to write the test so it runs on Travis-CI,
but not on CRAN?
You want skip_on_cran()

@noamross whoops, apologies – apparently the email notifications from Discourse lag enough behind that I saw only your original post and not your follow up comment at the time I replied from email.

Note that since the Travis scripts use --as-cran, skip_on_cran() causes tests to be skipped on Travis, as well. You can fix this by setting the NOT_CRAN environmental variable in your .travis.yml file, like so:

  - NOT_CRAN="true"

we can change email notification settings - was the lag too long?

@sckott really? that would be awesome. I find Github email from issues is
pretty close to real time, which I like. Is there any advantage to having
the lag built in?

More minor but I’ve also noticed that when I reply from email, I still get
my own comment emailed back to me (after the delay).

@cboettig The application tries to be smart, so if you have this site open on your laptop, it won’t send an email notification since it assumes you’ll see it in app. Likewise, it I think doesn’t email digests of recent activity to people that have visited the app recently.

I’ll play around and see if i can fix these

see also your own user preferences

1 Like

I’m going to guess this isn’t a hypothetical scenario :wink:

1 Like

Interesting; integrating now, I don’t get the auto-refresh. Hhrrmh!