Codeception Testing with Yii Framework 2.0 [Day 13]

Today’s Objective(s)

  1. Write a new acceptance test
  2. Research best practices for acceptance/functional testing in Yii

Introduction

So today we write a new acceptance test. Nothing complicated, I just want to create a basic acceptance test to confirm a page shows the text ‘Hello’ and has a text field. And text inserted into the text field will be appended to the ‘Hello’ string.

The Acceptance Test

Made HelloCept.php in ~\tests\codeception\acceptance :

<?php

/* @var $scenario Codeception\Scenario */

$I = new AcceptanceTester($scenario);
$I->wantTo('ensure that say page displays "Hello"');
//$I->amOnPage(\yii\helpers\Url::to(['say/index'])); (Hoped to use this, but doesn't work)
$I->amOnPage('index.php?r=say/index'); //used this for the time being
$I->see('Hello');
$I->amGoingTo('submit form without an input');

$I->fillField('input[name="SayForm[string]"]', '');
$I->click('say-button');

if (method_exists($I, 'wait')) {
    $I->wait(3); // only for selenium
}

$I->see('Hello');
$I->amGoingTo('submit a string');


$I->fillField('input[name="SayForm[string]"]', 'World!');
$I->click('say-button');

if (method_exists($I, 'wait')) {
    $I->wait(3); // only for selenium
}

$I->expectTo('see updated string');
$I->see('Hello World!');

Now to make the controller, model and view for this.

Controller (~\controllers\SayController.php):

<?php

namespace app\controllers;

use Yii;
use app\models\SayForm;

class SayController extends \yii\web\Controller
{
    public function actionIndex()
    {
        $model = new SayForm();

        if (Yii::$app->request->isPost) {
            $model->load(Yii::$app->request->post());
        }

        return $this->render('index',[
            'model' => $model
        ]);
    }

}

Basic controller that will load our model if the request has POST variables (This should be validated, but that’s out of scope :D ).

Model (~\models\SayForm.php):

<?php

namespace app\models;

use Yii;
use yii\base\Model;

/**
 * SayForm is the model to hold hold our string.
 */
class SayForm extends Model
{
    public $string;

    /**
     * simple rule set so that value is "safe"
     * @return array the validation rules.
     */
    public function rules()
    {
        return [
            ['string', 'string'],
        ];
    }

    /**
     * Basic label for string value.
     * @return array customized attribute labels
     */
    public function attributeLabels()
    {
        return [
            'string' => 'Say hello to what?',
        ];
    }
}

Also very basic, just has a public variable named $string which will be used in our view.

View (~\views\say\index.php):

<?php
/* @var $this yii\web\View */

use yii\widgets\ActiveForm;

?>
<h1>say/index</h1>

<p>
    Hello<?= ($model->string ? ' ' . $model->string : '') ?>
</p>
<p>
    <?php $form = ActiveForm::begin(); ?>
    <?= $form->field($model, 'string') ?>
    <?= \yii\helpers\Html::submitButton('Submit', ['id' => 'say-button']) ?>
    <?php ActiveForm::end(); ?>
</p>

Set the submit button to have an id of “say-button” (Since that is the button/link being clicked on in the acceptance test). And we append the string from SayModel to our ‘Hello’ string if there is a string to append.

And the acceptance test passes!

C:\wamp\www\codeception-test\tests>codecept run acceptance HelloCept
Codeception PHP Testing Framework v2.0.12
Powered by PHPUnit 4.5.1 by Sebastian Bergmann and contributors.

←[1mAcceptance Tests (1) ←[22m----------------------------------------------------------------------------------------------------------------
←[35;1mEnsure that say page displays "Hello"←[39;22m (HelloCept) Ok
-------------------------------------------------------------------------------------------------------------------------------------

Now you can see what I mean about ugly outputs ;) But it works, and this does seem to be a very easy method to confirm that pages do what they are supposed to.

I do find myself a bit troubled over complicated scenarios, but think that’s just me overthinking it all. So believe I’ve already thought of my next acceptance test :)

Conclusion

This form of acceptance testing is excellent in my opinion, the test itself is written in such a way that it’s simple to understand at a glance and could become very powerful with the right implementation.

Upcoming Objective(s)

  1. Get acceptance test to pull url without having to hardcode (ie. use a function instead of ‘index.php?r=site/index’)
  2. Write an acceptance test for functionality that uses a session.
  3. Research best practices for acceptance/functional testing in Yii

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>