R:如何使用 testthat 测试依赖于外部程序的函数?
R: How to test a function that relies on an external program using testthat?
我有一个调用 bowtie2-build 的函数 bowtieIndex(bowtieBuildLocation, filename)
。它的参数是我系统上的 bowtie2-build 位置和输出文件名。
如何在不对 bowtie2-build 位置进行硬编码的情况下为此函数编写测试?
如果您在函数内部所做的只是调用外部程序,那么您无法直接测试它是否有效。如果没有代码本身,这很难具体回答,但是,例如,如果 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" ))
我有一个调用 bowtie2-build 的函数 bowtieIndex(bowtieBuildLocation, filename)
。它的参数是我系统上的 bowtie2-build 位置和输出文件名。
如何在不对 bowtie2-build 位置进行硬编码的情况下为此函数编写测试?
如果您在函数内部所做的只是调用外部程序,那么您无法直接测试它是否有效。如果没有代码本身,这很难具体回答,但是,例如,如果 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" ))