codeception測試使用框架模塊Module


使用模塊Module
使用框架模塊

Codeception目前含有的模塊有這些(最新的當前codeception版本:3.1.2):

 

具體想看當前版本安裝的codecept.phar包含了哪些模塊,可以通過PhpStorm等IDE工具看包里的源代碼:

  模塊定義文件在路徑: codecept.phar > src > Module 目錄下。

 想查詢哪個模塊的具體用法,有哪些具體參數,可以點擊查看模塊源文件。

比如查看Db模塊信息:

 查看Db模塊的配置有哪些參數,和哪些參數是必須的:

查看源碼:

<?php
class Db extends CodeceptionModule implements DbInterface
{
    /**
     * @var array
     */
    protected $config = [
        'populate' => false,
        'cleanup' => false,
        'reconnect' => false,
        'waitlock' => 0,
        'dump' => null,
        'populator' => null,
    ];

    /**
     * @var array
     */
    protected $requiredFields = ['dsn', 'user', 'password'];

 $config 就是配置參數,$requiredFields 就是必須填寫的參數。

數據庫連接配置參考:

 * ## Example
 *
 *     modules:
 *        enabled:
 *           - Db:
 *              dsn: 'mysql:host=localhost;dbname=testdb'
 *              user: 'root'
 *              password: ''
 *              dump: 'tests/_data/dump.sql'
 *              populate: true
 *              cleanup: true
 *              reconnect: true
 *              waitlock: 10
 *              ssl_key: '/path/to/client-key.pem'
 *              ssl_cert: '/path/to/client-cert.pem'
 *              ssl_ca: '/path/to/ca-cert.pem'
 *              ssl_verify_server_cert: false
 *              ssl_cipher: 'AES256-SHA'
 *              initial_queries:
 *                  - 'CREATE DATABASE IF NOT EXISTS temp_db;'
 *                  - 'USE temp_db;'
 *                  - 'SET NAMES utf8;'
 *
 * ## Example with multi-dumps
 *     modules:
 *          enabled:
 *             - Db:
 *                dsn: 'mysql:host=localhost;dbname=testdb'
 *                user: 'root'
 *                password: ''
 *                dump:
 *                   - 'tests/_data/dump.sql'
 *                   - 'tests/_data/dump-2.sql'
 *
 * ## Example with multi-databases
 *
 *     modules:
 *        enabled:
 *           - Db:
 *              dsn: 'mysql:host=localhost;dbname=testdb'
 *              user: 'root'
 *              password: ''
 *              databases:
 *                 db2:
 *                    dsn: 'mysql:host=localhost;dbname=testdb2'
 *                    user: 'userdb2'
 *                    password: ''

連接到MySQL數據庫:

* For MySQL:
 *
 * ```yaml
 * modules:
 *    enabled:
 *       - Db:
 *          dsn: 'mysql:host=localhost;dbname=testdb'
 *          user: 'root'
 *          password: ''
 *          dump: 'tests/_data/dump.sql'
 *          populate: true # run populator before all tests
 *          cleanup: true # run populator before each test
 *          populator: 'mysql -u $user -h $host $dbname < $dump'
 *          initial_queries:
 *              - 'CREATE DATABASE IF NOT EXISTS temp_db;'
 *              - 'USE temp_db;'
 *              - 'SET NAMES utf8;'

連接到PostgreSQL:

 * For PostgreSQL (using pg_restore)
 *
 * ```
 * modules:
 *    enabled:
 *       - Db:
 *          dsn: 'pgsql:host=localhost;dbname=testdb'
 *          user: 'root'
 *          password: ''
 *          dump: 'tests/_data/db_backup.dump'
 *          populate: true # run populator before all tests
 *          cleanup: true # run populator before each test
 *          populator: 'pg_restore -u $user -h $host -D $dbname < $dump'

 實踐

配置連接數據庫模塊Db:

目前的unit.suite.xml配置文件:

actor: UnitTester
modules:
    enabled:
        - Asserts
        - \Helper\Unit
    step_decorators: ~

我們要增加幾個模塊,比如數據庫模塊Db,PhpBrowser, Filesystem等模塊:

actor: UnitTester
modules:
    enabled:
        - Asserts
        - \Helper\Unit
        - Db:
              dsn: 'mysql:host=localhost;dbname=testdb'
              user: 'root'
              password: 'root'
              dump: 'tests/_data/dump.sql'
        - PhpBrowser:
              url: http://localhost
        - Filesystem
    step_decorators: ~

編寫單元測試文件tests/unit/ExampleTest.php代碼:

<?php 
class ExampleTest extends Codeception\Test\Unit
{
    /**
     * @var \UnitTester
     */
    protected $tester;
    
    protected function _before()
    {
    }

    protected function _after()
    {
    }

    // tests
    public function testSomeFeature()
    {
        $this->assertTrue(true);

        $dbh = $this->getModule('Db')->_getDbh(); // dbh: contains the PDO connection 返回一個PDO連接對象
        // $dbh是一個PDO對象,就可以說使用任何PDO對象的方法 (https://www.php.net/manual/en/class.pdo.php)
        $sql = "SELECT username, email FROM `member` where username = 'lajox' ORDER BY id";
        // 比如使用PDO::query()方法
        foreach ($dbh->query($sql) as $row) {
            $this->assertContains('lajox', $row['username']); // $row['username']變量值是否包含字符串lajox
            $this->assertContains('blueno@yeah.net', $row['email']); // $row['email']變量值是否包含字符串blueno@yeah.net
        }

        $this->getModule('Db')->seeNumRecords(1, 'member', ['username' => 'lajox']); // 判斷member表里username='lajox'的數據記錄數是不是1(條)
        $this->getModule('Db')->seeInDatabase('member', ['username' => 'lajox', 'email like' => '%yeah.net%']); // 判斷member表里username='lajox' AND email like '%yeah.net%'是否存在記錄
        $this->getModule('Db')->dontSeeInDatabase('member', ['email like' => '%163.com%']); // 判斷member表里email like '%163.com%'是否不存在記錄
    }
}

Debug打印變量:

用內置的 codecept_debug() 方法來打印變量:

<?php 
class ExampleTest extends Codeception\Test\Unit
{
    /**
     * @var \UnitTester
     */
    protected $tester;
    
    protected function _before()
    {
    }

    protected function _after()
    {
    }

    // tests
    public function testSomeFeature()
    {
        $this->assertTrue(true);

        $dbh = $this->getModule('Db')->_getDbh(); // dbh: contains the PDO connection 返回一個PDO連接對象
        // $dbh是一個PDO對象,就可以說使用任何PDO對象的方法 (https://www.php.net/manual/en/class.pdo.php)
        $sql = "SELECT username, email FROM `member` where username = 'lajox' ORDER BY id";
        // 比如使用PDO::query()方法
        foreach ($dbh->query($sql) as $row) {
            $this->assertContains('lajox', $row['username']); // $row['username']變量值是否包含字符串lajox
            $this->assertContains('blueno@yeah.net', $row['email']); // $row['email']變量值是否包含字符串blueno@yeah.net
        }

        $this->getModule('Db')->seeNumRecords(1, 'member', ['username' => 'lajox']); // 判斷member表里username='lajox'的數據記錄數是不是1(條)
        $this->getModule('Db')->seeInDatabase('member', ['username' => 'lajox', 'email like' => '%yeah.net%']); // 判斷member表里username='lajox' AND email like '%yeah.net%'是否存在記錄
        $this->getModule('Db')->dontSeeInDatabase('member', ['email like' => '%163.com%']); // 判斷member表里email like '%163.com%'是否不存在記錄

        $number = $this->getModule('Db')->grabNumRecords('member', ['username' => 'lajox']); // 獲取member表里username='lajox'的記錄數
        $mails = $this->getModule('Db')->grabColumnFromDatabase('member', 'email', array('username' => 'lajox')); // 獲取member表里username='lajox'的郵箱字段email的數組列表
        //$email = $this->getModule('Db')->grabFromDatabase('member', 'email', ['email like' => '%blueno%']); // 獲取member表里email like '%blueno%'的第一條數據的email字段值

        $this->debugSection('number', $number);
        $this->debugSection('MailList', $mails);
    }

    protected function debugSection($title, $message)
    {
        if (is_array($message) or is_object($message)) {
            $message = stripslashes(json_encode($message));
        }
        \codecept_debug("[$title] $message");
    }
}

命令行下,codecept run命令加上 --debug參數, 例如:

codecept run unit ExampleTest.php --steps --debug --fail-fast

 

 解釋:命令行增加 --debug 參數才能完整詳細輸出打印信息:

又假如我們要驗證測試一個點贊功能的正確性,可以這么做:

<?php 
class ExampleTest extends Codeception\Test\Unit
{
    /**
     * @var \UnitTester
     */
    protected $tester;
    
    protected function _before()
    {
    }

    protected function _after()
    {
    }

    // tests
    public function testSomeFeature()
    {
        $testBookId = 99;    //要測試的書籍ID
        $bookSupport = $this->getModule('Db')->grabFromDatabase('book', 'support', ['id' => $testBookId]);    //從數據庫取出書籍點贊記錄

        //打印原始點贊數值
        $this->debugSection('bookSupport', $bookSupport);

        //假設這是對 ID為99的一本書進行"贊/喜歡"操作, 如果成功,結果應該是 喜歡數 support字段值 就會自動 + 1 了
        $this->getModule('PhpBrowser')->sendAjaxPostRequest('/book/support.do', ['id' => $testBookId]);

        $this->getModule('Db')->seeInDatabase('book', [
            'id' => $testBookId,
            'support' => $bookSupport + 1,
        ]);    //斷言support字段是否被加1了

        $this->getModule('Db')->dontSeeInDatabase('book', [
            'id' => $testBookId,
            'support' => $bookSupport,
        ]); //或者斷言不會是原來的值
    }

    protected function debugSection($title, $message)
    {
        if (is_array($message) or is_object($message)) {
            $message = stripslashes(json_encode($message));
        }
        \codecept_debug("[$title] $message");
    }
}

更多Db模塊的方法用例,請查閱: https://codeception.com/docs/modules/Db

查閱文檔:https://github.com/Codeception/codeception.github.com/blob/master/docs/modules/Db.md

 PhpStorm配置codeception單元測試運行參數:

編輯工具欄的Debug配置:

 彈出的Run/Debug Configurations窗口中,Test Runner Options 填入附加運行參數: --steps --debug

編輯配置文件 codeception.yml , 在默認開啟的 extensions 可能只有 Codeception\Extension\RunFailed ,

需要增加幾個 extensions 拓展選項開啟,例如增加開啟  Codeception\Extension\SimpleReporter,Codeception\Extension\DotReporter 等拓展:

include:
paths:
    tests: tests
    output: tests/_output
    data: tests/_data
    support: tests/_support
    envs: tests/_envs
actor_suffix: Tester
bootstrap: _bootstrap.php
settings:
    colors: true
    memory_limit: 1024M
extensions:
    enabled:
        - Codeception\Extension\RunBefore
        - Codeception\Extension\RunProcess
        - Codeception\Extension\RunFailed
        - Codeception\Extension\SimpleReporter
        - Codeception\Extension\DotReporter

 這樣調試輸出打印的運行日志信息會更多。

記住,修改yml配置文件之后,一般都要再運行 codecept build 構建代碼:

最后點運行按鈕 進行Debug單元測試:

 全方面的單元測試:

例如配置unit.suite.yml配置文件,增加幾個模塊:Db, PhpBrowser, REST等模塊引入:

actor: UnitTester
bootstrap: _bootstrap.php
modules:
    enabled:
        - Asserts
        - \Helper\Unit
        - Db:
              dsn: 'mysql:host=localhost;dbname=testdb'
              user: 'root'
              password: 'root'
              dump: 'tests/_data/dump.sql'
        - PhpBrowser:
              url: http://www.lancms.com
        - REST:
            url: http://www.lancms.com
            depends: PhpBrowser
            part: Json
        - Filesystem
    step_decorators: ~

注釋:bootstrap: _bootstrap.php 這個配置是引入了 _bootstrap.php 加載文件,可以往里面加你要引入的文件或類庫。比如:

<?php
# 文件 tests/unit/_bootstrap.php
# 引入單元測試方法拓展基類
require_once __DIR__ . '/UnitBase.php';

新建一個 tests/unit/UnitBase.php 文件:

<?php
# 文件 tests/unit/UnitBase.php
class UnitBase extends Codeception\Test\Unit
{
    /**
     * 調用類的私有方法
     * @param object $object
     * @param string $className
     * @param string $methodName
     * @param array  $params
     * @return mixed
     */
    protected function callPrivateMethod($object, string $className, string $methodName, array $params) {
        $method = $this->getPrivateMethod($className, $methodName);
        return $method->invokeArgs($object, $params);
    }

    /**
     * 獲取對象的私有屬性
     * @param object $object
     * @param string $className
     * @param string $propertyName
     * @return mixed
     */
    protected function getPrivatePropertyValue($object, string $className, string $propertyName) {
        $property = $this->getPrivateProperty($className, $propertyName);
        return $property->getValue($object);
    }

    /**
     * getPrivateProperty
     *
     * @param string $className
     * @param string $propertyName
     * @return    ReflectionProperty
     * @author    Joe Sexton <joe@webtipblog.com>
     */
    protected function getPrivateProperty(string $className, string $propertyName): \ReflectionProperty {
        $reflector = new ReflectionClass($className);
        $property  = $reflector->getProperty($propertyName);
        $property->setAccessible(true);

        return $property;
    }

    /**
     * getPrivateMethod
     *
     * @param string $className
     * @param string $methodName
     * @return    ReflectionMethod
     * @author    Joe Sexton <joe@webtipblog.com>
     */
    protected function getPrivateMethod(string $className, string $methodName): \ReflectionMethod {
        $reflector = new ReflectionClass($className);
        $method    = $reflector->getMethod($methodName);
        $method->setAccessible(true);

        return $method;
    }
}

修改 tests/unit/ExampleTest.php,就可以把 繼承方法 class ExampleTest extends Codeception\Test\Unit 改為: class ExampleTest extends UnitBase

編輯unit單元測試文件:tests/unit/ExampleTest.php

<?php
# 文件 tests/unit/ExampleTest.php
class ExampleTest extends Codeception\Test\Unit
{
    /**
     * @var \UnitTester
     */
    protected $tester;

    public function _before()
    {
    }

    public function _after()
    {
    }

    // tests
    public function testSomeFeature()
    {
        $this->assertTrue(true);

        $this->_testDB();          # 測試數據庫模塊: Db
        $this->_testPhpBrowser();  # 測試模塊: PhpBrowser
        $this->_testREST();        # 測試api測試模塊: REST
        $this->_testCept();        # 場景測試
        $this->_testScratch();     # 綜合測試,混用
        $this->_testThinPHP();     # 測試ThinkPHP 5.1方法
    }

    protected function _testDB()
    {
        // 可以查看文檔: https://codeception.com/docs/modules/Db
        $dbh = $this->getModule('Db')->_getDbh(); // dbh: contains the PDO connection 返回一個PDO連接對象
        // $dbh是一個PDO對象,就可以說使用任何PDO對象的方法 (https://www.php.net/manual/en/class.pdo.php)
        $sql = "SELECT username, email FROM `member` where username = 'lajox' ORDER BY id";
        // 比如使用PDO::query()方法
        foreach ($dbh->query($sql) as $row) {
            $this->assertContains('lajox', $row['username']); // $row['username']變量值是否包含字符串lajox
            $this->assertContains('blueno@yeah.net', $row['email']); // $row['email']變量值是否包含字符串blueno@yeah.net
        }

        $this->getModule('Db')->seeNumRecords(1, 'member', ['username' => 'lajox']); // 判斷member表里username='lajox'的數據記錄數是不是1(條)
        $this->getModule('Db')->seeInDatabase('member', ['username' => 'lajox', 'email like' => '%yeah.net%']); // 判斷member表里username='lajox' AND email like '%yeah.net%'是否存在記錄
        $this->getModule('Db')->dontSeeInDatabase('member', ['email like' => '%163.com%']); // 判斷member表里email like '%163.com%'是否不存在記錄

        $number = $this->getModule('Db')->grabNumRecords('member', ['username' => 'lajox']); // 獲取member表里username='lajox'的記錄數
        $mails = $this->getModule('Db')->grabColumnFromDatabase('member', 'email', array('username' => 'lajox')); // 獲取member表里username='lajox'的郵箱字段email的數組列表
        $email = $this->getModule('Db')->grabFromDatabase('member', 'email', ['email like' => '%blueno%']); // 獲取member表里email like '%blueno%'的數據列表(數組)

        $this->debugSection('number', $number);
        $this->debugSection('MailList', $mails);
        $this->debugSection('Email', $email);
    }

    protected function _testPhpBrowser()
    {
        // 可以查看文檔: https://codeception.com/docs/modules/PhpBrowser
        $this->getModule('PhpBrowser')->haveHttpHeader('accept', 'application/json');
        // $this->getModule('PhpBrowser')->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded'); // 普通表單形式發送
        $this->getModule('PhpBrowser')->haveHttpHeader('content-type', 'application/json'); // 發送JSON形式數據
        // AJAX請求
        //$this->getModule('PhpBrowser')->sendAjaxPostRequest('/api/test/demo', ['name' => 'test', 'email' => 'test@163.com']);
        $this->getModule('PhpBrowser')->sendAjaxRequest('POST', 'http://www.lancms.com/api/test/demo', [
            'name' => 'test',
            'email' => 'test@163.com',
        ]);
        $this->getModule('PhpBrowser')->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); // 200
    }

    protected function _testREST()
    {
        # 發送請求api地址: http://www.lancms.com/api/test/demo
        # 請求參數: {"name":"test","email":"test@163.com"}
        # 響應結果: {"code":1,"msg":"success","data":[]}
        $this->getModule('REST')->haveHttpHeader('accept', 'application/json');
        // $I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded'); // 普通表單形式發送
        $this->getModule('REST')->haveHttpHeader('content-type', 'application/json'); // 發送JSON形式數據
        $this->getModule('REST')->sendPOST('/api/test/demo', [
            'name' => 'test',
            'email' => 'test@163.com',
        ]);
        $this->getModule('REST')->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); // 200
        $this->getModule('REST')->seeResponseCodeIs(200);
        $this->getModule('REST')->seeResponseIsJson();
        $this->getModule('REST')->seeResponseContains('success');
        $this->getModule('REST')->seeResponseContainsJson([
            "code" => "1",
        ]);
        $this->getModule('REST')->seeResponseJsonMatchesJsonPath("$.data");
        $this->getModule('REST')->seeResponseJsonMatchesXpath('//data');
        $this->getModule('REST')->seeResponseMatchesJsonType([
            'code' => 'integer',
            'msg' => 'string',
            'data' => 'string|array|null',
        ]);
    }

    /**
     * 測試場景
     * @var \UnitTester $this->tester
     */
    protected function _testCept()
    {
        $this->tester->amOnPage('/index/test/show');
        $this->tester->see('show_test');
    }

    /**
     * 綜合測試,混用
     * @var \UnitTester $this->tester
     */
    protected function _testScratch()
    {
        # 因為unit.suite.yml已經配置了引入Db、PhpBrowser、REST等模塊,
        # 所以 $this->tester引用對象就會自動包含各個模塊的所有方法。可以用 $this->tester 簡化替代 $this->getModule() 方法。

        # 模塊Db方法:
        $this->getModule('Db')->seeNumRecords(1, 'member', ['username' => 'lajox']);
        $this->tester->seeNumRecords(1, 'member', ['username' => 'lajox']);

        # 模塊PhpBrowser方法:
        $this->getModule('PhpBrowser')->sendAjaxPostRequest('/api/test/demo', ['name' => 'test', 'email' => 'test@163.com']);
        $this->tester->sendAjaxPostRequest('/api/test/demo', ['name' => 'test', 'email' => 'test@163.com']);

        # 模塊REST方法:
        $this->getModule('REST')->sendPOST('/api/test/demo', ['name' => 'test', 'email' => 'test@163.com']);
        $this->tester->sendPOST('/api/test/demo', ['name' => 'test', 'email' => 'test@163.com']);
    }

    /**
     * 測試ThinkPHP的方法
     */
    protected function _testThinPHP()
    {
        $app = new \app\index\controller\Test();
        // 假設 index/test/show 方法返回的字符串中包含 "show_test"
        $this->assertContains('show_test', $app->show());
    }

    protected function debugSection($title, $message)
    {
        if (is_array($message) or is_object($message)) {
            $message = stripslashes(json_encode($message));
        }
        \codecept_debug("[$title] $message");
    }

}

phpstorm快速Debug測試unit單元測試方法:

 就能快速運行Debug單元測試了:

 編輯Debug工具欄, 配置此方法的選項:

 彈出的Run/Debug Configurations窗口中,Test Runner Options 填入附加運行參數: --steps --debug

 再次點擊 運行按鈕,就可以看到更多的Debug調試信息了:

 高級用法:

我們回顧一下,unit.suite.yml 配置文件默認是開啟了 \Helper\Unit 模塊:

 那么這個\Helper\Unit模塊定義文件在哪呢?

我們看下tests/ 目錄下的文件結構,就會發現:\Helper\Unit 模塊定義文件在: tests/_support/Helper/Unit.php 文件中:

 修改 tests/_support/Helper/Unit.php 文件代碼,我們增加了一個自定義方法 seeResponseIsValidate() :

<?php
namespace Helper;

// here you can define custom actions
// all public methods declared in helper class will be available in $I

class Unit extends \Codeception\Module
{
    public function seeResponseIsValidate()
    {
        $this->getModule('REST')->haveHttpHeader('accept', 'application/json');
        $this->getModule('REST')->haveHttpHeader('content-type', 'application/json'); // 發送JSON形式數據
        $this->getModule('REST')->sendPOST('/api/test/demo', [
            'name' => 'test',
            'email' => 'test@163.com',
        ]);
        $this->getModule('REST')->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); // 200
        $this->getModule('REST')->seeResponseCodeIs(200);
        $this->getModule('REST')->seeResponseIsJson();
        $this->getModule('REST')->seeResponseContains('success');
        $response = $this->getModule('REST')->grabResponse();
        $this->assertContains('success', $response);
    }
}

修改文件:文件 tests/unit/ExampleTest.php,內容為:

<?php
# 文件 tests/unit/ExampleTest.php
class ExampleTest extends UnitBase
{
    /**
     * @var \UnitTester
     */
    protected $tester;

    public function _before()
    {
    }

    public function _after()
    {
    }

    // tests
    public function testSomeFeature()
    {
        $this->assertTrue(true);

        $this->_testHelperUnit();          # 測試業務代碼: tests/_support/Helper/Unit.php
    }

    /**
     * 測試業務代碼放入 tests/_support/Helper/Unit.php 文件中
     */
    protected function _testHelperUnit()
    {
        $this->getModule('\Helper\Unit')->seeResponseIsValidate();
    }

    protected function debugSection($title, $message)
    {
        if (is_array($message) or is_object($message)) {
            $message = stripslashes(json_encode($message));
        }
        \codecept_debug("[$title] $message");
    }

}

運行一下Debug按鈕:

 添加新模塊文件:

通過命令 codecept generate:helper "Unit\MyModule" 就會自動在 tests/_support/Helper/ 目錄下生成一個文件夾Unit和Unit文件夾下的文件 MyModule.php:

當然,你也可以手動新建目錄Unit和文件 Unit/MyModule.php ,如果你不嫌麻煩的話。

codecept generate:helper "Unit\MyModule"

 編輯文件 tests/_support/Helper/Unit/MyModule.php ,代碼寫入:

<?php
# 文件 tests/_support/Helper/Unit/MyModule.php
namespace Helper\Unit;

// here you can define custom actions
// all public methods declared in helper class will be available in $I

class MyModule extends \Codeception\Module
{
    public function seeMyModuleIsValidate()
    {
        $this->assertTrue(false);
    }
}

配置 unit.suite.yml 配置文件,加入引入模塊代碼:\Helper\Unit\MyModule

# Codeception Test Suite Configuration
#
# Suite for unit or integration tests.

actor: UnitTester
bootstrap: _bootstrap.php
modules:
    enabled:
        - Asserts
        - \Helper\Unit
        - \Helper\Unit\MyModule
        - Db:
              dsn: 'mysql:host=localhost;dbname=testdb'
              user: 'root'
              password: 'root'
              dump: 'tests/_data/dump.sql'
        - PhpBrowser:
              url: http://www.lancms.com
        - REST:
            url: http://www.lancms.com
            depends: PhpBrowser
            part: Json
        - Filesystem
    step_decorators: ~

然后命令行執行命令 codecept build  構建代碼。

  看到  includes modules: 和 \Helper\Unit\MyModule 提示文字表示新的模塊已經引用進來:

 

編輯 tests/_support/Helper/Unit.php ,代碼:

<?php
# 文件 tests/_support/Helper/Unit.php
namespace Helper;

// here you can define custom actions
// all public methods declared in helper class will be available in $I

class Unit extends \Codeception\Module
{
    public function seeResponseIsValidate()
    {
        $this->getModule('REST')->haveHttpHeader('accept', 'application/json');
        $this->getModule('REST')->haveHttpHeader('content-type', 'application/json'); // 發送JSON形式數據
        $this->getModule('REST')->sendPOST('/api/test/demo', [
            'name' => 'test',
            'email' => 'test@163.com',
        ]);
        $this->getModule('REST')->seeResponseCodeIs(\Codeception\Util\HttpCode::OK); // 200
        $this->getModule('REST')->seeResponseCodeIs(200);
        $this->getModule('REST')->seeResponseIsJson();
        $this->getModule('REST')->seeResponseContains('success');
        $response = $this->getModule('REST')->grabResponse();
        $this->assertContains('success', $response);
    }

    public function seeMyModule()
    {
        $this->getModule('\Helper\Unit\MyModule')->seeMyModuleIsValidate();
    }
}

編輯文件:tests/unit/ExampleTest.php ,代碼:

<?php
# 文件 tests/unit/ExampleTest.php
class ExampleTest extends UnitBase
{
    /**
     * @var \UnitTester
     */
    protected $tester;

    public function _before()
    {
    }

    public function _after()
    {
    }

    // tests
    public function testSomeFeature()
    {
        $this->assertTrue(true);

        $this->_testHelperUnit();          # 測試業務代碼: tests/_support/Helper/Unit.php
    }

    /**
     * 測試業務代碼放入 tests/_support/Helper/Unit.php 文件中
     */
    protected function _testHelperUnit()
    {
        $this->getModule('\Helper\Unit')->seeResponseIsValidate();
        $this->getModule('\Helper\Unit')->seeMyModule();
        $this->getModule('\Helper\Unit\MyModule')->seeMyModuleIsValidate();

        $this->_testCept(); // 測試場景

        # debug輸出一條信息
        $this->debugSection('CurrentMethod', __METHOD__); // 就會輸出: [CurrentMethod] ExampleTest::_testHelperUnit
    }

    /**
     * 測試場景
     * @var \UnitTester $this->tester
     */
    protected function _testCept()
    {
        $this->tester->amOnPage('/index/test/show');
        $this->tester->see('show_test');
        # 可以將場景測試代碼移入文件 tests/_support/UnitTester.php 中
        $this->tester->seeUnitTester();
    }

    protected function debugSection($title, $message)
    {
        if (is_array($message) or is_object($message)) {
            $message = stripslashes(json_encode($message));
        }
        \codecept_debug("[$title] $message");
    }

}

編輯文件 tests/_support/UnitTester.php, 代碼:

<?php
# 文件 tests/_support/UnitTester.php

/**
 * Inherited Methods
 * @method void wantToTest($text)
 * @method void wantTo($text)
 * @method void execute($callable)
 * @method void expectTo($prediction)
 * @method void expect($prediction)
 * @method void amGoingTo($argumentation)
 * @method void am($role)
 * @method void lookForwardTo($achieveValue)
 * @method void comment($description)
 * @method void pause()
 *
 * @SuppressWarnings(PHPMD)
*/
class UnitTester extends \Codeception\Actor
{
    use _generated\UnitTesterActions;

   /**
    * Define custom actions here
    */
    public function seeUnitTester()
    {
        $this->amOnPage('/index/test/show');
        $this->see('show_test');

        # 因為unit.suite.yml已經配置了引入Db、PhpBrowser、REST等模塊,
        # 所以 $this引用對象就會自動包含各個模塊的所有方法

        # 使用Db模塊方法, 可以查看文檔: https://codeception.com/docs/modules/Db
        $this->seeNumRecords(1, 'member', ['username' => 'lajox']);

        # 使用PhpBrowser模塊方法, 可以查看文檔: https://codeception.com/docs/modules/PhpBrowser
        $this->sendAjaxRequest('POST', '/api/test/demo', [
            'name' => 'test',
            'email' => 'test@163.com',
        ]);

        # 使用REST模塊方法, 可以查看文檔: https://codeception.com/docs/modules/REST
        $this->sendPOST('/api/test/demo', [
            'name' => 'test',
            'email' => 'test@163.com',
        ]);

        # debug輸出一條信息
        $this->debugSection('CurrentMethod', __METHOD__); // 就會輸出: [CurrentMethod] UnitTester::seeUnitTester
    }

    /**
     * debug
     */
    protected function debugSection($title, $message)
    {
        if (is_array($message) or is_object($message)) {
            $message = stripslashes(json_encode($message));
        }
        \codecept_debug("[$title] $message");
    }
}

點擊運行一下Debug按鈕,查看測試運行效果:

 創建更多的單元測試文件,以文件夾Common, Controller 等為歸組:

codecept generate:test unit "Common\Common"
codecept generate:test unit "Controller\Controller"

注:

codecept generate:test unit "Common\Common" 命令會在 tests/unit/ 目錄下生成 Common/CommonTest.php (文件名以Test.php為后綴)

codecept generate:test unit "Common\Controller" 命令會在 tests/unit/ 目錄下生成 Controller/ControllerTest.php (文件名以Test.php為后綴)

文件 tests/unit/Common/CommonTest.php 的生成默認代碼:

<?php
# 文件 tests/unit/Common/CommonTest.php
namespace Common;

class CommonTest extends \Codeception\Test\Unit
{
    /**
     * @var \UnitTester
     */
    protected $tester;
    
    protected function _before()
    {
    }

    protected function _after()
    {
    }

    // tests
    public function testSomeFeature()
    {

    }
}

phpstorm配置只運行unit類型的單元測試: 

 

 

 

 

注: unit單元測試文件的類可以繼承 Codeception\Test\Unit ,也可以寫成繼承 Codeception\TestCase\Test

<?php 
# 文件 tests/unit/ExampleTest.php
class ExampleTest extends Codeception\TestCase\Test
{
    /**
     * @var \UnitTester
     */
    protected $tester;
    
    public function _before()
    {
    }

    public function _after()
    {
    }

    // tests
    public function testSomeFeature()
    {
    }
}

 

上面單元測試實例源碼已經放到Github上了: https://github.com/lajox/thinkphp-codeception-example

模塊參考資料:
https://codeception.com/docs/06-ModulesAndHelpers

https://github.com/Codeception/codeception.github.com

http://www.kkh86.com/it/codeception/guide-cept-test-base.html
https://www.cloudxns.net/Support/detail/id/1005.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM