r-lib / rprojroot

Finding files in project subdirectories
https://rprojroot.r-lib.org/
Other
149 stars 23 forks source link

devtools::check() (RStudio check) environment support #89

Closed hute37 closed 1 year ago

hute37 commented 1 year ago

running devtools::check() fails because test environment is very different in this case:

a separate (parallel) directory is generated for checking: project.Rcheck this directory contains a package subdirectory with a (filtered) copy of package contents. tests are copied outside package in a parallel directory. When tests are run, "DESCRIPTION" file and RProj files are not available, causing tests to fail.


* failing test
```R
context("ioutils")
dd_share <- "inst/extdata/ext/sim-rs.net/test/session-1/out"
out_path <- function(filename) { io_path(dd_share, filename) }

test_that("path creation", {
  #browser()
  fullpath <- out_path("test-one")
  datapath <- rprojroot::find_package_root_file(dd_share)
  expect_true(startsWith(fullpath, datapath))
  expect_true(file.exists(datapath))
})

See attached screenshot

image

hute37 commented 1 year ago

Fixed with this change instead of:

find_path <- function(fp) {
  result <- rprojroot::find_package_root_file(pathname)
  return (result)
}

use a multi-criteria, supporting testthat environment

find_path <- function(fp) {
  result <- rprojroot::find_root_file(fp, criterion = 
                                        rprojroot::is_r_package | 
                                        rprojroot::is_rstudio_project | 
                                        rprojroot::is_testthat)
  return (result)
}
hute37 commented 1 year ago

different semantics, patch does not work: with devtools::test(), it resolves to test directory, instead of project root

jennybc commented 1 year ago

What are you trying to do? What sort of path are you trying to make?

If it's a path within the test directory, use testthat::test_path() https://testthat.r-lib.org/reference/test_path.html.

If it's a generic "path within a package", use system.file() or fs::path_package().

This advice about files below inst/ might be relevant: https://r-pkgs.org/misc.html#sec-misc-inst and https://r-pkgs.org/data.html#sec-data-system-file

hute37 commented 1 year ago

I have an utility function with tests, unaware of containing package, that is used to fill path prefix to inst/extdata where data file are stored (or symbolic linked). In this directory I also store some small data file used by tests.

Problems arise when I run devtools::check(), that moves tests directory in a sibling position relative to the package root.

What I found so far is a way to detect DESCRIPTION file in /tests sibling directories. But in CHECK phase, the copied inst/extdata directory looks empty anyway ... So maybe the only option here is to disable these tests in check phase (This requires detection of this out-of-package-root condition).


Adjusted patch, still failing ...

find_test_path <- function(fp) {
  parent_path <- rprojroot::find_root_file(".", criterion = 
        rprojroot::root_criterion(function(path) dir.exists(file.path(path, "tests")), "has tests subdir"))
  sib_dirs <- list.dirs(path = parent_path, full.names = TRUE, recursive = FALSE)
  desc_path <- reader::find.file("DESCRIPTION", dir = "", dirs = sib_dirs)
  root_path <- dirname(desc_path)
  result <- paste(root_path, fp, sep='/')
  return (result)
}

find_path <- function(fp) {
  result <- tryCatch(rprojroot::find_root_file(fp, criterion = 
                                        rprojroot::is_r_package | 
                                        rprojroot::is_rstudio_project ),
                     error=function(cond) {
                       testpath <- find_test_path(fp)
                       return(testpath)
                     })
  return (result)
}
hute37 commented 1 year ago

conditional testing

is_check_mode <- function() {
  result <- tryCatch({rprojroot::find_root_file('.', criterion = 
                                                 rprojroot::is_r_package | 
                                                 rprojroot::is_rstudio_project )
                       return(FALSE)},
                     error=function(cond) {
                       return(TRUE)
                     })
  return (result)
}

dd_base  <- "inst/extdata/ext"
dd_user  <- "inst/extdata/ext/eem-ds.def/test/session-1/out"
dd_local <- "inst/extdata/ext/eem-ds.loc/test/session-1/out"
dd_share <- "inst/extdata/ext/eem-ds.net/test/session-1/out"

out_path <- function(filename) { io_path(dd_share, filename) }

test_that("base path", {
  #browser()
  if (!is_check_mode()) {
    basepath <- find_path(dd_base)
    expect_true(file.exists(basepath))
  }
})

test_that("path creation", {
  #browser()
  if (!is_check_mode()) {
    fullpath <- out_path("test-one")
    datapath <- find_path(dd_share)
    cat("\n\n@[path creation]\n")
    print(fullpath)
    print(datapath)
    cat("\n")
    expect_true(startsWith(fullpath, datapath))
    expect_true(file.exists(datapath))
  }
})