nette/claude-code/nette-tester
- community
Checking that the SKILL.md file is still in the repository.
Use this skill whenever writing, modifying, or running .phpt test files with Nette Tester. Invoke for any task involving Tester\Assert methods (Assert::same, Assert::match, Assert::exception, etc.), test bootstrap setup, vendor/bin/tester commands, or debugging failing test output (.expected/.actual files). Also use when the user needs to write tests for a Nette project and asks about test structure, the test() function, testException(), or assertion methods. This skill is specifically for Nette Tester – do not use for PHPUnit, Pest, Jest, Vitest, or other testing frameworks, and do not use for general PHP testing without Nette context.
Install
npx vskill@latest install nette/claude-code/nette-testerSKILL.md
Testing with Nette Tester
Nette Tester is a testing framework for PHP. Test files use the .phpt extension by convention; the runner also collects *Test.php.
Two failure modes worth knowing before writing a single test:
- A test that executes no assertion is an error – `Error: This test forgets to execute an
assertion. (exit code 178). It is on by default via Environment::setup()`.
- `exit()` / `die()` in a test ends it with code 0, i.e. as a PASS. Use
Assert::fail()to
fail deliberately.
Bootstrap File
The bootstrap file should set up the Tester environment and enable helper functions:
Basic Test Structure
Key points:
- Use the
test()function for each test case - The first parameter of
test()should be a clear description of what is being tested - Do not add comments before
test()calls - the description parameter serves this purpose - Group related tests in the same file
- Test file naming:
{ClassName}.phptor{ClassName}.{feature}.phpt
Test Annotations
In the first docblock of the test file, before require. Case-insensitive; no effect when the file is run as plain php test.phpt. The first non-@ line is the test title (written TEST: ...).
| Annotation | Syntax | Notes | |
|---|---|---|---|
@skip | – | always skipped | |
@phpVersion | [op] version | op: <= < == = != <> >= >, default >= | |
@phpExtension | pdo, pdo_mysql | comma/space separated; repeatable | |
@dataProvider | file.ini[, query] | path relative to the test file; a .php file returning array/Traversable works too | |
@dataProvider? | ? file.ini | leading ? = skip (not fail) when the file is missing | |
@multiple | N | runs the file exactly N times | |
@testCase | – | file holds a Tester\TestCase; runner runs each method in its own process | |
@exitCode | N | default 0 | |
@outputMatch / @outputMatchFile | pattern / file | Assert::match / matchFile against stdout | |
@phpIni | key=value | same as the runner's -d key=value; repeatable |
Trap — `@phpVersion` with an exact version. The skip condition is version_compare(annotation, actualPhpVersion, op), so equality skips. @phpVersion 8.4.3 on PHP 8.4.3 is skipped; write two components (@phpVersion 8.4), which sorts below 8.4.0 and therefore runs.
In the @dataProvider file form the test loads its own data set: $args = Tester\Environment::loadData(); — called once per run, returning one INI section. INI is parsed with INI_SCANNER_TYPED (values arrive typed). The optional query filters sections: its tokens are matched left to right against the whitespace-separated parts of the section name, operators <= =< < == = != <> >= => > (bare token = =), numeric tokens compared by version_compare. So @dataProvider databases.ini postgresql, >=9.0 selects [postgresql 9.1].
Tester\TestCase
- Discovery pattern is
#^test[A-Z0-9_]#:testArea,test_area,test2are tests — `testarea` silently is not. - A
test*method must bepublic; a protected one is discovered, then fails withMethod X is not public. Make it public or rename it. - Forgetting `->run()`: with
@testCasethe runner reportsCannot list TestCase methods in file '…'. Do you call TestCase::run() in it?; without it the file merely defines a class and dies asThis test forgets to execute an assertion.(exit 178). - Order per method:
setUp(), test,tearDown(). If the test throws,tearDown()still runs but errors inside it are suppressed. A failure insetUp()/tearDown()fails the test. - In v2.6.1
run()aborts at the first failing method;@testCasesidesteps that by isolating each method. $this->skip('reason')skips the current method from anywhere inside it.
The provider returns an array/Traversable of arrays. String-keyed sets are merged over the method's parameter defaults; list-keyed sets are passed positionally. A method with required parameters and no @dataProvider throws TestCaseException.
Assertions Overview
Assert::same($expected, $actual)- strict identity (===)Assert::notSame($expected, $actual)- not strictly equalAssert::equal($expected, $actual)- loose comparison (ignores object identity, array key order, float epsilon)Assert::notEqual($expected, $actual)Assert::true($actual),Assert::false($actual),Assert::null($actual),Assert::notNull($actual)Assert::truthy($actual),Assert::falsey($actual)Assert::contains($needle, $haystack)- checks substring or array element; avoid for testing output (see warning below)Assert::notContains($needle, $haystack)Assert::hasKey($key, $array),Assert::hasNotKey($key, $array)Assert::count($count, $value)Assert::type($type, $value)- class/interface or built-in type ('string','int','list', etc.)Assert::match($pattern, $actual)- pattern matching with placeholders (see below)Assert::matchFile($file, $actual)- pattern loaded from fileAssert::exception($fn, $class, $message, $code)- asserts exception is thrownAssert::error($fn, $type, $message)- asserts PHP error/warning/deprecation is generatedAssert::noError($fn)- asserts no errors or exceptions
Warning about Assert::contains: Do not use Assert::contains() for testing generated output (HTML, text, etc.). It only checks for a substring - the test will pass even if the output contains errors or is completely broken, as long as the needle appears somewhere. Use Assert::match() or Assert::matchFile() instead, which verify the entire structure of the output.
Pattern Matching with Assert::match
Assert::match($pattern, $actual) compares a string against a pattern with placeholders. Assert::matchFile($file, $actual) works the same way but loads the pattern from a file.
Available placeholders:
| Pattern | Meaning | |
|---|---|---|
%a% | one or more of anything except end of line | |
%a?% | zero or more of anything except end of line | |
%A% | one or more of anything including end of line | |
%A?% | zero or more of anything including end of line | |
%s% / %s?% | one or more / zero or more whitespace (except EOL) | |
%S% / %S?% | one or more / zero or more non-whitespace | |
%c% | a single character (except end of line) | |
%d% / %d?% | one or more / zero or more digits | |
%i% | signed integer | |
%f% | floating point number | |
%h% | one or more HEX digits | |
%w% | one or more alphanumeric characters | |
%ds% | directory separator (/ or \) | |
%% | literal % character |
Important behavior:
- Ungreedy matching - placeholders match as little text as possible, so
%a%captures the shortest possible string - Line endings are normalized -
\r\nand\nare treated as equivalent, so tests work cross-platform - Trailing whitespace is ignored
- Patterns can also be raw regexps delimited by
~or#
When Assert::matchFile() fails, the expected and actual output are written to the test output directory as .expected and .actual files.
Testing Exceptions
For simple single-call exceptions, use the concise fn() style:
The Assert::exception() method:
- First parameter: A closure that should throw the exception
- Second parameter: Expected exception class
- Third parameter (optional): Expected exception message, can contain match placeholders (
%a%,%s%, etc.)
For testing PHP errors and deprecations:
If the entire test() block is to end with an exception, you can use testException():
Assert::exception() returns the exception
The 3rd argument is an Assert::match pattern, the 4th compares getCode() strictly. The caught exception is returned, so a previous/nested one can be asserted further. Assert::throws() is a plain alias.
setUp() for Shared Setup
Use setUp() to run common initialization before each test() block:
Helpers
| Call | Purpose | ||
|---|---|---|---|
DomQuery::fromHtml($html) / ::fromXml($xml) | CSS querying; extends SimpleXMLElement, so text is (string) $el, attributes $el['href']. find($sel): list<DomQuery>, has($sel), matches($sel) (2.5.3), closest($sel) (2.5.5, needs PHP 8.4) | ||
FileMock::create(string $content = '', ?string $extension = null): string | returns a mock://N.ext URL usable with fopen, file_get_contents, parse_ini_file, … | ||
Helpers::purge(string $dir): void | creates the dir, wipes its contents; throws on an empty string or a root path | ||
Environment::lock(string $name, string $path): void | serializes parallel tests; the only sane fix for several tests hitting one database | ||
Environment::skip(string $message = ''): void | skips the running test | ||
| `Assert::with(object\ | string $objectOrClass, Closure $fn): mixed` | runs $fn bound to the object so $this reaches private members (a class-string binds statically); returns the closure's value |
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingplugins/nette/skills/nette-tester/SKILL.md
Popularity
- Repository stars
- 37
- Repository forks
- 4
- 7-day trend score
- 18
Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 21 Mar 2026, 7 months ago.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/nette/claude-code/nette-tester)