PHPUnitテストプライベート属性と方法機能例

6244 ワード

この例では、PHPUnitテストのプライベート属性とメソッド機能について説明します.皆さんの参考にしてください.具体的には以下の通りです.
一、テストクラスのプライベートメソッド:

class Sample
{
  private $a = 0;
  private function run()
  {
    echo $a;
  }
}


上には単純にクラスが含まれているだけで、プライベート変数とプライベートメソッドが含まれています.protectedメソッドとprivateメソッドではpublicメソッドのように直接呼び出すことができないためphpunitを用いて単測を行う場合,特に1つのクラスでは対外的に少量のインタフェースしか提供されず,内部的に大量のprivateメソッドが使用されている場合に不便であることが多い.
protectedメソッドでは、継承方式でテストすることを推奨しますが、ここでは説明しません.一方private法の試験ではphpの反射機構を用いて行うことを提案した.あまり話さないで、コードをつけます.

class testSample()
{
    $method = new ReflectionMethod('Sample', 'run');
    $method->setAccessible(true); // run private public 
    $method->invoke(new Sample()); // run 
}


runメソッドが静的である場合:

private static function run()
{
  echo 'run is a private static function';
}


invoke関数は次のように書くことができます.

$method->invoke(null); // 


runがパラメータを伝達する必要がある場合は、次のようにします.

private function run($x, $y)
{
  return $x + $y;
}

では、テストコードを次のように変更できます.

$method->invokeArgs(new Sample(), array(1, 2));
//array 。 3


【注意】:反射法によるプライベートメソッドのテストは良いが、setAccessible関数はphp 5である.3.2以降でサポートされている(>=5.3.2)
二、プライベート属性のget/set
プライベートメソッドについては、プライベートプロパティを見てみましょう.Sampleクラスを例に挙げます.Sampleクラスのプライベートプロパティ$aの値を取得または設定するには、次の方法があります.

public function testPrivateProperty()
{
  $reflectedClass = new ReflectionClass('Sample');
  $reflectedProperty = $reflectedClass->getProperty('a');
  $reflectedProperty->setAccessible(true);
  $reflectedProperty->getValue(); // $a 
  $reflectedProperty->setValue(123); // $a :$a = 123;
}


上記の方法は静的属性に対して依然として有効である.
これにより,プライベートメソッドや属性のテストが瞬時に容易になるのではないかと感じる.
付:PHPunitテストプライベートメソッド(英語原文)
This article is part of a series on testing untestable code:
  • Testing private methods
  • Testing code that uses singletons
  • Stubbing static methods
  • Stubbing hard-coded dependencies

  • No, not those privates. If you need help with those, this book might help.
    One question I get over and over again when talking about Unit Testing is this:
    "How do I test the private attributes and methods of my objects?"
    Lets assume we have a class Foo:
    
    bar = $this->doSomethingPrivate();
      }
      private function doSomethingPrivate()
      {
        return 'blah';
      }
    }
    ?>
    

    Before we explore how protected and private attributes and methods can be tested directly, lets have a look at how they can be tested indirectly.
    The following test calls the testDoSomething() method which in turn calls thedoSomethingPrivate() method:
    
    assertEquals('blah', $foo->doSomething());
      }
    }
    ?>
    
    

    The test above assumes that testDoSomething() only works correctly whentestDoSomethingPrivate() works correctly. This means that we have indirectly testedtestDoSomethingPrivate(). The problem with this approach is that when the test fails we do not know directly where the root cause for the failure is. It could be in eithertestDoSomething() or testDoSomethingPrivate(). This makes the test less valuable.
    PHPUnit supports reading protected and private attributes through thePHPUnit_Framework_Assert::readAttribute() method. Convenience wrappers such asPHPUnit_Framework_TestCase::assertAttributeEquals() exist to express assertions onprotected and private attributes:
    
    assertAttributeEquals(
         'baz', /* expected value */
         'bar', /* attribute name */
         new Foo /* object     */
        );
      }
    }
    ?>
    
    

    PHP 5.3.2 introduces the ReflectionMethod::setAccessible() method to allow the invocation of protected and private methods through the Reflection API:
    
    setAccessible(TRUE);
        $this->assertEquals(
         'blah', $method->invoke(new Foo)
        );
      }
    }
    ?>
    
    

    In the test above we directly test testDoSomethingPrivate(). When it fails we immediately know where to look for the root cause.
    I agree with Dave Thomas and Andy Hunt, who write in their book "Pragmatic Unit Testing":
    "In general, you don't want to break any encapsulation for the sake of testing (or as Mom used to say, "don't expose your privates!"). Most of the time, you should be able to test a class by exercising its public methods. If there is significant functionality that is hidden behind private or protected access, that might be a warning sign that there's another class in there struggling to get out."
    So: Just because the testing of protected and private attributes and methods is possible does not mean that this is a "good thing".
    参考文献:
    http://php.net/manual/en/class.reflectionmethod.php
    PHPに関する内容についてもっと興味のある読者は、「PHPエラーと異常処理方法の総括」、「php文字列(string)用法の総括」、「PHP配列(Array)操作技術大全」、「PHP演算と演算子用法の総括」、「PHPネットワークプログラミング技術の総括」、「PHP基本文法入門教程」、「php対象向けプログラム設計入門教程」および「php優秀開発フレームワークの総括」を参照してください.
    ここで述べたことが皆さんのPHPプログラム設計に役立つことを願っています.