# kephp-test-utils **Repository Path**: kephp/kephp-test-utils ## Basic Information - **Project Name**: kephp-test-utils - **Description**: kephp test utils - 测试辅助工具,提供单元测试、面向对象编程测试一些辅助工具,旨在简化和统一测试的中间代码,并可以对private和protected的方法进行更细的测试。 - **Primary Language**: PHP - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2018-10-20 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # kephp test utils - kephp测试辅助工具 测试驱动开发是好的,其实 PHP 开发之所以会被迅速和广泛的流行起来,正因为执行测试的门槛远较静态编译型语言的成本要低。 但一般的测试代码或者单元测试,编写测试代码,以及事后检阅测试代码,都是一件很头疼。 所以针对一些日常测试的使用情况,特别写了这个工具。 设计目的: 1. 旨在统一和简化单元测试过程代码。 2. 基于反射类,可以对private和protected的方法进行测试,而不局限与public,细化测试粒度。 3. 提供注解的方式标注要测试的方法,目前只有一个 `@testMethod anyMethod`。 4. 不负责测试实现,只负责整合测试用例和测试方法,具体的测试实现通过callback自己写。 5. 采用Trait混入,无需继承,轻松嵌入任意需要测试的类。 6. 自定义测试,直传传入一个Closure实例作为Excepted,参见示例代码 ## 安装方法 ```shell composer require kephp/kephp-test-utils --dev ``` 只需要require-dev即可。 ## API文档 https://apidoc.gitee.com/kephp/kephp-test-utils/namespaces/Ke.TestUtils.html ## 待补充 目前主要完成了类实例的方法封装(对于多数项目和框架而言,这方面需求覆盖度更高)。未针对静态类方法和普通函数,以后会补充。 ## 示例代码 容我偷懒,直接上测试的代码: ```php use PHPUnit\Framework\TestCase; require_once 'AnyClass.php'; class Test_TestClassInstanceTrait extends TestCase { use \Ke\TestUtils\TestClassInstanceTrait; /** * 初始化当前测试的测试实例 */ protected function setUp() { $this->setTestInstance(new AnyClass()); } /** * 测试不存在的方法 */ public function test_notExistsMethod() { $method = $this->newTestMethod('what'); $this->assertFalse($method->isInvokable()); } /** * 测试存在的方法 */ public function test_callExistsMethod() { $staticMethod = $this->newTestMethod('anyStaticMethod'); $publicMethod = $this->newTestMethod('anyPublicMethod'); $privateMethod = $this->newTestMethod('anyPrivateMethod'); $this->assertSame(AnyClass::RET_STATIC_METHOD, $staticMethod->invoke()); $this->assertSame(AnyClass::RET_PUBLIC_METHOD, $publicMethod->invoke()); $this->assertSame(AnyClass::RET_PRIVATE_METHOD, $privateMethod->invoke()); } /** * 测试生成测试用例 */ public function test_newTestItem() { $method = $this->newTestMethod('doSomeThing'); $testItems = [ $method->newTestItem("ok", "ok"), $method->newTestItem("abc", "abc"), ]; /** @var \Ke\TestUtils\TestItem $item */ foreach ($testItems as $item) { $this->assertSame($item->getExcepted(), $item->invoke()); } } /** * 自定义测试 */ public function test_customTest() { $method = $this->newTestMethod('doSomeThing'); $testItems = [ $method->newTestItem("ok", "ok", 'aaa'), $method->newTestItem("abc", "abc"), $method->newTestItem(function () { // 自定义测试 echo "run in custom test", PHP_EOL; $this->assertNotEquals("what", "what2"); $this->assertNotEquals(1, 2); }), ]; /** @var \Ke\TestUtils\TestItem $item */ foreach ($testItems as $item) { $this->assertSame($item->getExcepted(), $item->invoke(), $item->getMessage()); } } /** * 测试调用注解测试方法 * * @testMethod doSomeThing * @throws \Ke\TestUtils\TestMethodException */ public function test_annotateGetMethod() { $method = $this->getLastAnnotationTestMethod(); $testItems = [ $method->newTestItem("ok", "ok", "ok的测试"), $method->newTestItem("abc", "abc", "abc的测试"), ]; /** @var \Ke\TestUtils\TestItem $item */ foreach ($testItems as $item) { $this->assertSame($item->excepted, $item->invoke(), $item->message); } } /** * 测试批量生成测试用例 */ public function test_newItems() { $method = $this->newTestMethod('doSomeThing'); $testItems = $method->newTestItems([ ['OK', 'ok', "ok的测试"], ['ABC', 'abc', "abc的测试"], function (\Ke\TestUtils\TestMethod $method) { // 仍然获取到当前的测试方法 echo "run in custom test, "; echo $method->invoke("ok"), PHP_EOL; }, ], function (AnyClass $obj, $index, \Ke\TestUtils\TestItem $item) { $item->setExcepted(mb_strtolower($item->excepted)); }); /** @var \Ke\TestUtils\TestItem $item */ foreach ($testItems as $item) { $this->assertSame($item->excepted, $item->invoke(), $item->message); } } /** * 测试直接针对某个方法执行测试方法 */ public function test_runMethodTest() { $this->runMethodTest( 'doSomeThing', [ ['OK', 'ok'], ['ABC', 'abc'], ['你好ABC', '你好abc'], function (\Ke\TestUtils\TestMethod $method) { // 仍然获取到当前的测试方法 $this->assertSame('hello', $method->invoke('hello')); }, ], // 测试用例过滤回调函数 function (AnyClass $obj, $index, \Ke\TestUtils\TestItem $item) { $item->setExcepted(mb_strtolower($item->excepted)); }, // 执行测试的实现回调函数 function (AnyClass $obj, $index, \Ke\TestUtils\TestItem $item) { $this->assertSame($item->excepted, $item->invoke()); } )->throwLastException(); // 尝试抛出最后的异常,phpunit是采用throw来抛出断言错误的,所以要确保phpunit正确运行仍要执行这个 } /** * 基于注解取得测试方法 * * @testMethod doSomeThing * @throws \Ke\TestUtils\TestMethodException */ public function test_runMethodTest_byAnnotation() { $this->runMethodTest( $this->getLastAnnotationTestMethod(), [ ['OK', 'ok'], ['ABC', 'abc'], ['你好ABC', '你好abc'], function (\Ke\TestUtils\TestMethod $method) { // 仍然获取到当前的测试方法 $this->assertSame('hello', $method->invoke('hello')); }, ], // 测试用例过滤回调函数 function (AnyClass $obj, $index, \Ke\TestUtils\TestItem $item) { $item->setExcepted(mb_strtolower($item->excepted)); }, // 执行测试的实现回调函数 function (AnyClass $obj, $index, \Ke\TestUtils\TestItem $item) { $this->assertSame($item->excepted, $item->invoke()); } )->throwLastException(); // 尝试抛出最后的异常,phpunit是采用throw来抛出断言错误的,所以要确保phpunit正确运行仍要执行这个 } } ``` ## 开发环境配置说明 PHPStorm,最好按照以下配置: 1. 项目初始化composer环境,Terminal 执行 `composer install` 2. Settings -> Languages & Frameworks -> PHP,设置好本机的PHP执行环境 3. Settings -> Languages & Frameworks -> PHP -> Test Frameworks,按 + 号添加一个 `PHPUnit local` 本地测试环境。 4. 本地测试环境,选择 `Use Composer autoloader` ,选定项目内的 vendor/autoload.php 文件。 5. 如果有必要,本地测试环境,可以勾选添加测试的引导文件,`Default bootstarp file`。