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

Codeception Testing with Yii Framework 2.0 [Day 3]

Today’s Objective

As a user I would like to run tests on the basic template for Yii Framework. (Continued)

Today’s method

Going to use the instructions from the yii2 basic template (after everything set up from yesterday) and just add any notes of my own or any issues I run into.

Instructions from basic template

Install faker extension by running the following from template root directory where “composer.json” is:

composer require --dev yiisoft/yii2-faker:*

Template root directory in this instance is “C:\wamp\www\codeception-test”

Create “yii2_basic_tests” database and update it by applying migrations:

codeception/bin/yii migrate

Ran into an error when trying to execute this instruction. My thought is that it’s only necessary if my application used the database (Which isn’t the case for the basic template). But this points out that I should learn how to properly use migrations for Yii Framework.

 

Very nifty to be able to set up a test database with a simple execution, think this will be another tutorial/learning series after this one.

Build the test suites:

codecept build

Executed from C:\wamp\www\codeception-test\tests

In order to be able to run acceptance tests you need to start a webserver. The simplest way is to use PHP built in webserver. In the “web” directory execute the following:

php -S localhost:8080

Since I already have a webserver set up, I chose to skip this step and instead set up the tests to use my webserver instead by editing

C:\wamp\www\codeception-test\tests\codeception.yml

replace

http://localhost:8080/index-test.php

to

http://localhost/codeception-test/web/index-test.php

There’s a way to remove the “web” part out of that, which I have, but it’s out of scope for this… possibly later ;)

Now you can run the tests with the following commands:

# run all available tests
codecept run
# run acceptance tests
codecept run acceptance
# run functional tests
codecept run functional
# run unit tests
codecept run unit

Found that acceptance tests failed, but functional and unit tests completed successfully. Believe the issue with my acceptance tests is thanks to a configuration setting and not using PHP built in webserver.

 

Needed to edit

C:\wamp\www\codeception-test\tests\codeception\acceptance.suite.yml

replace

http://localhost:8080

to

http://localhost/codeception-test/web

Conclusion

Hurrah! We’ve successfully run tests on the basic template for Yii Framework. With that completed there are a few questions I have:

  1. Is there a way to execute tests and view results from a browser? The reason for this question is thanks to the following:
    • Don’t enjoy the idea of executing command line arguments after each change
    • Don’t like the output from windows command line, believe it would look better in unix… but I’m not using unix.
  2. What’s the best practice for unit tests?
    • Does it entail testing function calls on model only, or controller and model. Believe this will be answered with a look into the current tests provided.
  3. What’s the best practice for acceptance/functional tests?
    • This is more my lack of understanding for the process than anything else and requires further education

And that’s about it. With those questions I can make an objective for tomorrow :)

Tomorrow’s Stumble

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

Codeception Testing with Yii Framework 2.0 [Day 2]

Today’s Objective

As a user I would like to run tests on the basic template for Yii Framework.

Prerequisites

I have a few things already set up that I would like to state for the record:

Installing Basic Yii Template

With those items installed, let’s begin with installing Yii (Thorough instructions here).

First we inform composer of the required global package we will need (Only need to do this once)

composer global require "fxp/composer-asset-plugin:1.0.0"

Then we create the project (using Yii’s basic template), you should run this command in your www folder of WampServer (For me it’s C:\wamp\www)

composer create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic codeception-test

The last piece of that is the project name, in this case it’s ‘conception-test’ and now I have a folder codeception-test in C:\wamp\www, and Yii is installed!

Installing Codeception

With Yii up and running, we’ll need Codeception installed to execute tests:

composer global require "codeception/codeception=2.0.*"
composer global require "codeception/specify=*"
composer global require "codeception/verify=*"

With Codeception downloaded, we need to be able to run it from the command line by adding the path of Composer’s global vendor\bin directory, to get Composer’s global director we run the following:

composer global status

That command shows the following:

Changed current directory to C:/Users/<user>/AppData/Roaming/Composer

Now we add “C:\Users\<user>\AppData\Roaming\Composer\vendor\bin” to PATH for Windows Advanced system settings. Once done you should be able to run the following without an error:

codecept

You may need to restart your command line session for the changes to take effect.

Conclusion

Alrightey, we now have Codeception set up for use and a basic Yii application set up to execute tests on. I would’ve liked to at least execute a test by now, but haven’t made a lot of progress with this current method of describing/detailing the process involved. Think I will be making it far more shorthand in future posts and actually complete the objective before writing.

Signing off for now, the objective should be done tomorrow ;)

 

Codeception Testing with Yii Framework 2.0 [Day 1]

Introduction

I’ve been moving into developing Web applications/sites from scratch over using WordPress, and the framework that I’ve committed a good portion of time to learning has been the Yii Framework. Which has proved to be completely worth it, but this post is not about how awesome Yii Framework is… I’m creating this post because there’s one area I’ve found to be lacking in my education and that is using Codeception for testing my projects. There are a lot of articles out there of how to install/use codeception, but these all seem to leave me more confused than anything.

And so I’ve decided to publish my stumbling around the topic in a daily blog so I can better understand it and hopefully help somebody else better understand it too.

P1030362-Edit-Edit

How it’s going to work

I’ve found that aimless stumbling has rather poor results, so I’m putting myself on a more focused approach using this blog. I’ll be updating daily on what I’ve done during that day to progress my understanding of the subject at hand (Namely Codeception testing for Yii Framework 2.0, but I might do this with a few other topics as well). Once updated for the day a goal for the next day will be made and the cycle repeats until the job is done. A sort of agile/scrum approach to learning.

Tomorrow’s Stumble

As a user I would like to run tests on the basic template for Yii Framework.