Codeception trong thực tế

Sử dụng Codeception để kiểm thử mã PHP

Mục tiêu

  • Cài đặt và cấu hình Codeception
  • Viết mã kiểm thử để đơn giản hóa quá trình phát triển và tối đa hóa sự ổn định và khả năng bảo trì

Các loại kiểm thử

1. Kiểm thử đơn vị (Unit Testing - UT)

  • Thực thi một đoạn mã tách biệt khỏi phần còn lại của mã nguồn
  • Đưa ra các khẳng định về hành vi của mã
  • Mô tả các trường hợp sử dụng mong đợi

2. Kiểm thử chức năng (Functional Testing - FT)

  • Gửi yêu cầu đến ứng dụng (từ phía khách hàng)
  • Đưa ra các khẳng định về giá trị trả về
  • Mô tả hành vi mong đợi của ứng dụng
  • Tùy thuộc vào framework

3. Kiểm thử dịch vụ Web

  • Gửi yêu cầu API thông qua HTTP client
  • Đưa ra các khẳng định về giá trị trả về của API
  • Mô tả hành vi của API

Yêu cầu hệ thống

  • PHP 5.4+
  • Mở rộng json
  • Mở rộng mbstring
  • Mở rộng xdebug (để tạo báo cáo độ bao phủ)

Cài đặt và cấu hình xdebug Phiên bản được khuyến nghị: 2.6.1

wget https://pecl.php.net/get/xdebug-2.6.1.tgz
tar xvf xdebug-2.6.1.tgz
cd xdebug-2.6.1
/path/to/phpize
./configure --enable-xdebug
make
make install

Thêm dòng sau vào file php.ini:
zend_extension="/wherever/you/put/it/xdebug.so"

Kiểm tra cài đặt:
php -i | grep xdebug

Cài đặt, cấu hình và chạy Codeception

wget http://codeception.com/codecept.phar # Không cần giải nén

php codecept.phar help # Hiển thị tài liệu trợ giúp
php codecept.phar bootstrap # Tạo thư mục test và file codeception.yml trong thư mục hiện tại
php codecept.phar build # Tạo các lớp cần thiết từ cấu hình, chạy mỗi khi thay đổi cấu hình

php codecept.phar run {suite_name} # Chạy tất cả nếu không chỉ định suite name
php codecept.phar run api ThingTest.php
php codecept.phar run api ThingTest.php:method

Ví dụ cấu hình và mã nguồn Địa chỉ: https://github.com/wdy1184/CodeceptionExampleWithYii2

Định dạng mã kiểm thử Codeception hỗ trợ ba cách viết mã kiểm thử:

  1. Cept: Một file kiểm thử độc lập, có thể chứa một quy trình kiểm thử.
  2. Cest: Một file class, nhiều kiểm thử được viết trong một class.
  3. PHPUnit: Hỗ trợ định dạng của PHPUnit.

Tích hợp với Yii2

Cấu hình: _bootstrap.php

<?php

defined('APP_PATH') or define('APP_PATH', dirname(dirname(__FILE__)));
// Đăng ký tự động tải Composer
// Bao gồm file lớp Yii

require(__DIR__ . '/../../psservice/libs/envFun.php');
require(__DIR__ . '/../../vendor/autoload.php');

// Cấu hình biến môi trường
defined('YII_DEBUG') or define('YII_DEBUG', getYaconfEnv('YII_DEBUG'));
defined('YII_ENV') or define('YII_ENV', getYaconfEnv('YII_ENV'));
defined('YII_ENABLE_ERROR_HANDLER') or define('YII_ENABLE_ERROR_HANDLER', getYaconfEnv('YII_ENABLE_ERROR_HANDLER'));

require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');

// Tương thích ngược với các file cũ
require(__DIR__ . '/../../config/errorCode.php');
require(__DIR__ . '/../../config/constant.php');
Yii::setAlias('@backend', dirname(dirname(__DIR__)) . '/backend');
Yii::setAlias('@console', dirname(dirname(__DIR__)) . '/console');
Yii::setAlias('@psservice', dirname(dirname(__DIR__)) . '/psservice');
Yii::setAlias('@config', dirname(dirname(__DIR__)) . '/config');

$config = require(APP_PATH . '/../config/web.php');

Ví dụ mã Cest

<?php
namespace tests\api;

use backend\models\user\EduOcrTourist;
use backend\models\user\EduOcrUser;
use backend\modules\user\services\UserEntity;
use config\UserCacheKey;
use psservice\models\user\WxEduUser;
use tests\ApiTester;

class UserControllerCest
{
    private $token;

    public function _before(ApiTester $I)
    {
    }

    /**
     * Đăng nhập người dùng
     * @param ApiTester $I
     */
    public function actionLoginTest(ApiTester $I)
    {
        $mobile = '18510473853';
        $token = $I->amUserLogin($mobile);
        $I->sendCommandToRedis('select', getPsYaconfEnv('PS_OCR_SINGLE_REDIS_DATABASE_1'));

        $userRedisInfo = $I->grabFromRedis(sprintf(UserCacheKey::USER_INFO, $token));
        $userRedisInfo = json_decode($userRedisInfo, 1);
        codecept_debug($userRedisInfo);

        $I->assertGreaterThan(0, $userRedisInfo['userId']);
        $I->assertEquals(0, $userRedisInfo['touristUserId']);
        $I->assertEquals(UserEntity::$roleMap['user'], $userRedisInfo['role']);
        $I->assertEquals($mobile, $userRedisInfo['mobile']);

        $I->assertLessOrEquals(10, (time() - strtotime($userRedisInfo['loginTime'])));

        $I->seeRecord(WxEduUser::className(), ['UserId' => $userRedisInfo['commonUserId']]);
    }

    /**
     * Đăng nhập khách
     * @param ApiTester $I
     */
    public function actionTouristLoginTest(ApiTester $I)
    {
        $token = $I->amTouristLogin('6CB7B05E-DE62-415A-96CF-6D57B666F939');
        $I->sendCommandToRedis('select', getPsYaconfEnv('PS_OCR_SINGLE_REDIS_DATABASE_1'));

        $userRedisInfo = $I->grabFromRedis(sprintf(UserCacheKey::USER_INFO, $token));
        $userRedisInfo = json_decode($userRedisInfo, 1);
        codecept_debug($userRedisInfo);

        $I->assertGreaterThan(0, $userRedisInfo['id']);

        $I->seeRecord(EduOcrTourist::className(), ['deviceId' => '6CB7B05E-DE62-415A-96CF-6D57B666F939']);
    }

    /**
     * Đăng xuất
     * @param ApiTester $I
     */
    public function actionLogoutTest(ApiTester $I)
    {
        $this->token = $I->amUserLogin('18510473853');
        $I->sendPOST('/user/user/logout', [
            'token' => $this->token,
            'deviceId' => '6CB7B05E-DE62-415A-96CF-6D57B666F939',
        ]);

        $I->seeResponseContainsJson(['code' => 99999]);
    }

    /**
     * Thông tin người dùng đăng nhập
     */
    public function actionInfoTest(ApiTester $I)
    {
        $mobile = '18510473853';
        $this->token = $I->amUserLogin($mobile);
        $I->sendGET('/user/user/info', [
            'token' => $this->token,
        ]);
        $ret = json_decode($I->grabResponse(), 1);
        $I->seeRecord(EduOcrUser::className(), ['id' => $ret['data']['userId'], 'mobile' => $mobile]);
    }
}

Thêm phương thức tùy chỉnh Tạo file tests/_support/Helper/{suite_name}.php và thêm phương thức. Sau đó, bạn có thể gọi chúng thông qua đối tượng $I của ApiTester.

Chạy mã kiểm thử và tạo báo cáo độ bao phủ

php codecept.phar run -coverage --coverage-html --coverage-xml

Báo cáo sẽ được tạo trong thư mục tests/_output/coverage/.

Bạn có thể xem báo cáo bằng cách cài đặt máy chủ tĩnh nginx.

Sử dụng mã kiểm thử để tái cấu trúc Các bước:

  1. Viết mã kiểm thử
  2. Duy trì và cải thiện độ bao phủ của mã kiểm thử
  3. Chạy mã kiểm thử và đảm bảo nó thông qua. Lặp lại các bước 1, 2, 3
  4. Khi mã nguồn trở nên phức tạp
  5. Tái cấu trúc
  6. Hợp nhất các vòng lặp, phương thức, lớp tương tự
  7. Trích xuất phương thức
  8. v.v.
  9. Chạy mã kiểm thử, tìm các trường hợp thất bại
  10. Sửa mã tái cấu trúc, đảm bảo nó thông qua các trường hợp kiểm thử. Lặp lại các bước 5, 6, 7

Sử dụng mã kiểm thử để nhanh chóng hiểu mã mới steps sẽ in ra các khẳng định đang được thực thi, giúp quan sát hành vi của mã kiểm thử và cách sử dụng API.

php codecept.phar run api --steps # In ra các bước thực thi

Thẻ: Codeception php Yii2 Unit Testing Functional Testing

Đăng vào ngày 18 tháng 9 lúc 12:00