Files
2026-04-21 23:02:15 +08:00

11 KiB

Testing Patterns

Analysis Date: 2026-04-21

Test Framework

Runner:

  • PHPUnit exists in the project only as part of the ThinkPHP framework (thinkphp/phpunit.xml)
  • No project-level test runner configured

Assertion Library:

  • PHPUnit's built-in assertions (only in framework's own tests)

No Project Tests Exist. After thorough exploration of the entire codebase:

  • application/**/*.test.php -- None found
  • application/**/*.spec.php -- None found
  • tests/ directory -- Does not exist at project root
  • phpunit.xml -- Only exists at thinkphp/phpunit.xml (framework's own test suite)
  • .idea/phpunit.xml -- IDE config pointing to thinkphp/phpunit.xml (for framework testing only)

Framework PHPUnit Config (thinkphp/phpunit.xml):

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="tests/mock.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false">
    <testsuites>
        <testsuite name="ThinkPHP Test Suite">
            <directory>./tests/thinkphp/</directory>
        </testsuite>
    </testsuites>
    <listeners>
        <listener class="JohnKary\PHPUnit\Listener\SpeedTrapListener" />
    </listeners>
    <filter>
        <whitelist>
            <directory suffix=".php">./</directory>
            <exclude>
                <directory suffix=".php">tests</directory>
                <directory suffix=".php">vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>

This config is for testing the ThinkPHP framework itself, NOT the application code in application/.

ThinkPHP Framework Tests (not application code):

  • thinkphp/tests/ contains ~50 test files testing framework internals
  • Covers: Cache, Config, Controller, DB, Debug, Exception, Hook, Lang, Loader, Log, Model, Paginate, Request, Response, Route, Session, Template, URL, Validate, View
  • Example: thinkphp/tests/thinkphp/library/think/validateTest.php

Vendor Tests (not application code):

  • vendor/overtrue/socialite/tests/ -- OAuth provider tests
  • vendor/easywechat-composer/easywechat-composer/tests/ -- Composer plugin tests
  • vendor/pimple/pimple/.github/workflows/tests.yml -- CI config
  • vendor/phpoffice/phpspreadsheet/ -- No test files included in dist

Test File Organization

Current State: No test files exist for application code.

Recommended Structure (if tests were to be added):

tests/
├── bootstrap.php
├── admin/
│   ├── controller/
│   │   └── UserTest.php
│   ├── library/
│   │   └── AuthTest.php
│   └── validate/
│       └── UserTest.php
├── common/
│   ├── controller/
│   ├── library/
│   │   ├── AuthTest.php
│   │   └── UploadTest.php
│   └── model/
│       └── UserTest.php
├── api/
│   └── controller/
│       └── UserTest.php
├── extend/
│   └── fast/
│       └── RandomTest.php
├── fixtures/
│   └── database/
└── TestCase.php

Mocking

No mocking framework in use.

Dependencies that would need mocking for testing:

  • think\Db -- Database operations (query, startTrans, commit, rollback, name, table)
  • think\Config -- Configuration access (Config::get(), Config::set())
  • think\Request -- HTTP request ($this->request->post(), $this->request->isAjax())
  • think\Session -- Session management
  • think\Cookie -- Cookie operations
  • think\Hook -- Event/hook system
  • think\Lang -- Language/translation
  • think\Loader -- Class autoloading
  • think\View -- Template rendering
  • fast\Tree -- Tree data structure
  • \app\common\library\Auth -- Authentication singleton
  • \app\admin\library\Auth -- Admin authentication singleton
  • GuzzleHttp\Client -- HTTP client (used in application/index/controller/Index.php)

Mocking Challenge: The codebase relies heavily on ThinkPHP's singleton pattern (Auth::instance()) and static methods (Db::name(), Config::get()), making unit testing difficult without significant refactoring or a dedicated mocking framework like Mockery.

Fixtures and Factories

Current State: No test fixtures or factories exist.

Database fixtures would be needed for:

  • User records (admin users, regular users)
  • Auth groups and rules
  • Categories and attachments
  • Config entries

Coverage

Current Coverage: 0% -- No test coverage for any application code.

Untested Modules (by priority):

High Priority (core business logic):

Module File Functionality
Common Auth application/common/library/Auth.php User registration, login, token management, password encryption, email/mobile verification
Admin Auth application/admin/library/Auth.php Admin authentication, permission checking, breadcrumb generation
Backend Trait application/admin/library/traits/Backend.php CRUD operations: index, add, edit, del, multi, import, recyclebin, destroy, restore
Backend Controller application/common/controller/Backend.php buildparams() query building, selectpage() dropdown, data limit enforcement
Upload application/common/library/Upload.php File upload, validation, chunked upload, image processing
Token application/common/library/Token.php Token CRUD (MySQL/Redis drivers)
Security application/common/library/Security.php XSS cleaning, input sanitization

Medium Priority (data operations):

Module File Functionality
User Model (common) application/common/model/User.php Money/score change logging, level calculation, avatar generation
User Model (admin) application/admin/model/User.php Password hashing on change, money/score audit logging
MoneyLog application/common/model/MoneyLog.php Financial transaction logging
ScoreLog application/common/model/ScoreLog.php Score transaction logging
User Controller application/admin/controller/user/User.php User management with avatar processing
Command Controller application/admin/controller/Command.php Online command generation and execution
Validators application/admin/validate/*.php Data validation rules for all entities

Low Priority (utilities):

Module File
Global Helpers application/common.php (20+ functions)
Admin Helpers application/admin/common.php
Random extend/fast/Random.php
Date extend/fast/Date.php
Tree extend/fast/Tree.php
Rsa extend/fast/Rsa.php
Form extend/fast/Form.php
Http extend/fast/Http.php

Code Quality Tools

Static Analysis:

  • No PHPStan, Psalm, or PHPMD configured at project level
  • PhpStorm .idea/ directory contains transferred (inactive) configurations for PHPCS, PHPStan, and MessDetector
  • No .php-cs-fixer.php, phpcs.xml, phpmd.xml, or phpstan.neon files

Linting:

  • No ESLint, Prettier, or stylelint for frontend code
  • package.json exists with Grunt build tasks only (minification, no linting)

CI/CD:

  • No .github/ directory (no GitHub Actions)
  • No .gitlab-ci.yml
  • No Jenkinsfile
  • No .travis.yml
  • No CI pipeline of any kind

Build Tools:

  • Grunt for CSS/JS minification (public/assets/js/*.min.js, public/assets/css/*.min.css)
  • application/admin/command/Min.php for asset minification
  • application/admin/command/Crud.php for code generation
  • application/admin/command/Api.php for API documentation generation
  • application/admin/command/Menu.php for menu generation
  • application/admin/command/Install.php for installation

Composer Scripts: None defined in composer.json

Test Types

Unit Tests: Not used. No unit test files exist for any application code.

Integration Tests: Not used. No integration tests exist.

E2E Tests: Not used. No end-to-end testing framework (Selenium, Cypress, etc.) configured.

Feature Tests: Not used.

Why No Tests

  1. FastAdmin Nature -- This is a rapid development admin scaffold. FastAdmin projects prioritize speed over test coverage by design.
  2. No require-dev -- composer.json has no testing-related dev dependencies (no PHPUnit, Mockery, etc.)
  3. No scripts.test -- composer.json defines no test scripts
  4. No CI/CD -- No continuous integration pipeline to enforce test execution
  5. Tight Coupling -- Heavy reliance on ThinkPHP singletons and static methods makes unit testing difficult without significant refactoring
  6. Framework Philosophy -- ThinkPHP 5.x ecosystem does not emphasize testing as a first-class concern

Step 1: Add dev dependencies to composer.json:

"require-dev": {
    "phpunit/phpunit": "^9.6",
    "mockery/mockery": "^1.6"
}

Step 2: Create phpunit.xml at project root:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php"
         colors="true"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Application Test Suite">
            <directory>./tests/</directory>
        </testsuite>
    </testsuites>
    <php>
        <env name="APP_ENV" value="testing"/>
    </php>
</phpunit>

Step 3: Create tests/bootstrap.php:

<?php
// Load ThinkPHP bootstrap
define('APP_PATH', __DIR__ . '/../application/');
define('ROOT_PATH', __DIR__ . '/../');
define('RUNTIME_PATH', ROOT_PATH . 'runtime/');
require __DIR__ . '/../thinkphp/base.php';

// Set testing config
\think\Config::set('app_debug', false);

Step 4: Add composer script:

"scripts": {
    "test": "phpunit"
}

Run Commands (after setup):

composer install --dev           # Install dev dependencies
vendor/bin/phpunit               # Run all tests
vendor/bin/phpunit --coverage-html coverage/  # Generate coverage report
composer test                    # Run via composer script

Testing Challenges Specific to This Codebase

  1. Singleton Auth -- Auth::instance() is called directly throughout, requiring careful mock setup or refactoring to dependency injection
  2. Static Db Calls -- Db::name(), Db::query(), Db::startTrans() used everywhere instead of injected connections
  3. Global Functions -- __(), cdnurl(), etc. depend on ThinkPHP runtime being bootstrapped
  4. Request Context -- Controllers depend on $this->request populated by framework routing
  5. Session/Cookie -- Many operations depend on session/cookie state
  6. Config Dependency -- Heavy use of Config::get() makes isolation testing difficult
  7. View Rendering -- Some tests would need to verify HTML output from templates

Testing analysis: 2026-04-21