R:如何使用testthat测试依赖外部程序的函数?

时间:2016-02-03 12:41:31

标签: r testthat

我有一个调用bowtie2-build的函数bowtieIndex(bowtieBuildLocation, filename)。它的参数是我系统上的bowtie2-build位置和输出文件名。

如何在不对bowtie2-build位置进行硬编码的情况下为此函数编写测试?

1 个答案:

答案 0 :(得分:3)

如果您在函数内部所做的只是调用外部程序,那么您无法测试它是否直接起作用。如果没有代码本身,这很难具体回答,但是,例如,如果bowtieIndex正在调用system来运行外部程序,则可以模拟system将执行的操作,假装它运作或失败。查看testthat::with_mock的文档。

接下来是三个例子。第一个参数是将执行的新代码,而不是真正的system函数。如果您想要执行非常具体的操作,则在函数定义中正常使用调用system函数的参数。我发现重复测试更容易,而不是编写复杂的替换函数。第二个参数(代码块{})内的所有内容都是使用仅查看替换系统函数的上下文执行的,包括所有嵌套函数调用。在此代码块之后,with_mock函数退出,真实base::system自动返回范围。可以模拟哪些函数有一些限制,但可以覆盖令人惊讶的基本函数。

# Pretend that the system call exited with a specific error
with_mock(
    `base::system`= function(...) {
        stop("It didn't work");
    }, {
    expect_error( bowtieIndex( bowtieBuildLocation, filename ),
                  "It didn't work"
    )
})

# Pretend that the system call exited with a specific return value
with_mock(
    `base::system`= function(...) {
        return(127);
    }, {
    expect_error( bowtieIndex( bowtieBuildLocation, filename ),
                  "Error from your function on bad return value." )
    expect_false( file.exists( "someNotGeneratedFile" ))
})

# Pretend that the system call worked in a specific way
with_mock(
    `base::system`= function(...) {
        file.create("someGeneratedFile")
        return(0);
    }, {
    # No error
    expect_error( got <- bowtieIndex(bowtieBuildLocation, filename), NA )

    # File was created
    expect_true( file.exists( "someGeneratedFile" ))
})

# got variable holding results is actually available here, outside
# with_mock, so don't need to test everything within the function.
test_equal( got, c( "I", "was", "returned" ))
相关问题