使用模塊Module
使用框架模塊
Codeception目前含有的模塊有這些(最新的當前codeception版本:3.1.2):
- \Helper\Unit
- \Helper\Acceptance
- \Helper\Functional
- Asserts ( https://codeception.com/docs/modules/Asserts )
- PhpBrowser ( https://codeception.com/docs/modules/PhpBrowser )
- REST ( https://codeception.com/docs/modules/REST )
- Db ( https://codeception.com/docs/modules/Db )
- SOAP ( https://codeception.com/docs/modules/SOAP )
- Filesystem ( https://codeception.com/docs/modules/Filesystem )
- WebDriver ( https://codeception.com/docs/modules/WebDriver )
- Laravel5 ( https://codeception.com/docs/modules/Laravel5 )
- Lumen ( https://codeception.com/docs/modules/Lumen )
- Symfony ( https://codeception.com/docs/modules/Symfony )
- Doctrine2 ( https://codeception.com/docs/modules/Doctrine2 )
- Yii2 ( https://codeception.com/docs/modules/Yii2 )
- ZF2 ( https://codeception.com/docs/modules/ZF2 )
- Phalcon ( https://codeception.com/docs/modules/Phalcon )
- Redis ( https://codeception.com/docs/modules/Redis )
- MongoDb ( https://codeception.com/docs/modules/MongoDb )
- Memcache ( https://codeception.com/docs/modules/Memcache )
- FTP ( https://codeception.com/docs/modules/FTP )
- Cli ( https://codeception.com/docs/modules/Cli )
- Queue ( https://codeception.com/docs/modules/Queue )
- Sequence ( https://codeception.com/docs/modules/Sequence )
- DataFactory ( https://codeception.com/docs/modules/DataFactory )
- Apc ( https://codeception.com/docs/modules/Apc )
- AMQP ( https://codeception.com/docs/modules/AMQP )
- ZendExpressive ( https://codeception.com/docs/modules/ZendExpressive )
具體想看當前版本安裝的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