Yii 2.0 Testing Examples
Saving to Database

Add records to a table using any of these:

$tblUser = Yii::$app->db->schema->getRawTableName(app\models\User::tableName());
$this->tester->haveInDatabase($tblUser, [
    'username'      => 'test',
    'email'         => 'jdoe@example.com',
    'phone'         => '407-555-4444',
    'first_name'    => 'John',
    'last_name'     => 'Doe',
    'password_hash' => '$2y$13$GU0atvXcHvtszSoOgW3o/OB1WGSYh244IgAjMVDi16wzb8M0l5paS',
    'auth_key'      => '0d5QBmVsdb_HDRILGZQ_marAMHUMShNJ',
    'access_token'  => '103-token',
    'role'          => 10,
    'status'        => 0,
]);
$user_id = $this->tester->haveRecord('app\models\User', ['username' => 'admin']);   // Using ORM      

Update database records:

$tblUser = Yii::$app->db->schema->getRawTableName(app\models\User::tableName());
// Updates user record to be used
$this->tester->updateInDatabase($tblUser, ['status' => 0], ['username' => 'demo']);

Check records in a table using any of these:

$this->tester->seeInDatabase('price', ['item_code' => 'TABLE_BLACK']);
$this->tester->seeRecord(    'app\models\Price', ['description' => 'Black Table']);  // Using ORM
$this->tester->dontSeeRecord('app\models\Price', ['description' => 'Red Table']);    // Using ORM      

Example:

<?php
namespace models;
 
use app\models\Price;
 
class PriceTest extends \Codeception\Test\Unit
{
    use \Codeception\Specify;
 
    private $model;
 
    /**
     * @var \UnitTester
     */
    protected $tester;
 
    protected function _before()
    {
        Price::deleteAll(['description' => 'Octane BTE 4']);
        Price::deleteAll(['description' => 'Octane 4']);
 
        $this->model = new Price();
        $this->model->item_code         = 'BTEO4';
        $this->model->description       = 'Octane BTE 4';
        $this->model->cost              = 100.00;
        $this->model->msrp              = 1500.00;
        $this->model->price             = 150.00;
        $this->model->price_volume      = 140.00;
        $this->model->warranty_1yr      = '20';
        $this->model->warranty_2yr      = '40';
        $this->model->warranty_included = '';
        $this->model->type              = 'Product';
        $this->model->category          = 'BTE';
    }
 
    protected function _after()
    {
    }
 
    public function testSavingPrice()
    {
        $this->model->save();
 
        // Verify data was saved using framework methods
        $this->tester->seeInDatabase('price', ['item_code' => 'BTEO4', 'description' => 'Octane BTE 4', 'cost' => 100.00]);
        //$this->tester->seeInDatabase('price', ['item_code' => 'BTEO4']);
        $this->tester->seeRecord(    'app\models\Price', ['description' => 'Octane BTE 4']);     // Checks that record exists in database
        $this->tester->dontSeeRecord('app\models\Price', ['description' => 'Octane 4']);         // Checks that record does not exist in database
    }
 
    function testRecordCanBeChanged()
    {
        // Create an Price record from framework.  Price will be deleted after the test.
        $id = $this->tester->haveRecord('app\models\Price', [
            'item_code'   => 'BTEO66',
            'description' => 'Octane 6',
            'price'       => 200,
        ]);
        $this->assertNotEquals($id, null);
        $this->assertNotNull($id);
 
        // Access model
        $price = \app\models\Price::find()->where(['id' => $id])->one();
        //codecept_debug("Price found: " . print_r($price, true));
        $price->item_code = 'BTEO6';
        $price->save();
        $this->assertEquals('BTEO6', $price->item_code);
 
        // Verify data was saved using framework methods
        $this->tester->seeRecord(    'app\models\Price', ['item_code' => 'BTEO6']);
        $this->tester->dontSeeRecord('app\models\Price', ['item_code' => 'BTEO66']);
    }
    //...
}    
Comments

Use amGoingTo, expect, expectTo to make test more descriptive:

$I->amGoingTo('query the customer info using his phone number');
$I->expectTo('see query result');
$I->expect('good results');
Users
// Login
$I->amLoggedInAs(\app\models\User::findByUsername('admin'));
$I->amOnPage(['site/index']);
$I->see('Logout');
 
// User Details
$user = \app\models\User::findByUsername('test');
$I->amOnPage(['user/view', 'id' => $user->id]);
 
// Logout
\Yii::$app->user->logout();
$I->amOnPage(['site/index']);
$I->see('Signup');
$I->see('Login');
Forms
public function signupNewUser(\FunctionalTester $I)
{
    $faker = Faker\Factory::create();
    $username = $faker->userName;
 
    $I->expectTo('Sign up new user');
 
    \Yii::$app->user->logout();
    $I->amOnPage(['site/index']);
    $I->see('Signup');
    $I->click('Signup');
 
    $I->seeCurrentUrlMatches('/user(.+)signup/');
    $I->see('Signup', 'h1'); 
    $I->fillField(['name' => 'SignupForm[username]'], $username);
    $I->fillField(['name' => 'SignupForm[password]'], 'testing');
    $I->fillField(['name' => 'SignupForm[first_name]'], $faker->firstName);
    $I->fillField(['name' => 'SignupForm[last_name]'], $faker->lastName);
    $I->fillField(['name' => 'SignupForm[email]'], $faker->email);
    $I->fillField(['name' => 'SignupForm[phone]'], $faker->phoneNumber);
    $I->click('Signup', 'button');  // button
 
    $I->seeCurrentUrlMatches('/(.+)index(.+)/');
    $I->see("Logout ({$username})");   // user
    $I->dontSee('Sign up as a user to get exclusive access to information.');
    $I->dontSee('Cannot be blank.');
    $I->dontSee('has already been taken.');
    $I->dontSeeCurrentUrlMatches('/user(.+)signup/');
 
    // logout
    \Yii::$app->user->logout();
    $I->amOnPage(['site/index']);
    $I->see('Signup');
    $I->see('Login');
}    

With fields, you can fill them in several says, all meaning the same thing:

// All equivalent (input box)
$I->fillField('input',   ['name' => 'UserSearch[username]'], 'demo');
$I->fillField(['name' => 'UserSearch[username]'], 'demo');
$I->fillField('UserSearch[username]', 'demo');
$I->fillField('#user-username', 'demo');
$I->fillField('#myformname input=[UserSearch[username]]', 'demo');
$I->fillField('input=[UserSearch[username]]', 'demo');
$I->fillField(['id' => 'user-username'], 'demo');
$I->fillField('input[id=user-username]', 'demo');
 
// All equivalent (selection box)
$I->seeOptionIsSelected('form select[id=user-status]', 'inactive');      // status: inactive
$I->seeOptionIsSelected('select[id=user-status]', 'inactive');           // status: inactive
$I->seeOptionIsSelected('#user-status', 'inactive');                     // status: inactive
Debug
// Access model
$entry = \app\models\Entry::find()->where(['id' => $id])->one();
codecept_debug("find a value in " . print_r($entry, true));  // debug