Skip to content

Testing

Sascha Greuel edited this page Aug 2, 2026 · 1 revision

Tests and fixture generation

Home · Adding a protocol · Contributing

GameQ's protocol suite replays captured responses without contacting live game servers. This protects old and poorly documented protocols from regressions when shared parsers change.

Install development dependencies

composer install

Complete quality suite

composer test

This runs:

  1. parallel PHP syntax checks;
  2. the PSR-12/PHPCS ruleset;
  3. PHPStan at maximum level;
  4. PHPUnit.

Also run when relevant:

composer validate --strict
composer audit
composer bc-check

composer bc-check compares public and protected APIs with GameQ 4.0.0 and should be run before changing an extension point.

Run a focused test

vendor/bin/phpunit tests/Protocols/Source.php
vendor/bin/phpunit --filter 'GameQ\\Tests\\Protocols\\Source'

Use a focused test while iterating, then run composer test before considering the change complete.

Generate a protocol fixture

The extensionless CLI script queries one real server and stores its raw and parsed responses:

php tests/Protocols/generate_provider \
    -p css \
    -s 192.0.2.10:27015

Pass per-server options as JSON:

php tests/Protocols/generate_provider \
    -p teamspeak3 \
    -s 192.0.2.10:9987 \
    -o '{"query_port":10011}'

The script writes pairs beneath tests/Protocols/Providers/<Protocol>/:

1_response.txt
1_result.json
2_response.txt
2_result.json

Raw response files are binary even when their extension is .txt. Do not normalize encoding or line endings.

Fixture quality

Capture several representative cases where possible:

  • zero and many players;
  • split and unsplit packets;
  • optional fields present and absent;
  • passworded and public servers;
  • multiple server/game versions;
  • pagination or challenge variants;
  • malformed/truncated synthetic packets for validation paths.

Query a server normally before capturing it. An offline server only creates an unhelpful empty fixture.

Prefer a stable IP in recorded server metadata. Tests never contact the recorded game server, but legacy fixtures can still contain hostnames that code attempts to resolve. Use MockDNS in a test when a meaningful hostname must remain stable.

Secrets and privacy

Fixtures can contain player names, addresses, rules, server descriptions, tokens, and other operational data. Never commit:

  • administrator passwords;
  • query-plugin tokens or administration codes;
  • API usernames and passwords;
  • private master endpoints;
  • internal addresses or identifiers that should not be public.

Use synthetic responses for credentialed HTTP protocols. Existing tests inject decoded API/master responses specifically to avoid live network calls and secrets.

Test class conventions

  • Mirror src/GameQ/Protocols/Examplegame.php with tests/Protocols/Examplegame.php.
  • Extend GameQ\Tests\Protocols\Base for fixture-driven named protocols.
  • Test packet bytes and challenge/follow-up behavior for a new wire protocol.
  • Assert invalid headers, lengths, counts, truncation, and oversized values.
  • Add issue regressions under tests/Issues/Issue<number>.php when the issue spans more than one normal protocol fixture.
  • Let unexpected exceptions fail the test; do not catch them merely to make the suite green.

Updating expected results

Review fixture-result changes manually. A mass rewrite can hide a parser regression. Confirm that changed native and normalized fields reflect an intentional behavior change, then update the relevant changelog entry.

Clone this wiki locally