crdesign8/laratest-advisor
Composer 安装命令:
composer create-project crdesign8/laratest-advisor
包简介
Intelligent Laravel/PHP static analysis tool providing evidence-based test scenario recommendations.
README 文档
README
Ultra-fast, 100% offline, AST-based (Abstract Syntax Tree) static analysis for Laravel/PHP classes that identifies and recommends robust test scenarios.
Unlike automatic generators that suffer from LLM hallucinations and incorrect mocking, LaraTestAdvisor acts as a Test Scenario Advisor. It tells you (or an AI agent) what to test, why to test it, which risk to protect against, and provides the exact anti-hallucination AI prompt signature to create the correct Pest PHP test.
Key Features
- Offline & AST-Only: No Laravel framework booting, no database access, and no side effects. Uses
nikic/php-parserv5 to purely analyze the file structure. - Multi-Candidate Classification: Scores the likelihood of a PHP class fitting into major Laravel patterns (Actions, Form Requests, Policies, Controllers, Models, etc.) with confidence scoring.
- Double-Risk Assessment Model: Evaluates both the overall class risk (Complexity, Coupling, Dependencies) and each individual scenario's risk independently.
- Top 8 Rules Engine: Focused analysis on:
- Happy Path (basic flow)
- Sad Path (
throwexceptions andtry/catch) - Boundary Conditions (logical limits
<=or>=) - Form Requests (robust validation)
- Authorization (Policies and Gates)
- Database Transactions (
DB::transactionand rollback) - Events & Queues (dispatched events and jobs)
- Database Writes (Eloquent/Query Builder persistence)
- Suppressions Engine: Ignore recommendations using native PHP 8 attributes (
#[TestAdvisorIgnore]), inline comments (// laratest-advisor-ignore), or local YAML configuration profiles. - Anti-Hallucination Prompting: Generates a tailored structured AI prompt containing the original source code and mapped scenarios, forcing the AI to create bulletproof Pest tests.
- Multiple Output Formats: Styled terminal output via Termwind, structured JSON with official Schema validation, or detailed Markdown reports.
Technical Documentation
The advisor's internal architecture, rules engine, risk model, suppressions, and scenario consolidation are documented in docs/architecture.md. The official contract for creating and evolving rules is documented in docs/rules-contract.md.
Installation & Setup
Prerequisites
- PHP >= 8.2
- Composer
Step by Step
- Clone the project and install dependencies:
composer install
- Make the CLI executable executable:
chmod +x laratest-advisor
Usage
To analyze any class or PHP file from your Laravel application:
1. Default Terminal Output (Styled)
./laratest-advisor analyze example-classes/CancelStockTransferAction.php
Terminal output:
LARA TEST ADVISOR v1.0.0
────────────────────────────────────────────────────────────
STRUCTURAL COMPLEXITY:
MEDIUM (0.30)
• Moderate Dependency Coupling Detected
OPERATIONAL RISK:
HIGH (0.70)
• Database Transaction Detected
• Multiple Database Writes Detected
• Collaborator Side Effect Detected
OVERALL RISK:
HIGH (0.62)
• Moderate Dependency Coupling Detected
• Database Transaction Detected
• Multiple Database Writes Detected
• Collaborator Side Effect Detected
────────────────────────────────────────────────────────────
Class: Modules\Inventory\Actions\StockTransfer\CancelStockTransferAction
Location: example-classes/CancelStockTransferAction.php
Classification: ACTION (100%) GENERIC_SERVICE (10%)
────────────────────────────────────────────────────────────
RECOMMENDED SCENARIOS (9)
CRITICAL should roll back database changes if a failure occurs during the transaction in method execute (execute())
Rule: transaction.rollback | Type: integration | Evidence: L24, L35
A transactional block (`function(…)`) was detected on line 24. If any internal operation fails, the database state must return to its original state. Consolidated scenario includes: - transaction.rollback.collaborator: should roll back the transaction if collaborator action 'releaseStockLockAction' fails
Arrange/Mock: Simulate a transaction failure (Force collaborator call 'releaseStockLockAction' to throw a test exception OR Force a failure in the persistence method 'save')…
HIGH should persist the entity with its changed status/mutation after 'markCancelled' in method execute (execute())
Rule: database.write.model_mutation_followed_by_save | Type: integration | Evidence: L40, L41
The action performs the transition '$transfer->markCancelled()' and then persists the state using '$transfer->save()' on line 41. The test should validate the persisted state transition, not just the existence of a generic database write…
Arrange/Mock: Execute method 'execute' and verify that the state transition promoted by '$transfer->markCancelled()' was actually persisted in the database after calling '$transfer->save()'. Use assertions such as `assertDatabaseHas` to validate the state change…
HIGH should reject the operation when the domain constraint 'assertBelongsToCompany' is violated (execute())
Rule: domain.guard_call | Type: unit_orchestration | Evidence: L30
The action explicitly validates a domain boundary or invariant via '$transfer->assertBelongsToCompany($command->companyId())' on line 30. The sad-path test should ensure that violating this rule aborts the flow immediately.
Arrange/Mock: Configure the input data or entity state so that the call '$transfer->assertBelongsToCompany($command->companyId())' fails and throws the expected exception. Verify that no later changes are executed or persisted.
HIGH should reject the operation when the domain constraint 'assertCanBeCancelled' is violated (execute())
Rule: domain.guard_call | Type: unit_orchestration | Evidence: L31
The action explicitly validates a domain boundary or invariant via '$transfer->assertCanBeCancelled()' on line 31. The sad-path test should ensure that violating this rule aborts the flow immediately.
Arrange/Mock: Configure the input data or entity state so that the call '$transfer->assertCanBeCancelled()' fails and throws the expected exception. Verify that no later changes are executed or persisted.
MEDIUM should load the expected data through query 'loadCancellableStockTransferQuery' in method execute (execute())
Rule: query.load.dependency | Type: unit_orchestration | Evidence: L25
The query collaborator call '$this->loadCancellableStockTransferQuery->execute($command->companyId(), $command->stockTransferId())' was detected on line 25. The test should verify that the action requests the expected data and handles the query boundary explicitly.
Arrange/Mock: Stub the 'loadCancellableStockTransferQuery' query collaborator. Execute the flow and assert it receives the expected filters or aggregate, then returns the data required by the use case.
MEDIUM should load the expected data through query 'loadCancellableStockLockQuery' in method execute (execute())
Rule: query.load.dependency | Type: unit_orchestration | Evidence: L33
The query collaborator call '$this->loadCancellableStockLockQuery->execute($transfer)' was detected on line 33. The test should verify that the action requests the expected data and handles the query boundary explicitly.
Arrange/Mock: Stub the 'loadCancellableStockLockQuery' query collaborator. Execute the flow and assert it receives the expected filters or aggregate, then returns the data required by the use case.
MEDIUM should return DTO with the expected payload in method execute (execute())
Rule: dto.contract.return_value | Type: unit_orchestration | Evidence: L43
The DTO factory call '\Modules\Inventory\DTOs\StockTransfer\CancelStockTransferResultData::fromTransfer($transfer, $command)' was detected on line 43. The test should assert that the response object is assembled from the source state without losing fields or transforming data incorrectly.
Arrange/Mock: Execute the flow and assert the returned DTO contains the expected values copied from the domain state and command input.
MEDIUM should invoke collaborator action 'releaseStockLockAction' with the expected arguments on the success path (execute())
Rule: collaborator.side_effect.invocation | Type: unit_orchestration | Evidence: L35
The success path depends on a critical side effect in another domain boundary executed by '$this->releaseStockLockAction->execute($stockLock, $command->cancelledBy())' on line 35. The test should verify that this collaborator was invoked with the correct payload.
Arrange/Mock: Replace collaborator 'releaseStockLockAction' with a mock or spy. Execute the main flow and verify it was invoked with the expected entity and arguments.
LOW should execute the main flow successfully in method execute (execute())
Rule: happy_path.execution | Type: integration | Evidence: Class Definition
Method 'execute' encapsulates the class's main execution flow with parameters: $command (Modules\Inventory\DTOs\StockTransfer\CancelStockTransferData). Sequential steps detected: wraps the flow in a database transaction (`function(…)`) -> validates a domain invariant…
Arrange/Mock: Provide the ideal typical parameters ($command (Modules\Inventory\DTOs\StockTransfer\CancelStockTransferData)), configure doubles/mocks to succeed on the identified calls, execute method 'execute', and verify that the returned result matches the expected type…
────────────────────────────────────────────────────────────
Evidence strictly based on static AST analysis. Use --prompt to get structured prompt.
2. Export as Structured JSON (Per Official Schema)
./laratest-advisor analyze example-classes/CancelStockTransferAction.php --format json
You can specify a destination file using -o or --output-file:
./laratest-advisor analyze example-classes/CancelStockTransferAction.php --format json --output-file report.json
3. Export Detailed Markdown Report
./laratest-advisor analyze example-classes/CancelStockTransferAction.php --format markdown -o REPORT.md
4. Generate the Ideal Prompt for AI to Create Tests
./laratest-advisor analyze example-classes/CancelStockTransferAction.php --prompt
Configuring Suppressions
LaraTestAdvisor supports three ways to granularly silence warnings or irrelevant scenarios:
1. Native PHP 8 Attribute
Use the #[TestAdvisorIgnore] attribute passing the rule ID at class or method scope:
use App\Attributes\TestAdvisorIgnore; class PostPolicy { // Ignores all authorization rules for the delete method #[TestAdvisorIgnore('authorization.checks')] public function delete(User $user, Post $post): bool { return $user->isAdmin(); } }
2. Inline Comment
Insert an inline comment immediately before or inside the method:
public function execute(array $data): array { // laratest-advisor-ignore transaction.rollback return DB::transaction(function () use ($data) { // ... }); }
3. YAML Configuration Profile (laratest-advisor.yaml)
Create a laratest-advisor.yaml file at the root of your project to disable rules on specific files:
suppressions: - file: "example-classes/CancelStockTransferAction.php" ruleId: "transaction.rollback" reason: "The database infrastructure handles this globally."
Running the Project's Tests
The official local validation commands are centralized in the Makefile:
make test
make analyse
make check
make testruns the Pest test suite.make analyseruns PHPStan with the phpstan.neon configuration.make checkruns the full local gate: tests, static analysis, and architecture validation when tests exist intests/Architecture.make precommitis an alias formake checkfor use in local hooks.
Suite organization
tests/Unit/Parser/covers parsing, classification, and metadata extraction.tests/Unit/Inference/covers suppressions and scenario consolidation.tests/Unit/Scorer/covers the risk model.tests/Unit/Formatter/covers output serialization.tests/Feature/CLI/covers theanalyzecommand.tests/Fixtures/contains the input files used by the suite.
To run LaraTestAdvisor's internal quality tests directly with Pest:
./vendor/bin/pest
All tests validate real engine scenarios against complex fixture files (including compliance tests against the official JSON Schema located at resources/schema/analysis-result.schema.json).
License
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog
See CHANGELOG for the release history.
Contributing
See CONTRIBUTING for development setup and guidelines.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 0
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-24
