2013-06-24 18 views
10

最近、PHPUnitに飛びついて、将来のプロジェクトのテストを書く上で快適になるためにいくつかの例を試してみました。PHPUnit:オブジェクトの配列をテスト

私はこのようなものです学生クラス持って、このシナリオをテストする必要があります。今、私は学生クラス返すかどうかをテストする方法

class Students 
{ 
    public function getStudents($studentName, $studentId) 
    {  
     $students= array(); 

     //Instantiating OldStudent Class from Old Project 
     $oldStudents = \OldStudents::getStudentByName($studentName, $studentId); 

     //Create a Student Object for every OldStudent found on Old Project and set 
     //values 
     foreach ($oldStudents as $oldStudent) 
     {    
      $student = new \Entity\Student(); 

      //Set Student ID 
      $student->setStudentId($oldStudent->getStudentID()); 

      //Set Student Name 
      $student->setStudentName($oldStudent->getStudentName());  
      //.....other setters for student data, irrelevant for this example 

      $students[] = $student;    
     } 

     return $students; 
    } 
} 

、学生クラス

Class Student 
{ 
    protected $studentId; 
    protected $studentName; 

    public function getStudentId() 
    { 
     return $this->studentId; 
    } 
    public function setStudentId($studentId) 
    { 
     $this->studentId = $studentId; 
     return $this; 
    } 
    public function getStudentName() 
    { 
     return $this->studentName; 
    } 
    public function setStudentName($studentName) 
    { 
     $this->studentName = $studentName; 
     return $this; 
    } 
} 

を値が設定されたオブジェクトの配列、ゲッターを使用して値を確認する生徒クラス

光線/情報/リンクを投げて、私に正しい経路を指示してください。

ありがとうございました

答えて

24

私は以下のサンプルコードを書いています。 getStudentsへのパラメータはオプションのフィルタであると推測しました。すべての生徒を取得するテストが1つあります。彼らがいつも並べ替え順に戻ってくるかどうかはわかりません。なぜなら、私はStudentクラスで何かをテストしないのです。 2回目のテストでは特定の生徒が1人いて、いくつかの生徒機のテストが始まります。

class StudentsTest extends PHPUnit_Framework_TestCase{ 

    public function testGetAllStudents(){ 
     $s=new Students; 
     $students=$s->getStudents("",""); 
     $this->assertInternalType('array',$students); 
     $this->assertEquals(7,count($students)); 
     $first=$students[0]; //Previous assert tells us this is safe 
     $this->assertInstanceOf('Student',$first); 
    } 

    public function testGetOnlyStudentNamedBob(){ 
     $s=new Students; 
     $students=$s->getStudents("Bob",""); 
     $this->assertInternalType('array',$students); 
     $this->assertEquals(1,count($students)); 
     $first=$students[0]; //Previous assert tells us this is safe 
     $this->assertInstanceOf('Student',$first); 
     $this->assertEquals('Bob',$first->getStudentName()); 
    } 
} 

これは良い第一歩です。あなたがしばらくそれを使用した後、それは非常に壊れやすいことに気づくでしょう。私。最初のテストに合格するには、正確に7人の学生がいなければなりません。 2人目が合格するには、ボブと呼ばれる生徒が1人いなければなりません。 \OldStudents::getStudentByNameがデータベースからデータを取得している場合は、それも遅くなります。単体テストをできるだけ早く実行したいと考えています。

これらの両方の修正は、コールを\OldStudents::getStudentByNameに偽装することです。その後、独自の人工データを注入することができます。その後、ロジックはgetAllStudentsでのみテストされます。これは、あなたのユニットテストが壊れたときに、あなたがそれを壊した可能性のあるラインがわずか20ほどあることを意味します。

モッキングを行う方法はまったく問題ではなく、PHPのバージョンとコード設定の柔軟性に左右されます。

+0

こんにちはダーレン、あなたは本当にレガシーコードであり、私はそれに触れることはできません "OldStudents"と絶対に正しいです。あなたのサンプルコードをありがとう。私は両方のあなたが満足のいく返答を与えたので、私はupvoteしたい答えに修理でIm: – 125369

+1

まあ、あなたはそれに勝つ! – 125369

3

アサーションで行うことができます。まず、実際にという結果を得てから、いくつかのアサーションを実行する必要があります。比較:

をあなたはそれが配列であることを主張することができます

class InternalTypeTest extends PHPUnit_Framework_TestCase 
{ 
    public function testFailure() 
    { 
     $this->assertInternalType('array', 42); 
    } 
} 

その後、あなたはそれが空でないことを主張することができ(あなたが知っているように、それはいくつかのデータを返す必要があります) :

class NotEmptyTest extends PHPUnit_Framework_TestCase 
{ 
    public function testFailure() 
    { 
     $this->assertNotEmpty(ARRAY()); 
    } 
} 

次に、各値が学生タイプ:

class InstanceOfTest extends PHPUnit_Framework_TestCase 
{ 
    public function testFailure() 
    { 
     $this->assertInstanceOf('Student', new Exception); 
    } 
} 

これはあなたにいくつかの指針を与えることを望みます。一般的なアサーションのリストについては、上のリンクを参照してください。 IDEを使用してテストを実行する場合は、すべてのアサーションのリストも提供する必要があります。

10

バージョン3.1.4以降のPHPUnitでは、 "type"パラメータを持つアサーション "assertContainsOnly"があります。これは、すべてのPHPタイプをアサートすることができます(これには、以下が含まれます)。インスタンスおよび内部型)、バージョン3.7以上では、明示的にのみPHP変数型ではなくクラスインスタンスを確認するアサーション "assertContainsOnlyInstancesOf"があります。

したがってアレイは、所与のタイプのオブジェクトのみを含んでいるかどうかをチェックテストは単純である:

$this->assertContainsOnlyInstancesOf('Student', $students); 

注このチェックが暗黙$studentsはアレイまたはTraversableのインターフェースを実装するオブジェクトのいずれかであることをテストすること。 Traversableを実装してもカウントできるわけではありませんので、Studentオブジェクトが存在することを保証するために後でassertCountを呼び出しても成功するとは限りませんが、戻り値が配列であるという追加チェックはあまりにも盛り上がりそうです。あなたは配列を何かを使って作成して返しています - あなたがそれを数えることができると想定するのは安全です。しかし、これはどこにでも当てはまらないかもしれません。

+0

この関数は実際には 'assertContainsOnlyInstancesOf()'です(インスタンスは複数でなければなりません)。 – kielabokkie

+0

そのタイプミスを発見してくれてありがとう - オートコンプリートの怠惰がおそらく私に当たったでしょう。このようなタイプミスは自由に編集してください。彼らは待ち行列に入り、見直され、元の著者に通知されます。そうすれば、間違った情報を簡単に更新できます。 – Sven

+0

私はそれを試みましたが、2文字しか変更しなかったので受け入れられません;) – kielabokkie

関連する問題