Internal testing using clipr and testthat in terms of code coverage

Hello everyone! How are we all doing? :smile:

I have a package I have been making whose purpose is to house use case functions I have been using frequently. I have Travis-CI set up with covr's code coverage. I get results back fine (love how great these tools are), however, the issue lays within my back_to_forward() function. This function takes a copied file path (primarily on Windows) that has back slashes and pastes it with forward slashes (efficient using the hotkey + addin).

I have been through trying methods from reprex and datapasta (also amazing tools!) for testing. I have the tests working locally on my computer, but code coverage shows that nothing is being tested. I assume this is because within Travis-CI the code doesn't get tested due to clipr not being available.

Below are my scripts for the function and the testing file. Is there a way to get my function to be "covered" by code coverage?

Click to show R/back_to_forward.R

#' @title Backslash to Forward Slash
#'
#' @description This function is primary for windows users. When copying file paths on windows they will contain backslashes, "\", which will throw an error in R because "\" is used for escape characters. Due to how R reads "\", this function reads the filepath directly from the clipboard. The user can either run *back_to_forward()* in the console to get the path with forward slashes, or put *back_to_forward()* on a hotkey for instant posting within the script.
#'
#' @details Primarily for Windows users. When copying file paths in Windows it will use a backslash to seperate files, this will throw an error in R. The process of manually changing the backslashe to forward slashes can get highly repetitive. The `back_to_forward()` function will take what is in the users clipboard and paste the path with the wanted forward slashes. There are two approaches to this; 1) run `back_to_forward()` in the console to retreive the string version with forward slashes of the path, or 2) Assign a hotkey to the addin `Back to Forward Slash`. Shout out to the `reprex` package for testing `clipr` methods.
#'
#' @param render A Logical. Defaults to `TRUE`. Exists primarily for the sake of internal testing.
#'
#' @return A string. A file path that is compatible with R.
#' @export
#'
#' @examples
#' \dontrun{
#' # Example path in clipboard:
#' # C:\Documents\Newsletters\Summer2018.csv
#' back_to_forward()
#' }
back_to_forward <- function(render = TRUE) {
  text <- clipr::read_clip()

  if (stringr::str_detect(text, "\\\\")) {
    text <- gsub(
      pattern = "\\\\",
      replacement = "/",
      x = text
    )
  }

  if (render) {
    rstudioapi::insertText(text)
  } else {
    text
  }
}

Click to show tests/testthat/test-back_to_forward.R

test_that("back slash", {
  skip_on_cran()
  # explicitly permit clipboard access in non-interactive session
  withr::local_envvar(c(CLIPR_ALLOW = TRUE))
  skip_if_not(
    clipr::clipr_available(),
    "System clipboard is not available - skipping test."
  )
  clipr::write_clip(content = "sample\\file\\path")
  expect_match(back_to_forward(render = FALSE), "sample/file/path")
})

test_that("forward slash (just paste it!)", {
  skip_on_cran()
  withr::local_envvar(c(CLIPR_ALLOW = TRUE))
  skip_if_not(
    clipr::clipr_available(),
    "System clipboard is not available - skipping test."
  )
  clipr::write_clip(content = "sample/file/path")
  expect_match(back_to_forward(render = FALSE), "sample/file/path")
})

Thank you for your time. I appreciate any help and direction for this process!

Kyle

edit 2019-06-13: Fixed a small error in original .R file :smile:

@KoderKow Looks like a very useful set of utility functions!

My advice to increase your code coverage is to separate the ability of your function to convert file paths from its ability to read from the clipboard. This will make it easier to write automated tests specifically for the feature added by your function.

For example, you could modify back_to_forward() to take an argument text:

back_to_forward <- function(text = clipr::read_clip(), render = TRUE) {
  
  if (stringr::str_detect(text, "\\\\")) {
    text <- gsub(
      pattern = "\\\\",
      replacement = "/",
      x = text
    )
  }
  
  if (render) {
    rstudioapi::insertText(text)
  } else {
    text
  }
}

The default behavior will be exactly the same, i.e. reading from the clipboard. But now your tests can bypass the requirement of reading from the clipboard by directly passing in a character string. Then you could add these new tests:

test_that("back slash", {
  expect_match(back_to_forward("sample\\file\\path", render = FALSE),
               "sample/file/path")
})

test_that("forward slash (just paste it!)", {
  expect_match(back_to_forward("sample/file/path", render = FALSE),
               "sample/file/path")
})

On your local machine, you can run all the tests. But on Travis, the above tests could still run, which would cover most of the lines of the function.

2 Likes

Wow! The solution was in my face this whole time haha! Thank you so much, that is a fantastic way to approach this.

:tada::tada::tada::tada::tada::tada:

Codecov test coverage

:tada::tada::tada::tada::tada::tada:

The only uncovered part is render = TRUE, you mentioned most of the function should be covered and it is now. This has made me incredibly happy, I was going crazy trying to get this function even partially covered :sweat_smile:

Thanks again @jdblischak :smile:

1 Like

Wow! The solution was in my face this whole time haha!

I've been in the same situation many times. A second set of eyes is always very helpful :grinning:

Thank you so much, that is a fantastic way to approach this.

Glad I could help! Congrats on reaching 98% code coverage!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.