暂时忽略R

时间:2019-04-18 13:15:30

标签: r unit-testing continuous-integration r-package

我目前正在为我们公司开发的R软件包进行持续集成设置。每个R包都有一个Jenkins项目,每个项目都有一个对应的库。

我已经定义了将包的所有依赖项安装到项目库中的逻辑。现在我想定义一个基本上运行的检查阶段

devtools::check("${PROJECT_DIR}/pkg")

仅将项目库用于依赖项。我尝试通过以下方式使用callr包。

callr::r(
  function(...) {
    devtools::check(...)
  ),
  args = list("${PROJECT_DIR}/pkg"),
  libpath = "${PROJECT_DIR}/lib"
)

但是,检查过程仍然可以找到libpath中未安装的软件包。有没有办法确保在构建阶段仅使用"${PROJECT_DIR}/lib"

到目前为止,我已经尝试了以下方法

  • callr()libpath参数
  • withr::with_libpathsnew参数
  • 浏览devtools::checkR CMD BUILD中的文档以了解 合适的参数
  • 使用.libPaths("${JOB_DIR}/lib")

这是一个说明callr意外行为的repex。我预计第3行会出现错误。

find.package("ggplot2", .libPaths()[1])
#> Error in find.package("ggplot2", .libPaths()[1]): there is no package called 'ggplot2'
callr::r(function() {  ggplot2::vars() }, libpath = .libPaths()[1])
#> named list()
find.package("ggplot2", .libPaths()[2])
#> [1] "/data/R/3.5.3/lib/R/library/ggplot2"
callr::r(function() {  ggplot2::vars() }, libpath = .libPaths()[2])
#> named list()

2 个答案:

答案 0 :(得分:1)

根据this question编码,可以使用base::assign对此进行归档。如果有更合适的解决方案,我很想听听。

callr::r(function() {
  assign(".lib.loc", .libPaths()[1], envir = environment(.libPaths))
  ggplot2::vars() 
})
#> Error in loadNamespace(name): there is no package called ‘ggplot2’

我在这里遇到的问题是双重的

  1. 基本上,这是一种黑客行为,如果.libPaths()的内部结构发生变化,它可以随时中断
  2. 我可能还必须修改.Library.Library.site.libPaths()的内部),以确保devtools::check受到适当的影响。

答案 1 :(得分:1)

这可能与主题无关,但是您是否考虑过在本用例中使用docker

您可以定义Dockerfile中引用的Jenkinsfile,这将为运行的每个CI作业定义一个自定义图像。您可以使用Jenkins中的devtools::install()将软件包安装到docker容器上。 CI完成后,此容器将被扔掉。

使用这种方法,您不必担心在运行CI时自己手动安装软件包,也不必担心不同软件包之间的命名空间冲突。

这肯定会有更高的启动成本,但是我认为从长远来看,测试R软件包是值得的。资料来源:我也在工作中测试了内部R包。

样本Dockerfile

FROM docker.io/rocker/r-base

USER root

# Install packages needed for package development
RUN R -e 'install.packages(c("devtools", "rmarkdown", "testthat", "roxygen2"))'

然后您在Dockerfile中引用此Jenkinsfile,以便安装,测试和检查软件包(下面的管道示例)

    agent {
        dockerfile {
            args '-u root'
        }
    }
    stages {
        stage('Install') {
            steps {
                sh 'r -e "devtools::install()"'
            }
        }
        stage('Test') {
            steps {
                sh '''
                  r -e "options(testthat.output_file = 'test-out.xml'); devtools::test(reporter = 'junit')"
                '''
                junit 'test-out.xml'
            }
        }
        stage('Check') {
           // Might need to modify expected ouput, depends on devtools version
            steps {
                sh '''
                  testOutput=$(R -e "devtools::check(args='--no-tests')" 2>&1)
                  echo "${testOutput}" | grep -q "0 errors ✔ | 0 warnings ✔ | 0 notes ✔"
                '''
            }
        }
    }
}

相关问题