测试与压测
框架追求“使用简单”,因此没有强制引入 PHPUnit / Composer 依赖——自带一套极简测试基座与压测工具,任意 PHP 8 环境 php8 即可运行。
20.1 测试基座(零依赖)
核心三件套:
Mtphp\Testing\Assert:断言助手(assertSame/assertTrue/assertFalse/assertContains/assertNotContains/assertNull/assertException等),失败即抛异常。Mtphp\Testing\TestCase:测试用例基类,提供setUp()(每个用例前)与tearDown()(每个用例后)钩子,并内置runBare()调度。tests/run.php:测试运行器,自动发现tests/*Test.php并反射执行其中所有test*方法,输出汇总报告与正确退出码(CI 友好)。
编写测试(示例:tests/DbTest.php):
<?php
require_once __DIR__ . '/bootstrap.php'; // 注册自动加载 + 载入夹具
use Mtphp\Database\Query;
use Mtphp\Testing\Assert;
use Mtphp\Testing\TestCase;
use Tests\SqliteConnector;
class DbTest extends TestCase
{
private \PDO $pdo;
private Query $q;
protected function setUp(): void // 用例前准备
{
$this->pdo = new \PDO('sqlite::memory:');
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$this->pdo->exec('CREATE TABLE user (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER)');
$this->q = new Query(new SqliteConnector($this->pdo), '');
}
public function testInsertAndSelect(): void // 以 test 开头的方法会被自动发现
{
$id = $this->q->table('user')->insert(['name' => '张三', 'age' => 30]);
Assert::assertSame(1, $id);
Assert::assertTrue($this->q->table('user')->count() === 1);
}
}
运行:
php tests/run.php :: 跑全部
php tests/run.php DbTest :: 只跑某个类(可多传,空格分隔)
退出码:全部通过 0;有失败 1;用法错误 2。输出示例:
用例:8 通过:8 失败:0 断言:36
✅ ALL PASSED
夹具 tests/fixtures.php 提供 Tests\SqliteConnector(用内存 SQLite 实现 Connector 契约)与 sqliteResolver(),让 DB / Model / Query 在完全不依赖 MySQL 的情况下回归验证(与连接池解耦能力对称)。
20.2 压测工具(零依赖)
bin/bench.php 用 curl_multi 实现固定并发压测,输出吞吐(RPS)与延迟分位:
php bin/bench.php <URL> [总请求数=500] [并发数=20]
php bin/bench.php http://127.0.0.1:8080/ 1000 50
输出包含:总请求、成功/失败、总耗时、吞吐 RPS、延迟(最小/平均/最大)、分位(P50/P95/P99)。
⚠️ 说明:Windows 演示用的「内置服务器」
php -S是单工作进程、单线程,不能代表生产性能——本工具在此仅用于“功能/回归级”验证(吞吐是否随并发线性提升、有无报错)。生产级数字请在 Linux / WSL + Swoole 常驻服务器上跑,并用wrk/ab获取(见第 18 节): MD4 Swoole 常驻内存 + 协程连接池才是高并发关键(启动期只引导一次、连接复用、IO 协程化)。