

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
12345678910# Cross-Cutting Testing Standards1112## Testing Philosophy1314### Test Pyramid15- **Unit Tests (70%)**: Fast, isolated16- **Integration Tests (20%)**: Component interactions17- **E2E Tests (10%)**: Complete workflows1819### What to Test20✅ **Do test:**21- Business logic22- Edge cases and errors23- API contracts24- Critical workflows25- Data transformations2627❌ **Don't test:**28- Third-party library internals29- Trivial getters/setters30- Framework code3132## Test Organization3334Python (hermes-api):35```36tests/37├── conftest.py # Shared fixtures38├── test_api/ # API tests39├── test_integration/ # Integration tests40├── test_services/ # Service tests41└── test_tasks/ # Task tests42```4344TypeScript (hermes-app):45```46src/47├── components/__tests__/ # Component tests48├── hooks/__tests__/ # Hook tests49└── services/__tests__/ # Service tests50```5152### File Naming53- Python: `test_*.py`54- TypeScript: `*.test.ts`, `*.test.tsx`55- Match test file to source file name5657## Test Structure5859### Arrange-Act-Assert60```python61def test_create_user():62 # Arrange63 user_data = {"username": "test", "email": "test@example.com"}6465 # Act66 result = create_user(user_data)6768 # Assert69 assert result.username == "test"70 assert result.id is not None71```7273### Test Naming74Follow: `test_<what>_<condition>_<expected>`7576```python77# ✅ Good78def test_create_download_valid_url_returns_download():79def test_get_download_not_found_raises_404():8081# ❌ Bad82def test_download():83def test_1():84```8586## Best Practices8788### Test Independence89- Each test runs independently90- Don't rely on order91- Clean up after tests92- Use fresh data9394### Single Assertion Concept95```python96# ✅ Good - One concept (user creation)97def test_create_user():98 user = create_user({"username": "test"})99 assert user.username == "test"100 assert user.id is not None101 assert user.created_at is not None102103# ❌ Bad - Multiple concepts104def test_user_workflow():105 user = create_user({"username": "test"})106 updated = update_user(user)107 delete_user(user.id)108```109110### Descriptive Assertions111```python112assert response.status_code == 200, f"Expected 200, got {response.status_code}"113assert len(downloads) > 0, "Should return downloads"114assert "id" in data, "Missing required 'id' field"115```116117## Mocking118119### When to Mock120- External API calls121- File system operations122- Database calls (in unit tests)123- Time-dependent code124- Slow operations125126### Python127```python128def test_fetch_video(mocker):129 mock_api = mocker.patch("app.services.yt_dlp_service.extract_info")130 mock_api.return_value = {"title": "Test", "duration": 120}131132 result = get_video_info("https://example.com")133134 assert result["title"] == "Test"135 mock_api.assert_called_once()136```137138### TypeScript139```typescript140test("fetches user", async () => {141 const mockFetch = jest.fn().mockResolvedValue({142 json: async () => ({ id: "1", name: "Test" }),143 });144 global.fetch = mockFetch;145146 const user = await fetchUser("1");147 expect(user.name).toBe("Test");148});149```150151## Test Data152153### Fixtures (Python)154```python155@pytest.fixture156def test_user():157 return {158 "username": "testuser",159 "email": "test@example.com"160 }161162@pytest.fixture163def test_download(test_user):164 return {165 "url": "https://example.com/video",166 "user_id": test_user["id"]167 }168```169170### Builders171```python172class DownloadBuilder:173 def __init__(self):174 self.data = {"url": "https://example.com", "status": "queued"}175176 def with_url(self, url: str):177 self.data["url"] = url178 return self179180 def build(self):181 return self.data182183# Usage184download = DownloadBuilder().with_status("completed").build()185```186187## Coverage188189### Running Coverage190Python:191```bash192pytest --cov=app --cov-report=html193```194195TypeScript:196```bash197npm test -- --coverage198```199200### Goals201- Aim for 80%+ on critical code202- 100% not required203- Focus on meaningful coverage204- Prioritize complex logic205206## Performance207208### Mark Slow Tests209```python210@pytest.mark.slow211def test_large_download():212 pass213214# Run fast tests only215# pytest -m "not slow"216```217218## Integration Testing219220```python221@pytest.mark.integration222async def test_full_flow(db_session, test_user):223 repos = await get_repositories()224225 # Create226 download = await repos["downloads"].create({227 "url": "https://example.com",228 "user_id": test_user.id229 })230231 # Verify232 retrieved = await repos["downloads"].get_by_id(download.id)233 assert retrieved is not None234```235236## Error Testing237238```python239def test_invalid_url():240 with pytest.raises(ValidationError) as exc:241 create_download("not-a-url")242 assert "Invalid URL" in str(exc.value)243244def test_not_found():245 with pytest.raises(HTTPException) as exc:246 get_download("nonexistent")247 assert exc.value.status_code == 404248```249250## CI Integration251252- Run full suite on every commit253- Run linting and type checking254- Generate coverage reports255- Fail build on failures256257### Skip in CI258```python259@pytest.mark.skipif(260 os.getenv("CI") == "true",261 reason="Requires external service"262)263def test_external():264 pass265```266267## Documentation268269```python270def test_download_formats():271 """Test various supported URL formats."""272 urls = [273 "https://www.youtube.com/watch?v=abc",274 "https://youtu.be/abc",275 ]276 for url in urls:277 result = parse_url(url)278 assert result is not None, f"Failed: {url}"279```280
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 46 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-app.mdc · 46 | Cursor rules | lint-formatstylearchtypes+5 | 88/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-api.mdc · 46 | Cursor rules | stylearchdependenciesapi+2 | 77/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 46 | Cursor rules | teststyletesting-strategysecurity+3 | 97/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-app-components.mdc · 46 | Cursor rules | archtypesuiperformance+1 | 65/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-app-routes.mdc · 46 | Cursor rules | archapiuido-not | 65/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/30-docker.mdc · 46 | Cursor rules | setupbuildstylesecurity+4 | 84/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/00-project.mdc · 46 | Cursor rules | setuplint-formatstylearch+4 | 89/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-db.mdc · 46 | Cursor rules | teststylearchtesting-strategy+3 | 73/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-app-hooks.mdc · 46 | Cursor rules | lint-formatstylearchtypes+3 | 73/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/30-docs.mdc · 46 | Cursor rules | setuplint-formatstylearch+3 | 81/100 | 14 days ago |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126 | Cursor rules | setupbuildtestlint-format+6 | 100/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 46 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 14 days ago | |
| Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| markstev/mark-starter.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+6 | 99/100 | 14 days ago | |
| langflow-ai/langflow.cursor/rules/docs_development.mdc · 153k | Cursor rules | setupbuildtestlint-format+7 | 97/100 | 14 days ago | |
| bybren-llc/safe-agentic-workflow.cursor/rules/10-backend-python.mdc · 399 | Cursor rules | testlint-formatstylegit+4 | 97/100 | today |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/techsquidtv-hermes-cursor-rules-30-tests)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.