Yii-User-Management And Unit Tests

Hello,

I’m having a quite remarkable problem. I am building unit tests for my app, and specifically for Yii User Management scripts so that I may better understand how it works. Now I have a unit test file that works well, called RoleModuleTest.php, and another that has errors, called AppControllerTest.php. The error in AppControllerTest is in the setUp() method- so it fails in all six tests I have built into the file so far. The error looks like this:





EEEEEE..........


Time: 0 seconds, Memory: 23.25Mb


There were 6 errors:


1) AppControllerTest::testYumUser

include(YumUserIdentity.php): failed to open stream: No such file or directory


/home/dhimes/public_html/studyswami/yiiroot/framework/YiiBase.php:423

/home/dhimes/public_html/studyswami/yiiroot/framework/YiiBase.php:423

/home/dhimes/public_html/studyswami/studyswami/protected/tests/unit/AppControllerTest.php:59


(and 5 more errors just like this- one for each test)



If fails on line 59, which is (full code will be posted below):




$this->identity = new YumUserIdentity('dan','danpw');



On the other hand, the test file RoleModuleTest.php works fine.

Yii(?) can’t find the YumUserIdentity.php file when running the test AppControllerTest.php. But, here’s the kicker: I made the AppControllerTest.php file by copying the RoleModuleTest.php file, as I built the RoleModuleTest.php file first (in an attempt to understand the YUM stuff in isolation before testing how it works with my app). So, the setup is identical in the two files, yet it fails in one and works in the other[1].

Here is RoleModuleTest.php, which works fine. I’m leaving in everything, even useless comments that remind me about the tests and stuff, just so there’s nothing overlooked.




<?php

    /**********  phpunit assertions

    TODO:  put the list in here (from Assert.php in the phpunit framework)

    arg order:  expected,actual

    assertArrayHasKey()

    assertClassHasAttribute()

    assertClassHasStaticAttribute()

    assertContains()

    assertContainsOnly()

    assertContainsOnlyInstancesOf()

    assertCount()

    assertEmpty()

    assertEqualXMLStructure()

    assertEquals()

    assertFalse()

    assertFileEquals()

    assertFileExists()

    assertGreaterThan()

    assertGreaterThanOrEqual()

    assertInstanceOf()

    assertInternalType()

    assertJsonFileEqualsJsonFile()

    assertJsonStringEqualsJsonFile()

    assertJsonStringEqualsJsonString()

    assertLessThan()

    assertLessThanOrEqual()

    assertNull()

    assertObjectHasAttribute()

    assertRegExp()

    assertStringMatchesFormat()

    assertStringMatchesFormatFile()

    assertSame()

    assertSelectCount()

    assertSelectEquals()

    assertSelectRegExp()

    assertStringEndsWith()

    assertStringEqualsFile()

    assertStringStartsWith()

    assertTag()

    assertThat()

    assertTrue()

    assertXmlFileEqualsXmlFile()

    assertXmlStringEqualsXmlFile()

    assertXmlStringEqualsXmlString()


    **********/

Yii::import('application.modules.user.models.*');

Yii::import('application.modules.user.controllers.*');

Yii::import('application.modules.registration.models.*');

Yii::import('application.modules.registration.controllers.*');


class RoleModuleTest extends CDbTestCase{


    public $identity;

    public $webUser;

    public $session;


    public function setUp(){

        $this->identity = new YumUserIdentity('dan','danpw'); // this is line 59

        $this->webUser = new YumWebUser();

        $this->webUser->setID($this->identity); 

        $this->session = Yii::app()->getSession();

        $this->session->open();

        // Does more than authenticate- also sets the state of the user.  That's

        // why we have to do it before logging in!

        $this->assertTrue($this->identity->authenticate());

        // After authenticating, can log in

        $this->assertTrue($this->webUser->login($this->identity));

        parent::setUp();

        }


    public function testYumUser(){

        // testing

        $this->assertEquals(2, Yii::app()->user->id);

        $this->assertEquals('student', trim(Yii::app()->user->getRoles()));

        }

        

    public function testSetOtherUserData(){

        $user = Yii::app()->user;

        $id = $user->id;

        $this->assertEquals(2, $id);

        }


    public function testHasRole(){

        $user = Yii::app()->user;

        $this->assertTrue($user->hasRole('student'));

        $this->assertFalse($user->hasRole('Student'),' Is capitalization important? ');

        $this->assertFalse($user->hasRole('firefighter'),'roles are '.$user->getRoles());

        }


    public function testHasSessionRole(){

        $this->assertEquals('student',$this->session['role']);

        $this->assertTrue('student'==$this->session['role']);

        $this->assertFalse('teacher'==$this->session['role']);

        $this->assertFalse('parent'==$this->session['role']);

        }


    public function testIsStudent(){

        //$this->assertTrue(Yii::app()->user->isStudent(),' Do we have an isStudent method? ');

        }

}



Here is the problematic part of AppControllerTest.php- again leaving in the unimportant stuff so that you can see that they are identical(!!).




<?php

    /**********  phpunit assertions

    TODO:  put the list in here (from Assert.php in the phpunit framework)

    arg order:  expected,actual

    assertArrayHasKey()

    assertClassHasAttribute()

    assertClassHasStaticAttribute()

    assertContains()

    assertContainsOnly()

    assertContainsOnlyInstancesOf()

    assertCount()

    assertEmpty()

    assertEqualXMLStructure()

    assertEquals()

    assertFalse()

    assertFileEquals()

    assertFileExists()

    assertGreaterThan()

    assertGreaterThanOrEqual()

    assertInstanceOf()

    assertInternalType()

    assertJsonFileEqualsJsonFile()

    assertJsonStringEqualsJsonFile()

    assertJsonStringEqualsJsonString()

    assertLessThan()

    assertLessThanOrEqual()

    assertNull()

    assertObjectHasAttribute()

    assertRegExp()

    assertStringMatchesFormat()

    assertStringMatchesFormatFile()

    assertSame()

    assertSelectCount()

    assertSelectEquals()

    assertSelectRegExp()

    assertStringEndsWith()

    assertStringEqualsFile()

    assertStringStartsWith()

    assertTag()

    assertThat()

    assertTrue()

    assertXmlFileEqualsXmlFile()

    assertXmlStringEqualsXmlFile()

    assertXmlStringEqualsXmlString()


    **********/

Yii::import('application.modules.user.models.*');

Yii::import('application.modules.user.controllers.*');

Yii::import('application.modules.registration.models.*');

Yii::import('application.modules.registration.controllers.*');


class AppControllerTest extends CDbTestCase{


    public $identity;

    public $webUser;

    public $session;


    public function setUp(){

        $this->identity = new YumUserIdentity('dan','danpw'); // this is line 59

        $this->webUser = new YumWebUser();

        $this->webUser->setID($this->identity); 

        $this->session = Yii::app()->getSession();

        $this->session->open();

        // Does more than authenticate- also sets the state of the user.  That's

        // why we have to do it before logging in!

        $this->assertTrue($this->identity->authenticate());

        // After authenticating, can log in

        $this->assertTrue($this->webUser->login($this->identity));

        parent::setUp();

        }


    public function testYumUser(){

        // testing

        $this->assertEquals(2, Yii::app()->user->id);

        $this->assertEquals('student', trim(Yii::app()->user->getRoles()));

        }


(remainder of file not posted for brevity)



So, for completeness, here is my dir tree under protected/tests




 $tree

.

├── bootstrap.php

├── fixtures

├── functional

│   ├── debug_multipart_answer

│   ├── Interview_Selenium

│   ├── SiteTest.php

├── phpunit.xml

├── report

├── unit

│   ├── AppControllerTest.php

│   ├── AssignmentModelControllerTest.php

│   ├── DbTest.php

│   ├── HelpControllerTest.php

│   ├── HelpDirFilesTest.php

│   ├── RegistrationTest.php

│   └── RoleModuleTest.php

└── WebTestCase.php




And, here are permissions:




 $ll

total 36

-rwxr-xr-x 1 dhimes dhimes 6667 2013-05-06 10:13 AppControllerTest.php

-rwxr-xr-x 1 dhimes dhimes 1334 2012-11-27 17:47 AssignmentModelControllerTest.php

-rwxr-xr-x 1 dhimes dhimes  177 2012-11-01 10:34 DbTest.php

-rwxr-xr-x 1 dhimes dhimes 1934 2012-11-28 15:02 HelpControllerTest.php

-rwxr-xr-x 1 dhimes dhimes 2052 2012-11-29 08:15 HelpDirFilesTest.php

-rwxr-xr-x 1 dhimes dhimes 6353 2013-05-02 16:02 RegistrationTest.php

-rwxr-xr-x 1 dhimes dhimes 3271 2013-05-06 09:15 RoleModuleTest.php




And, in case it’s important, AppController.php is under


 protected/controllers/AppController.php 

while all of the YUM stuff is under


 /protected/modules 

Just to check, I changed the name of AppControllerTest.php to AppTest.php, and the name of the class to AppTest, but it still failed.

Also, I must confess that I don’t understand all of the behind-the-scenes magic that Yii works (hence the test I just mentioned- ‘just in case’).

Thank you so so so much for any time you may have to look at this. Hopefully it’s obvious to you, but it’s driving me nuts!

[1] The entire point of working in a field like computers instead of with people is to avoid irrational behavior like this! ;D

Well, I’ve learned this much: The phpunit tests are run in alphabetical order by filename. The first one, AppControllerTest.php, fails because the files application.modules.user.components.* aren’t loaded. That is, adding this line to the import statements


Yii::import('application.modules.user.components.*'); 

makes everybody happy. However, this is not needed by the time the tests in the last file are executed- something between has forced these files to be loaded.

I just wish I knew what kind of magic is forcing these files to be loaded.

My config/main.php is set up with this


'user'=>array(

      'class' => 'application.modules.user.components.YumWebUser',



which I understood to mean that YumWebUser would be loaded when the app started.

I can’t just call ‘new YumWebUser()’ to start the app- that’s what’s throwing the error. I wonder: what is starting the app and auto loading YumWebUser?

When this test runs (code below) first, all is well. If not, I have to specifically import user.components.*

It turns out that the critical line in the code below is




$user = new YumRegistrationForm;



in


 public function testValidation()

For whatever reason, this line auto loads the components. Without it, the tests fail.

Here is the test code in full:




<?php

   

Yii::import('application.modules.user.models.*');

Yii::import('application.modules.user.controllers.*');

Yii::import('application.modules.registration.models.*');

Yii::import('application.modules.registration.controllers.*');


class RegistrationTest extends CDbTestCase{


    public function testValidation(){

        Yii::app()->controller = new YumRegistrationController('registration');

        $user = new YumRegistrationForm;

        $session = new CHttpSession;

        $session->open();

        $session['id'] = 2;


        $user->setAttributes(array(

                'username' => 'A_Testuser',

                'password' => 'hiddenpassword1', 

                'verifyPassword' => 'hiddenpassword1', 

                ));

        $this->assertTrue($user->validate());


        $user->setAttributes(array(

                'username' => 'daniel', // This works too

                'password' => 'user12xr453', 

                'verifyPassword' => 'user12xr453', 

                ));

        $this->assertTrue($user->validate());


        $user->setAttributes(array(

                'username' => 'dan',  // user name too short

                'password' => 'user12xr453', 

                'verifyPassword' => 'user12xr453', 

                ));

        $this->assertFalse($user->validate());


        $user->setAttributes(array(

                'username' => 'dan iel', // no white space allowed in username

                'password' => 'user12xr453', 

                'verifyPassword' => 'user12xr453', 

                ));

        $this->assertFalse($user->validate());


        $user->setAttributes(array(

                'username' => '[\(danl', // no funky db-clearing shit in username

                'password' => 'user12', 

                'verifyPassword' => 'user12', 

                ));

        $this->assertFalse($user->validate());

        }


}