2016-05-12 29 views
1

現在、プロジェクトでR6クラスを使用しています。R6クラスのプライベートメソッドのテストR

私は使用しているプラ​​イベートメソッドの機能をテストする単体テストを作成したいと考えています(これらのプライベートメソッドを使用しているより複雑なパブリックメソッドを実行しないことが望ましい)。

ただし、プライベートメソッドにアクセスするようにアクセスできません。

どのようにすれば最適ですか?

ありがとうございます!

+3

通常、クライアントコードから間接的に(つまり、クラスのパブリックメソッド内から)呼び出されるようにプライベートメソッドをテストするべきではなく、*直接*ではありませんか?メソッドとデータメンバーをプライベートにするのは、オブジェクトインスタンスの外部からアクセスできないようにすることです。 – nrussell

+1

ありがとう@nrussell。私にとっては、単体テストの作成は、すべての機能が意図どおりに機能することを保証するためのものです。そのために、単体テストはできるだけ低いレベルで書かれるのが最善です。はるかに複雑な何かを行うパブリックメソッド(例えば、プライベートメソッドをさまざまな設定で何百回も呼び出す)の単体テストを書くと、テストの実行とデバッグの失敗がずっと複雑になります。 –

答えて

4

は環境がハッキングや変更を必要としないソリューションです。このようにそれを使用するよりも

... 

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つは、詳細なテスト結果を保存したい場合に備えて、環境をきれいに保つことです。

2

現在、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 
1

あなたのクラスにヘルパーメソッドgetを追加することができます。ここでは

a <- A$new() 

a$get("private_print")() 
## [1] "Ola" 
関連する問題