Files
City10/.claude/skills/testing-best-practices/rules/performance.md
T
marcocosta10000 79ce2a1825 feat(world): add persistent citizen simulation with needs, jobs, and social features
- Adds Character model with survival needs (hunger, thirst, energy) and state machine
- Implements city:tick world ticker for offline progression every minute
- Adds city territory expansion and building construction system
- Introduces job economy, inventory, and transaction audit trail
- Adds social graph (friends, marriage, children) and character chat
- Implements admin approval workflow for new registrations
- Adds hospital admission system for traffic accidents
- Includes comprehensive feature tests and world seeders
2026-10-17 21:46:23 -03:00

2.7 KiB

Test Suite Performance

These settings apply to the project and CI, not to individual tests. Read rules/isolation.md for choices within a test.

Fetch the PHPUnit 12.5.40 documentation at https://phpunit.de/documentation.html for PHPUnit options that make test runs faster. Verify each flag in the documentation before adding it to CI.

Measure before changing a setting. Find the slow test first, and apply a project-wide setting only after identifying the costly work.

Test Environment

  • Set BCRYPT_ROUNDS=4 in .env.testing or in phpunit.xml. The default value is 12, and the hash then takes most of the time of each test that signs a user in.
  • Disable XDebug. Disable pcov also, unless the run needs the coverage.
  • Disable packages that perform work on every request in the test environment. Examples are Pulse, Telescope, and Nightwatch.
  • Use the WithCachedConfig and WithCachedRoutes traits, so the run does not parse the configuration and the routes for every test.
  • Call withoutVite(), or withoutMix(), so the framework does not resolve a built asset.

Global Fakes

Put these three calls in the setUp() of the base TestCase of the project:

  • Http::preventStrayRequests(), because one request that reaches the network can slow the suite. This catches requests made through Laravel's HTTP client. Check direct Guzzle and cURL usage separately.
  • Sleep::fake(syncWithCarbon: true), so a retry and a backoff do not sleep.
  • Exceptions::fake(), so the suite does not report an exception to an external service.

How to Run the Suite in Parallel

Run php artisan test --parallel, which uses ParaTest, to spread tests across the machine's CPU cores. Add --processes=N if the default count is unsuitable for the machine or CI.

A parallel run gives each process a separate database. Tests must meet these conditions; a test that fails only in parallel breaks one of them:

  • The test creates each record that it reads. It does not read a record that another test creates.
  • The test does not depend on the order of the run.
  • The test does not share a file, a cache key, or a queue with another test. Give each process a separate name for such a resource.

How to Find a Slow Test

Run php artisan test --profile to list the slowest tests. Start with the ten slowest tests, because the same cause often applies to the complete suite.

If the cause of a slow test is unclear, add an event listener or temporary log entry to identify its work.

Common Errors

  • The run loads XDebug for a test that does not need it.
  • BCRYPT_ROUNDS keeps the default value, because the project has no .env.testing.
  • The code under test calls the real sleep(), and Sleep::fake() then does not help.