首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 單元測試實戰:SimpleTest 目錄結構、測試分層與持續整合整合

     編輯:PHP 綜合知識

為什麼選擇 SimpleTest?

  • 純 PHP 5+,無擴展依賴,部署簡單。
  • API 直觀:`TestCase`、`TestSuite`、`Reporter` 三大核心類。
  • 支援 **Web 測試器** (模擬瀏覽器表單提交、Cookie、重導向)、**Mock 物件**、**資料庫測試**。
  • 雖然 PHPUnit 為主流,SimpleTest 適合輕量專案、舊版 PHP 維護、或團隊偏好其語法。

專案目錄結構建議

project-root/
├── src/                    # 產品代碼
│   ├── Models/
│   │   └── User.php
│   ├── Services/
│   │   └── AuthService.php
│   └── Utils/
│       └── Validator.php
├── tests/                  # 測試代碼 (鏡像 src 結構)
│   ├── bootstrap.php       # 自動載入、常數、測試專用配置
│   ├── Models/
│   │   └── UserTest.php
│   ├── Services/
│   │   └── AuthServiceTest.php
│   └── Utils/
│       └── ValidatorTest.php
├── vendor/                 # Composer 依賴 (含 simpletest/simpletest)
├── phpunit.xml.dist        # (若併用 PHPUnit)
└── .github/workflows/ci.yml

引導檔 (tests/bootstrap.php)

<?php
// tests/bootstrap.php
define('APP_ROOT', __DIR__ . '/..');
define('TEST_MODE', true);

// Composer 自動載入
require_once APP_ROOT . '/vendor/autoload.php';

// 簡易自動載入 (若專案未用 PSR-4)
spl_autoload_register(function ($class) {
    $file = APP_ROOT . '/src/' . str_replace('\\', '/', $class) . '.php';
    if (is_file($file)) require_once $file;
});

// 測試專用配置 (如 SQLite 內存資料庫)
putenv('DB_DSN=sqlite::memory:');
putenv('CACHE_DRIVER=array');
// ...

單元測試範例 (tests/Models/UserTest.php)

<?php
require_once __DIR__ . '/../bootstrap.php';
require_once 'simpletest/autorun.php'; // 自動執行
require_once 'simpletest/web_tester.php'; // 若需 Web 測試

class UserTest extends UnitTestCase {
    private $user;

    function setUp() {
        $this->user = new User([
            'email'    => 'test@example.com',
            'password' => 'secret123',
            'name'     => 'Test User',
        ]);
    }

    function tearDown() {
        unset($this->user);
    }

    // 基本屬性測試
    function testUserCreation() {
        $this->assertEqual($this->user->email, 'test@example.com');
        $this->assertTrue($this->user->validateEmail());
        $this->assertFalse($this->user->isAdmin());
    }

    // 密碼雜湊驗證
    function testPasswordHashing() {
        $this->assertTrue($this->user->checkPassword('secret123'));
        $this->assertFalse($this->user->checkPassword('wrong'));
        $this->assertNotEqual($this->user->password, 'secret123'); // 應為雜湊
    }

    // 例外情況
    function testInvalidEmailThrows() {
        $this->expectException('InvalidArgumentException');
        new User(['email' => 'invalid', 'password' => 'x', 'name' => 'X']);
    }

    // Mock 依賴測試 (如發送歡迎郵件)
    function testRegisterSendsWelcomeEmail() {
        $mailer = $this->mock('MailerInterface');
        $mailer->expectOnce('send', ['welcome', 'test@example.com']);
        $service = new AuthService($mailer);
        $service->register($this->user);
    }
}

整合測試 / Web 測試範例 (tests/Services/AuthServiceTest.php)

<?php
require_once __DIR__ . '/../bootstrap.php';
require_once 'simpletest/autorun.php';
require_once 'simpletest/web_tester.php';

class AuthServiceWebTest extends WebTestCase {
    function testLoginPageLoads() {
        $this->get('https://localhost/test/login.php');
        $this->assertResponse(200);
        $this->assertTitle('登入');
        $this->assertFieldByName('email');
        $this->assertFieldByName('password');
    }

    function testSuccessfulLogin() {
        $this->get('https://localhost/test/login.php');
        $this->setField('email', 'test@example.com');
        $this->setField('password', 'secret123');
        $this->clickSubmit('登入');
        $this->assertResponse(302); // 重導向
        $this->assertCookie('session_id');
        $this->followRedirect();
        $this->assertText('歡迎回來');
    }
}

測試分層策略

層級目標工具/方法執行頻率
單元測試純邏輯函數/類別,無外部依賴SimpleTest `UnitTestCase` + Mock每次 commit (pre-commit hook / CI)
整合測試模組間互動、資料庫、快取、外部 APISimpleTest `WebTestCase` / `DatabaseTestCase`每次 push / PR (CI 階段)
端到端測試真實瀏覽器流程 (登入、下單、付款)Codeception / Cypress / Playwright每日 / 發布前

持續整合 (GitHub Actions 範例)

# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    services:
      mysql:
        image: mysql:8
        env: { MYSQL_ROOT_PASSWORD: secret, MYSQL_DATABASE: test }
        ports: [3306:3306]
        options: --health-cmd="mysqladmin ping" --health-interval=10s
    steps:
      - uses: actions/checkout@v4
      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with: { php-version: '8.2', extensions: mbstring, pdo_mysql, sqlite3, coverage: xdebug }
      - name: Install dependencies
        run: composer install --prefer-dist --no-progress
      - name: Run unit tests
        run: php vendor/bin/simpletest tests/ --tap | tee test_results.tap
      - name: Upload coverage
        if: always()
        uses: actions/upload-artifact@v4
        with: { name: coverage, path: build/coverage }

遷移到 PHPUnit 建議

SimpleTest 社群活躍度較低,新專案建議直接採用 **PHPUnit 10+**;遷移步驟:

  1. `composer require --dev phpunit/phpunit`
  2. 將 `UnitTestCase` → `PHPUnit\Framework\TestCase`,`assertEqual` → `assertEquals`,`assertTrue` → `assertTrue` (同名)。
  3. `WebTestCase` 功能改用 **Codeception** 或 **Symfony Panther**。
  4. Mock 物件改用 `createMock()` / `getMockBuilder()` 或 **Mockery**。
  5. 執行 `vendor/bin/phpunit` 驗證。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved