Testo - extensible PHP testing framework. Tests without TestCase inheritance, middleware architecture, PSR-14 events, separate Assert/Expect facades.
docs/ # English (root)
├── index.md # Home page
├── docs/ # Documentation pages
└── .vitepress/
├── config.mts # Config: nav, sidebar, locales
└── theme/style.css # Custom styles (dough colors)
ru/ # Russian locale (same structure)
Tone: Informal but technically accurate. Code examples over explanations.
Home page rules:
- DON'T show code in features (text only, 1 sentence each)
- Don't mention competitors, use "old solutions"
Code examples:
- List of options first, then one code block with all examples (easier to read than many small blocks)
- Keep examples compact — show structure, not implementation (when implementation doesn't matter)
- Show contrast between approaches in examples
Text structure:
- Avoid tautology in lists, fix typos
- Small sections sometimes better integrated into existing ones
Markdown: Use ::: tip, ::: warning, ::: info blocks
Adding pages:
- Create both
docs/page.md(EN) andru/docs/page.md(RU) - Add to sidebar in
.vitepress/config.mtsfor both locales - Internal links:
./pageor/docs/page(no.html)
Syncing translations:
- CRITICAL: When changing documentation content (adding sections, examples, explanations), ALWAYS update BOTH English and Russian versions
- This applies to content changes, NOT just translation quality fixes
- If you modify
docs/page.md, you MUST also updateru/docs/page.mdwith the translated version - Exception: Only fixing translation quality in
ru/doesn't require touching English version
Dead links: Create stub with ::: tip Coming Soon block
Styles: .vitepress/theme/style.css - brand colors --vp-c-brand-1, responsive breakpoints 960px/640px
Adding blog posts:
- Create both
blog/post.md(EN) andru/blog/post.md(RU) - Add link to
blog/index.mdandru/blog/index.md
Required frontmatter:
---
title: "Post Title"
date: 2025-01-01
description: "Short description for RSS and sharing"
image: /blog/post-name/preview.jpg
author: Author Name
---title,date,description— required for RSSimage— used for preview in blog list, og:image for social sharing, and displayed in post headerauthor— displayed in blog list and post header
Optional frontmatter:
outline— controls heading levels shown in the right sidebar (table of contents):outline: [2, 3]— show h2 and h3 (default behavior)outline: 'deep'— show all levels (h2-h6)outline: false— hide outline completelyoutline: 2— show only h2
Testo provides llms.txt for AI agents. Only docs/ pages are included — blog posts are excluded from llms generation entirely (no llms frontmatter in blog files).
Manifest: llms.config.ts — project-level metadata (title, summary, key facts, base URL). Edit when project description or key facts change.
Generator: .vitepress/llms.ts — builds llms.txt, llms-full.txt, and per-page .md files during buildEnd. Only scans docs/ directory.
Frontmatter fields (English docs/ pages only, not ru/ or blog/):
---
llms: true # default — included in "Docs" section
llms: "optional" # included in "Optional" section (secondary content)
llms: false # excluded from llms.txt
llms_description: "Technical description of what LLM learns from this page"
---llms— controls inclusion. Default istrue(can be omitted)."optional"for secondary content,falseto excludellms_description— short, technical description for LLM context. Lists key entities and concepts, not marketing text. Required for all included pages
Guidelines for llms_description:
- List specific classes, attributes, methods — not vague descriptions
- Example:
"#[BeforeEach], #[AfterEach], #[BeforeAll], #[AfterAll] lifecycle hooks, execution order, priority" - NOT:
"Learn about test lifecycle management"
When adding new doc pages: add llms_description to the English version frontmatter. Do NOT add llms frontmatter to blog posts.
npm run docs:dev # Dev server at localhost:5173
npm run docs:build # Build to .vitepress/dist/
npm run docs:preview # Preview buildFile: .vitepress/config.mts
locales: root (EN) +ru(RU) with separate nav/sidebarcleanUrls: true,lastUpdated: true,search.provider: 'local'- Nav and Sidebar defined in
themeConfigfor each locale - Sidebar sections: Introduction, Guide, Customization
-
Естественность важнее дословности
- Перевод должен звучать так, как говорят русские разработчики
- Избегать кальки с английского, если это звучит неестественно
-
Сохранять технические термины
- Не переводить названия классов, методов, атрибутов, пакетов
- Оставлять код примеры без изменений
| Английский | ❌ Неправильно | ✅ Правильно | Примечание |
|---|---|---|---|
| test | — | тест | Один метод теста или InlineTest |
| test case | тестовый случай | Test Case / тест-кейс / тестовый класс / класс тестов / набор тестов | Класс/файл с тестами. Выбор зависит от контекста |
| test suite | тестовый набор | Test Suite / комплект тестов | Глобальная группа (Unit, Feature). Предпочтительно без перевода |
| data provider | поставщик данных | провайдер данных | |
| dataset | — | датасет / набор данных | Оба допустимы |
| callable | вызываемый | вызываемый объект | В контексте |
| closure | закрытие | замыкание |
Важно понимать правильную иерархию компонентов:
- Test Suite (комплект тестов) - Unit, Integration, Feature
- События:
TestSuite*(TestSuiteStarting, TestSuiteFinished)
- События:
- Test Case (тестовый класс) - UserTest, OrderTest
- События:
TestCase*(TestCaseStarting, TestCaseFinished)
- События:
- Test (тестовый метод или функция) - testLogin(), testCreate()
- События:
Test*(TestStarting, TestFinished, TestBatchStarting)
- События:
| Английский | ❌ Неправильно | ✅ Правильно |
|---|---|---|
| Simple as that | Просто как это | Вот так просто |
| right on the method | прямо на методе | непосредственно над методом |
-
Избегать канцеляризмов
- Вместо "тестовый случай" → "тест"
- Вместо "осуществить проверку" → "проверить"
-
Сохранять тон оригинала
- Если оригинал неформальный и дружелюбный — перевод тоже
- Технические термины оставлять точными
-
Порядок слов
- Использовать естественный русский порядок слов
- Не копировать английскую структуру предложения
-
Термин + конкретное значение
- При упоминании технического термина с конкретным значением использовать дефис для разделения
- Примеры:
- ✅ "Test Suite - Unit" (не "Test Suite Unit")
- ✅ "комплект тестов Unit" (альтернатива)
- ✅ "провайдер данных - UserDataProvider"
Перед финализацией перевода задать вопросы:
- Так ли говорят русские разработчики?
- Звучит ли фраза естественно при чтении вслух?
- Сохранен ли технический смысл оригинала?