Codeception Testing with Yii Framework 2.0 [Day 4]

Today’s Objective

As a user I would like to create a new unit test, implement it and test it.

Today’s Method

Yesterday’s method was rather successful, of course today I don’t have already made steps. Instead I’ll be putting each step in as a heading and the text inside each of those headings will give details on that action.

Actions

Create new unit test(s)

Using the examples from Yii basic template, I created the following “ModelTest.php” in ~\tests\codeception\unit\models:

<?php

namespace tests\codeception\unit\models;

use Yii;
use yii\codeception\TestCase;
use app\models\Model;
use Codeception\Specify;

class ModelTest extends TestCase
{
 use Specify;

 protected function tearDown()
 {
   parent::tearDown();
 }

 public function testModelString()
 {
   $model = new Model();

   $this->specify('model string function should return a string', function () use ($model) {
     expect('function should return string', $model->string())->string();
   });
 }

 public function testModelBoolean()
 {
   $model = new Model();

   $this->specify('model bool function should return a boolean opposite to boolean passed', function () use ($model) {
     expect('argument is true, result should be false', $model->bool(true))->false();
     expect('argument is false, result should be true', $model->bool(false))->true();
   });
 }

 public function testModelArray()
 {
   $model = new Model();

   $this->specify('comma seperated string should return array of items', function () use ($model) {
     expect('passing "dave,joe" should return array with ["dave","joe"]', $model->getArray("dave,joe"))->array(['dave','joe']);
     expect('execution with no argument should return empty array', $model->getArray())->array();
   });
 }

}

I really need to set up a code box for this blog… possibly a job for another daily-blog. (Edit 15/04/15: I downloaded Code Highlight plugin, which highlights code but doesn’t do everything I’d like it to do… but it’ll do for now). Anyway, what I’ve decided to do is make a Model model class and in it have functions to return different types of data and this unit test is set up to check that those functions do what they are supposed to:

  • string() – returns a string
  • bool() – returns a boolean opposite to the one passed to it
  • array() – returns an exploded comma separated string

On running my new unit test (From the tests folder in codeception-test):

codecept run unit models/ModelTest

It crashed completely with the error that “Class ‘app\models\Model’ not found”, which is completely expected since I haven’t made the Class yet. And to my understanding is how Unit testing in general is supposed to work, so let’s move to the next action on this list.

Create “Model” class for codeception-test

At this step is where I realised that Model is an already made class (yii\base\Model) for Yii Framework…. technically this is a big no-no, but since this isn’t for any sort of production I’ll carry on without going back and editing everything to “MySimpleModel”, which it should be named. Taking this as an educational play with namespaces in PHP ;)

Which proved very educational.

I created the model Model (app\models\Model) and on attempting to run my unit test I was informed that PHP cannot declare my class because the name is already in use.

I’m taking this as a 2 part lesson:

  1. Namespace does not allow for scoping class names (Which should be something I should already know, but I have my noob moments :) ).
  2. This points out to me how useful unit testing is… I know in theory how much it could help, but this was a practical lesson for me :)

So, I will rename my model as I mentioned earlier but leave in the original part of this post for posterity. So, renamed ModelTest.php to MySimpleModelTest.php and updated it to use MySimpleModel.

This what I have in ~\models\MySimpleModel.php

<?php

namespace app\models;

use Yii;
use yii\base\Model;

/**
 * Model is a model to test out unit testing.
 */
class MySimpleModel extends Model
{
 /**
 * Function to return a string
 * @param string $param
 * @return string
 */
 public function string($param = "string")
 {
   return $param;
 }

 /**
 * Function to return opposite of parameter
 * @param boolean $param
 * @return boolean opposite of $param
 */
 public function bool($param)
 {
   return !$param;
 }

 /**
 * return array of CSV string
 * @return User|null
 */
 public function getArray($csv_string)
 {
   return explode(',', $csv_string);
 }
}

Execute unit test(s)

With everything set up to use MySimpleModel, I executed my unit test and found that my initial thought that the following code:

$this->specify('model string function should return a string', function () use ($model) {
 expect('function should return string', $model->string())->string();
});

Would check for a string, was completely off base.

Foolish, but educational process. After reading through documentation on unit tests from Codeception and some documentation on PHPUnit I decided to go with the following:

$this->assertInternalType('string', $model->string());

Since I only want to know that the returned value is a string it works in this instance, but the experience and brief reading through links above has shown me that there’s a whole world of possibilities that I should learn before I can say that I’m at most “decent” with unit testing in Yii Framework.

The testModelBoolean() test went off without a hitch, and I’m not completely sure why. By that I mean that I have no idea how the expect method works, which requires further analysis.

And testModelArray() test fails, which is very true, since I didn’t name my model’s function “array()” because of a naming issue. Instead I named it “getArray()”. Although even with that correction I do not believe that my unit test will bare fruit due to the initial issue I had with string.

Think I will close off on that note, with a rather nice objective for tomorrow :)

Tomorrow’s Objective

As a user…. I’m gonna stop this “As a user…” thing. It’s agile and all that, but I don’t think it will be worthwhile in the long run of this experiment. So just going to list upcoming objectives that I can think of in order of decided priority on the day and pick one for the next day (If there are multiples).

Upcoming Objective(s)

  1. Update testModelArray() unit test to confirm that returned object is an array with correct values
  2. Explore and understand the basic functions of basic test methods (Understand what is going on in testModelBoolean() function to be precise).
  3. Try to use the entire $I->wantTo(‘load all values’); style of Codeception

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>