現在、プロジェクトでR6クラスを使用しています。R6クラスのプライベートメソッドのテストR
私は使用しているプライベートメソッドの機能をテストする単体テストを作成したいと考えています(これらのプライベートメソッドを使用しているより複雑なパブリックメソッドを実行しないことが望ましい)。
ただし、プライベートメソッドにアクセスするようにアクセスできません。
どのようにすれば最適ですか?
ありがとうございます!
現在、プロジェクトでR6クラスを使用しています。R6クラスのプライベートメソッドのテストR
私は使用しているプライベートメソッドの機能をテストする単体テストを作成したいと考えています(これらのプライベートメソッドを使用しているより複雑なパブリックメソッドを実行しないことが望ましい)。
ただし、プライベートメソッドにアクセスするようにアクセスできません。
どのようにすれば最適ですか?
ありがとうございます!
は環境がハッキングや変更を必要としないソリューションです。このようにそれを使用するよりも
...
A <- R6::R6Class(
"A",
private = list(
private_print = function(){print("Ola")}
),
public = list(
get = function(name=NULL){
# recursion
if(length(name)>1){
tmp <- lapply(name, self$get)
names(tmp) <- name
return(tmp)
}
if(is.null(name)){
self$message("no input, returning NULL")
return(NULL)
}
# self
if(name=="self"){
return(self)
}
# in self
if(name %in% names(self)){
return(base::get(name, envir=self))
}
# private or in private
if(exists("private")){
if(name=="private"){
return(private)
}else if(name %in% names(private)){
return(base::get(name, envir=private))
}
}
# else
self$message("name not found")
return(NULL)
}
)
)
...
をあなたがテストしたいクラスですが、あなたのためのテストを行う新しいクラスを作成します。 R6
で
、派生クラスは、(C++
またはあなたが同じ結果をarchieveするprotected
キーワードが必要Java
とは違って)その基底クラスのprivate
メソッドへのアクセス権を持っています。したがって、テストするクラスから派生したTesterClass
を書くことができます。例:
library(R6)
ClassToTest <- R6Class(
private = list(
privateMember = 7,
privateFunction = function(x){
return(x * private$privateMember)
}
)
)
TesterClass <- R6Class(
inherit = ClassToTest,
public = list(
runTest = function(x = 5){
if(x * private$privateMember != private$privateFunction(x))
cat("Oops. Somethig is wrong\n")
else
cat("Everything is fine\n")
}
)
)
t <- TesterClass$new()
t$runTest()
# Everything is fine
このアプローチの利点の1つは、詳細なテスト結果を保存したい場合に備えて、環境をきれいに保つことです。
現在、R6オブジェクトのプライベート環境にアクセスする方法があります。しかし、これは文書化されていない方法でオブジェクトに到達しているので、将来破損する可能性があります...私はそれがすぐにでも起こるとは思わない。
# Gets private environment from an R6 object
get_private <- function(x) {
x[['.__enclos_env__']]$private
}
A <- R6::R6Class("A",
private = list(x = 1)
)
a <- A$new()
get_private(a)$x
# [1] 1
あなたのクラスにヘルパーメソッドget
を追加することができます。ここでは
a <- A$new()
a$get("private_print")()
## [1] "Ola"
通常、クライアントコードから間接的に(つまり、クラスのパブリックメソッド内から)呼び出されるようにプライベートメソッドをテストするべきではなく、*直接*ではありませんか?メソッドとデータメンバーをプライベートにするのは、オブジェクトインスタンスの外部からアクセスできないようにすることです。 – nrussell
ありがとう@nrussell。私にとっては、単体テストの作成は、すべての機能が意図どおりに機能することを保証するためのものです。そのために、単体テストはできるだけ低いレベルで書かれるのが最善です。はるかに複雑な何かを行うパブリックメソッド(例えば、プライベートメソッドをさまざまな設定で何百回も呼び出す)の単体テストを書くと、テストの実行とデバッグの失敗がずっと複雑になります。 –