[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6HV97THARTD4WDS2HX01DDC":3,"skill-same:01M6HV97THARTD4WDS2HX01DDC":51},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":26,"linkOnly":27,"markdownContent":28,"markdownBody":28,"frontMatter":29,"refName":30,"commitSha":31,"skillDirectory":32,"forksCount":33,"repositoryHtmlUrl":34,"repositoryHomepageUrl":6,"ownerHtmlUrl":35,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":36,"install":37,"resources":50},"01M6HV97THARTD4WDS2HX01DDC","test-runner",null,"Silex-Research\u002FDontPanic","Silex-Research","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F130925891?v=4","01M6HV5K48NKSZT37SQKSV639D","Silex Research","01M6HV5K8R2281GSJB6S9A5TF8",5,"Apache-2.0","https:\u002F\u002Fgithub.com\u002FSilex-Research\u002FDontPanic\u002Fblob\u002Fmain\u002Fclaude\u002Fskills\u002Ftest-runner\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[23,24,25],"test","test runner","runner","2026-11-10 10:12:30",false,"# test-runner\n\nWrite and run tests across languages and frameworks.\n\n## Framework Selection\n\n| Language | Unit Tests | Integration | E2E |\n|----------|-----------|-------------|-----|\n| TypeScript\u002FJS | Vitest (preferred), Jest | Supertest | Playwright |\n| Python | pytest | pytest + httpx | Playwright |\n| Swift | XCTest | XCTest | XCUITest |\n\n## Quick Start by Framework\n\n### Vitest (TypeScript \u002F JavaScript)\n```bash\nnpm install -D vitest @testing-library\u002Freact @testing-library\u002Fjest-dom\n```\n\n```typescript\n\u002F\u002F vitest.config.ts\nimport { defineConfig } from 'vitest\u002Fconfig'\nexport default defineConfig({\n  test: {\n    globals: true,\n    environment: 'jsdom',\n    setupFiles: '.\u002Ftests\u002Fsetup.ts',\n  },\n})\n```\n\n```bash\nnpx vitest              # Watch mode\nnpx vitest run          # Single run\nnpx vitest --coverage   # With coverage\n```\n\n### Jest\n```bash\nnpm install -D jest @types\u002Fjest ts-jest\n```\n\n```bash\nnpx jest                # Run all\nnpx jest --watch        # Watch mode\nnpx jest --coverage     # With coverage\nnpx jest path\u002Fto\u002Ftest   # Single file\n```\n\n### pytest (Python)\n```bash\nuv pip install pytest pytest-cov pytest-asyncio httpx\n```\n\n```bash\npytest                          # Run all\npytest -v                       # Verbose\npytest -x                       # Stop on first failure\npytest --cov=app                # With coverage\npytest tests\u002Ftest_api.py -k \"test_login\"  # Specific test\npytest --tb=short               # Short tracebacks\n```\n\n### XCTest (Swift)\n```bash\nswift test                      # Run all tests\nswift test --filter MyTests     # Specific test suite\nswift test --parallel           # Parallel execution\n```\n\n### Playwright (E2E)\n```bash\nnpm install -D @playwright\u002Ftest\nnpx playwright install\n```\n\n```bash\nnpx playwright test                    # Run all\nnpx playwright test --headed           # With browser visible\nnpx playwright test --debug            # Debug mode\nnpx playwright test --project=chromium # Specific browser\nnpx playwright show-report             # View HTML report\n```\n\n## TDD Workflow\n\n1. **Red** — Write a failing test that describes the desired behavior.\n2. **Green** — Write the minimum code to make the test pass.\n3. **Refactor** — Clean up the code while keeping tests green.\n\n```\n┌─────────┐     ┌─────────┐     ┌──────────┐\n│  Write   │────▶│  Write  │────▶│ Refactor │──┐\n│  Test    │     │  Code   │     │  Code    │  │\n│  (Red)   │     │ (Green) │     │          │  │\n└─────────┘     └─────────┘     └──────────┘  │\n     ▲                                          │\n     └──────────────────────────────────────────┘\n```\n\n## Test Patterns\n\n### Arrange-Act-Assert\n```typescript\ntest('calculates total with tax', () => {\n  \u002F\u002F Arrange\n  const cart = new Cart([{ price: 100, qty: 2 }]);\n\n  \u002F\u002F Act\n  const total = cart.totalWithTax(0.08);\n\n  \u002F\u002F Assert\n  expect(total).toBe(216);\n});\n```\n\n### Testing Async Code\n```typescript\ntest('fetches user data', async () => {\n  const user = await getUser('123');\n  expect(user.name).toBe('Colt');\n});\n```\n\n### Mocking\n```typescript\nimport { vi } from 'vitest';\n\nconst mockFetch = vi.fn().mockResolvedValue({\n  json: () => Promise.resolve({ id: 1, name: 'Test' }),\n});\nvi.stubGlobal('fetch', mockFetch);\n```\n\n### Testing API Endpoints (Python)\n```python\nimport pytest\nfrom httpx import AsyncClient\nfrom app.main import app\n\n@pytest.mark.asyncio\nasync def test_get_users():\n    async with AsyncClient(app=app, base_url=\"http:\u002F\u002Ftest\") as client:\n        response = await client.get(\"\u002Fusers\")\n    assert response.status_code == 200\n    assert isinstance(response.json(), list)\n```\n\n### Testing React Components\n```typescript\nimport { render, screen, fireEvent } from '@testing-library\u002Freact';\nimport { Button } from '.\u002FButton';\n\ntest('calls onClick when clicked', () => {\n  const handleClick = vi.fn();\n  render(\u003CButton onClick={handleClick}>Click me\u003C\u002FButton>);\n  fireEvent.click(screen.getByText('Click me'));\n  expect(handleClick).toHaveBeenCalledOnce();\n});\n```\n\n## Coverage Commands\n\n```bash\n# JavaScript\u002FTypeScript\nnpx vitest --coverage          # Vitest (uses v8 or istanbul)\nnpx jest --coverage            # Jest\n\n# Python\npytest --cov=app --cov-report=html    # HTML report\npytest --cov=app --cov-report=term    # Terminal output\npytest --cov=app --cov-fail-under=80  # Fail if \u003C 80%\n\n# View HTML coverage report\nopen coverage\u002Findex.html       # macOS\nopen htmlcov\u002Findex.html        # Python\n```\n\n## What to Test\n\n**Always test:**\n- Public API \u002F exported functions\n- Edge cases: empty input, null, boundary values\n- Error handling: invalid input, network failures\n- Business logic: calculations, state transitions\n\n**Don't bother testing:**\n- Private implementation details\n- Framework internals (React rendering, Express routing)\n- Trivial getters\u002Fsetters\n- Third-party library behavior\n",{},"main","14ffaf54d57448d72d9f32efca397086f3de0e64","claude\u002Fskills\u002Ftest-runner",1,"https:\u002F\u002Fgithub.com\u002FSilex-Research\u002FDontPanic","https:\u002F\u002Fgithub.com\u002FSilex-Research","2026-11-10 08:27:00",{"source":7,"skillName":5,"commands":38,"prompt":48,"zipAvailable":49},[39,42,45],{"tool":40,"command":41},"npx","npx skills add Silex-Research\u002FDontPanic --skill test-runner",{"tool":43,"command":44},"bunx","bunx skills add Silex-Research\u002FDontPanic --skill test-runner",{"tool":46,"command":47},"pnpm","pnpm dlx skills add Silex-Research\u002FDontPanic --skill test-runner","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FSilex-Research\u002FDontPanic\u002Fblob\u002Fmain\u002Fclaude\u002Fskills\u002Ftest-runner\u002FSKILL.md",true,[],[52,67,82,99,117,135],{"skillNo":53,"name":54,"nameZh":6,"description":55,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":56,"categories":57,"keywords":58,"publishedAt":26},"01M6HVB95QJ3TXWYQ4M6F1SGCJ","worktree-isolation","Creates an isolated git worktree.","https:\u002F\u002Fgithub.com\u002FSilex-Research\u002FDontPanic\u002Fblob\u002Fmain\u002Fscripts\u002Fdontpanic_orchestrate\u002Ftests\u002Ffixtures\u002Fskill_rubrics\u002Fworktree-isolation\u002FSKILL.md",[],[59,60,61,62,63,64,65,66],"worktree isolation","isolation","worktree","repo","mutation","implementation","git worktree","git",{"skillNo":68,"name":5,"nameZh":6,"description":69,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":70,"categories":71,"keywords":73,"publishedAt":26},"01M6HVB49HTWVCD3DBH0Y1D84E","Runs the targeted test suite.","https:\u002F\u002Fgithub.com\u002FSilex-Research\u002FDontPanic\u002Fblob\u002Fmain\u002Fscripts\u002Fdontpanic_orchestrate\u002Ftests\u002Ffixtures\u002Fskill_rubrics\u002Ftest-runner\u002FSKILL.md",[72],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[23,24,25,74,75,76,77,78,79,64,80,81],"review","safe","auto","path","evidence","test suite","pytest","output",{"skillNo":83,"name":84,"nameZh":6,"description":85,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":26},"01M6HVAZMH62Z9GTM8GRDN2MEA","subagent-driven-dev","Meta toolkit for dispatching subagents.","https:\u002F\u002Fgithub.com\u002FSilex-Research\u002FDontPanic\u002Fblob\u002Fmain\u002Fscripts\u002Fdontpanic_orchestrate\u002Ftests\u002Ffixtures\u002Fskill_rubrics\u002Fsubagent-driven-dev\u002FSKILL.md",[],[89,90,91,92,93,94,95,96,97,98],"dev","subagent","driven","subagent driven dev","subagents","dispatching subagents","never","for","Meta","toolkit",{"skillNo":100,"name":101,"nameZh":6,"description":102,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":103,"categories":104,"keywords":105,"publishedAt":26},"01M6HVAWTYK3JF6Q7PGBTQBBZH","security-review","Read-only security review of pending changes.","https:\u002F\u002Fgithub.com\u002FSilex-Research\u002FDontPanic\u002Fblob\u002Fmain\u002Fscripts\u002Fdontpanic_orchestrate\u002Ftests\u002Ffixtures\u002Fskill_rubrics\u002Fsecurity-review\u002FSKILL.md",[],[106,107,74,108,109,101,110,111,112,76,113,114,78,115,116],"security review","security","files","run","json","read","skills run","readonly","only","read-only","changes",{"skillNo":118,"name":119,"nameZh":6,"description":120,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":121,"categories":122,"keywords":123,"publishedAt":26},"01M6HVARJ3DCMZH3RZFHAEFJJJ","revenue-check","Reads production revenue dashboards.","https:\u002F\u002Fgithub.com\u002FSilex-Research\u002FDontPanic\u002Fblob\u002Fmain\u002Fscripts\u002Fdontpanic_orchestrate\u002Ftests\u002Ffixtures\u002Fskill_rubrics\u002Frevenue-check\u002FSKILL.md",[],[124,125,126,127,74,128,129,130,131,132,110,111,133,78,134],"revenue","revenue check","check","project","planning","network","Production","dashboards","access","approval","id",{"skillNo":136,"name":137,"nameZh":6,"description":138,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":139,"categories":140,"keywords":144,"publishedAt":26},"01M6HVANBY28H9E38P1T01EEQ5","prompt-optimizer","Optimizes a prompt template.","https:\u002F\u002Fgithub.com\u002FSilex-Research\u002FDontPanic\u002Fblob\u002Fmain\u002Fscripts\u002Fdontpanic_orchestrate\u002Ftests\u002Ffixtures\u002Fskill_rubrics\u002Fprompt-optimizer\u002FSKILL.md",[141],{"categoryNo":142,"categoryName":143,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[145,146,147,148,149,64],"prompt optimizer","prompt","optimizer","template","text"]