{"id":"da64b902-bcc5-450b-8467-b04e8d69ab66","shortId":"7aMbTb","kind":"skill","title":"testing-principles","tagline":"Language-agnostic testing principles including TDD, test quality, coverage standards, and test design patterns. Use when writing tests, designing test strategies, or reviewing test quality.","description":"# Language-Agnostic Testing Principles\n\n## Core Testing Philosophy\n\n1. **Tests are First-Class Code**: Maintain test quality equal to production code\n2. **Fast Feedback**: Tests should run quickly and provide immediate feedback\n3. **Reliability**: Tests should be deterministic and reproducible\n4. **Independence**: Each test should run in isolation\n\n## Test-Driven Development (TDD)\n\n### The RED-GREEN-REFACTOR Cycle\n\n**Always follow this cycle:**\n\n1. **RED**: Write a failing test first\n   - Write the test before implementation\n   - Ensure the test fails for the right reason\n   - Verify test can actually fail\n\n2. **GREEN**: Write minimal code to pass\n   - Implement just enough to make the test pass\n   - Focus on making it work\n\n3. **REFACTOR**: Improve code structure\n   - Clean up implementation\n   - Eliminate duplication\n   - Improve naming and clarity\n   - Keep all tests passing\n\n4. **VERIFY**: Ensure all tests still pass\n   - Run full test suite\n   - Check for regressions\n   - Validate refactoring didn't break anything\n\n### TDD Benefits\n\n- Better design through testability requirements\n- Comprehensive test coverage by default\n- Living documentation of expected behavior\n- Confidence to refactor\n\n## Quality Requirements\n\n### Coverage Standards\n\n- **Minimum 80% code coverage** for production code\n- Prioritize critical paths and business logic\n- Prioritize meaningful assertions over coverage percentage\n- Use coverage as a guide, not a goal\n\n### Test Characteristics\n\nAll tests must be:\n\n- **Independent**: No dependencies between tests (see Test Independence Verification for detailed criteria)\n- **Reproducible**: Same input always produces same output\n- **Fast**: Unit tests < 100ms each, integration tests < 1s each, full suite < 10 minutes\n- **Self-checking**: Clear pass/fail without manual verification\n- **Timely**: Written close to the code they test\n\n## Test Types\n\n### Unit Tests\n\n**Purpose**: Test individual components in isolation\n\n**Characteristics**:\n- Test single function, method, or class\n- Fast execution (milliseconds)\n- No external dependencies\n- Mock external services\n- Majority of your test suite\n\n**Example Scope**:\n```\n✓ Test calculateTotal() function\n✓ Test UserValidator class\n✓ Test parseDate() utility\n```\n\n### Integration Tests\n\n**Purpose**: Test interactions between components\n\n**Characteristics**:\n- Test multiple components together\n- May include database, file system, or APIs\n- Slower than unit tests\n- Verify contracts between modules\n- Smaller portion of test suite\n\n**Example Scope**:\n```\n✓ Test UserService with Database\n✓ Test API endpoint with authentication\n✓ Test file processing pipeline\n```\n\n### End-to-End (E2E) Tests\n\n**Purpose**: Test complete workflows from user perspective\n\n**Characteristics**:\n- Test entire application stack\n- Simulate real user interactions\n- Slowest test type\n- Fewest in number\n- Highest confidence level\n\n**Example Scope**:\n```\n✓ Test user registration flow\n✓ Test checkout process\n✓ Test complete report generation\n```\n\n## Test Design Principles\n\n### AAA Pattern (Arrange-Act-Assert)\n\nStructure every test in three clear phases:\n\n```\n// Arrange: Setup test data and conditions\nuser = createTestUser()\nvalidator = createValidator()\n\n// Act: Execute the code under test\nresult = validator.validate(user)\n\n// Assert: Verify expected outcome\nassert(result.isValid == true)\n```\n\n**Adaptation**: Apply this structure using your language's idioms (methods, functions, procedures)\n\n### One Assertion Per Concept\n\n- Test one behavior per test case\n- Multiple assertions OK if testing single concept\n- Split unrelated assertions into separate tests\n\n**Good**:\n```\ntest(\"validates user email format\")           // input validation\ntest(\"returns error when service unavailable\") // error path\ntest(\"transitions order from pending to paid\") // state transition\n```\n\n**Bad**:\n```\ntest(\"validates user\") // Tests everything at once\n```\n\n### Descriptive Test Names\n\nTest names should clearly describe:\n- What is being tested\n- Under what conditions\n- What the expected outcome is\n\n**Recommended format**: `\"should [expected behavior] when [condition]\"`\n\n**Examples**:\n```\ntest(\"should return error when email is invalid\")\ntest(\"should calculate discount when user is premium\")\ntest(\"should throw exception when file not found\")\n```\n\n**Adaptation**: Follow your project's naming convention (camelCase, snake_case, describe/it blocks)\n\n## Test Independence\n\n### Setup and Teardown\n\n- Use setup hooks to prepare test environment\n- Use teardown hooks to clean up resources\n- Keep setup minimal and focused\n- Ensure teardown runs even if test fails\n\n## Mocking and Test Doubles\n\n### When to Use Mocks\n\n- **Mock external dependencies**: APIs, databases, file systems\n- **Mock slow operations**: Network calls, heavy computations\n- **Mock unpredictable behavior**: Random values, current time\n- **Mock unavailable services**: Third-party services\n\n### Mocking Principles\n\n- Mock at boundaries, not internally\n- Keep mocks simple and focused\n- Verify mock expectations when relevant\n- Wrap external libraries/frameworks behind adapters and mock the adapter\n\n## Data Layer Testing\n\n### Mock Limitations for Data Layer\n\nMocks validate call patterns but cannot verify data layer correctness. The following pass through undetected with mock-only testing:\n- Schema mismatches (table names, column names, data types)\n- Query correctness (joins, filters, aggregations, grouping)\n- Database constraints (NOT NULL, UNIQUE, foreign keys)\n- Migration drift (schema changes that make code out of sync)\n\n### When Mocks Are Appropriate for Data Access\n\n- Testing business logic that receives data from the data layer (mock the repository, test the service)\n- Testing error handling paths (simulating connection failures, timeouts)\n- Unit tests where data access is a dependency, not the subject under test\n\n### When Mocks Are Insufficient for Data Access\n\n- Testing repository or data access implementations themselves\n- Verifying query correctness (joins, filters, aggregations, grouping)\n- Testing data integrity constraints\n- Testing migration compatibility\n\n### Real Database Testing (Environment-Dependent)\n\nOptions for verifying data layer correctness against a real database engine:\n- **Containerized databases** for CI environments\n- **In-memory databases** for fast feedback (note: dialect differences may mask issues)\n- **Dedicated test databases** with seed data\n\nThe appropriate approach depends on project environment and CI/CD capabilities.\n\n### AI-Generated Code and Schema Awareness\n\n- AI-generated data access code has heightened schema hallucination risk\n- Generated queries may use correct syntax but reference nonexistent schema elements\n- Mock-based tests pass regardless of schema accuracy\n- Mitigation: Design Docs should include explicit schema references so that documented schemas can be cross-checked against data access code during review\n\n## Test Quality Practices\n\n### Keep Tests Active\n\n- **Fix or delete failing tests**: Resolve failures immediately\n- **Remove commented-out tests**: Fix them or delete entirely\n- **Keep tests running**: Broken tests lose value quickly\n- **Maintain test suite**: Refactor tests as needed\n\n### Test Helpers and Utilities\n\n- Create reusable test data builders\n- Extract common setup into helper functions\n- Build test utilities for complex scenarios\n- Share helpers across test files appropriately\n\n## What to Test\n\n### Focus on Behavior\n\n**Test observable behavior, not implementation**:\n\n✓ **Good**: Test that function returns expected output\n✓ **Good**: Test that correct API endpoint is called\n✗ **Bad**: Test that internal variable was set\n✗ **Bad**: Test order of private method calls\n\n### Test Public APIs\n\n- Test through public interfaces\n- Avoid testing private methods directly\n- Test return values, outputs, exceptions\n- Test side effects (database, files, logs)\n\n### Test Edge Cases\n\nAlways test:\n- **Boundary conditions**: Min/max values, empty collections\n- **Error cases**: Invalid input, null values, missing data\n- **Edge cases**: Special characters, extreme values\n- **Happy path**: Normal, expected usage\n\n## Test Quality Criteria\n\nThese criteria ensure reliable, maintainable tests.\n\n### Literal Expected Values\n\n- Use hardcoded literal values in assertions\n- Calculate expected values independently from the implementation\n- If the implementation has a bug, the test catches it through independent verification\n- If expected value equals mock return value unchanged, the test verifies nothing (no transformation occurred)\n\n### Result-Based Verification\n\n- Verify final results and observable outcomes\n- Assert on return values, output data, or system state changes\n- For mock verification, check that correct arguments were passed\n\n### Meaningful Assertions\n\n- Every test must include at least one assertion\n- Assertions must validate observable behavior\n- A test without assertions always passes and provides no value\n\n### Appropriate Mock Scope\n\n- Mock direct external I/O dependencies: databases, HTTP clients, file systems\n- Use real implementations for internal utilities and business logic\n- Over-mocking reduces test value by verifying wiring instead of behavior\n\n### Boundary Value Testing\n\nTest at boundaries of valid input ranges:\n- Minimum valid value\n- Maximum valid value\n- Just below minimum (invalid)\n- Just above maximum (invalid)\n- Empty input (where applicable)\n\n### Test Independence Verification\n\nEach test must:\n- Create its own test data\n- Not depend on execution order\n- Clean up its own state\n- Pass when run in isolation\n\n## Verification Requirements\n\n### Before Commit\n\n- ✓ All tests pass — fix failing tests immediately\n- ✓ No tests skipped or commented — delete or fix\n- ✓ No debug code left in tests\n- ✓ Test coverage meets standards\n- ✓ No flaky tests — make deterministic\n- ✓ Tests run within performance thresholds\n\n## Test Organization\n\n### File Structure\n\n- **Mirror production structure**: Tests follow code organization\n- **Clear naming conventions**: Follow project's test file patterns\n  - Examples: `UserService.test.*`, `user_service_test.*`, `test_user_service.*`, `UserServiceTests.*`\n- **Logical grouping**: Group related tests together\n- **Separate test types**: Unit, integration, e2e in separate directories\n\n### Test Suite Organization\n\n```\ntests/\n├── unit/           # Fast, isolated unit tests\n├── integration/    # Integration tests\n├── e2e/            # End-to-end tests\n├── fixtures/       # Test data and fixtures\n└── helpers/        # Shared test utilities\n```\n\n## Performance Considerations\n\n### Test Speed\n\n- **Unit tests**: < 100ms each\n- **Integration tests**: < 1s each\n- **Full suite**: Should run frequently (< 10 minutes)\n\n### Optimization Strategies\n\n- Run tests in parallel when possible\n- Use in-memory databases for tests\n- Mock expensive operations\n- Split slow test suites\n- Profile and optimize slow tests\n\n## Continuous Integration\n\n### CI/CD Requirements\n\n- Run full test suite on every commit\n- Block merges if tests fail\n- Run tests in isolated environments\n- Test on target platforms/versions\n\n### Test Reports\n\n- Generate coverage reports\n- Track test execution time\n- Identify flaky tests\n- Monitor test trends\n\n## Test Design Guardrails\n\n### Every Test Must\n\n- Include at least one meaningful assertion\n- Create its own test data and clean up its own state\n- Pass when run in any order and in isolation\n- Test observable behavior through public interfaces\n- Keep test logic simple (no branching, no loops)\n- Mock only external I/O boundaries, use real implementations for internal logic\n\n### Flaky Test Resolution\n\n- Use deterministic time mocking instead of real clocks\n- Use fixed seed values instead of random data\n- Ensure proper resource cleanup in teardown\n- Resolve race conditions with synchronization primitives\n\n## Regression Testing\n\n### Prevent Regressions\n\n- Add test for every bug fix\n- Maintain comprehensive test suite\n- Run full suite regularly\n- Keep all tests unless the tested functionality is removed\n\n### Legacy Code\n\n- Add characterization tests before refactoring\n- Test existing behavior first\n- Gradually improve coverage\n- Refactor with confidence\n\n## Testing Best Practices by Language Paradigm\n\n### Type System Utilization\n\n**For languages with static type systems:**\n- Leverage compile-time verification for correctness\n- Focus tests on business logic and runtime behavior\n- Use language's type system to prevent invalid states\n\n**For languages with dynamic typing:**\n- Add comprehensive runtime validation tests\n- Explicitly test data contract validation\n- Consider property-based testing for broader coverage\n\n### Programming Paradigm Considerations\n\n**Functional approach:**\n- Test pure functions thoroughly (deterministic, no side effects)\n- Test side effects at system boundaries\n- Leverage property-based testing for invariants\n\n**Object-oriented approach:**\n- Test behavior through public interfaces\n- Mock dependencies via abstraction layers\n- Test polymorphic behavior carefully\n\n**Common principle:** Adapt testing strategy to leverage language strengths while ensuring comprehensive coverage\n\n## Documentation and Communication\n\n### Tests as Documentation\n\n- Tests document expected behavior\n- Use clear, descriptive test names\n- Include examples of usage\n- Show edge cases and error handling\n\n### Test Failure Messages\n\n- Provide clear, actionable error messages\n- Include actual vs expected values\n- Add context about what was being tested\n- Make debugging easier","tags":["testing","principles","claude","code","workflows","shinpr","agent-skills","agentic-ai","ai-agents","automation","claude-code","claude-code-plugin"],"capabilities":["skill","source-shinpr","skill-testing-principles","topic-agent-skills","topic-agentic-ai","topic-ai-agents","topic-automation","topic-claude-code","topic-claude-code-plugin","topic-code-quality","topic-developer-tools","topic-development-workflow","topic-llm-orchestration","topic-productivity","topic-prompt-engineering"],"categories":["claude-code-workflows"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/shinpr/claude-code-workflows/testing-principles","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add shinpr/claude-code-workflows","source_repo":"https://github.com/shinpr/claude-code-workflows","install_from":"skills.sh"}},"qualityScore":"0.613","qualityRationale":"deterministic score 0.61 from registry signals: · indexed on github topic:agent-skills · 327 github stars · SKILL.md body (13,527 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-02T18:53:53.588Z","embedding":null,"createdAt":"2026-04-18T22:03:20.752Z","updatedAt":"2026-05-02T18:53:53.588Z","lastSeenAt":"2026-05-02T18:53:53.588Z","tsv":"'1':38,94 '10':264,1406 '100ms':256,1395 '1s':260,1399 '2':52,119 '3':63,139 '4':71,157 '80':202 'aaa':418 'abstract':1707 'access':747,776,791,796,875,921 'accuraci':901 'across':987 'act':422,441 'action':1756 'activ':930 'actual':117,1760 'adapt':457,577,677,681,1715 'add':1567,1592,1651,1764 'aggreg':722,804 'agnost':6,32 'ai':865,872 'ai-gener':864,871 'alway':90,249,1057,1185 'anyth':176 'api':342,363,631,1013,1033 'appli':458 'applic':387,1252 'approach':856,1673,1698 'appropri':744,855,990,1191 'argument':1163 'arrang':421,431 'arrange-act-assert':420 'assert':216,423,450,454,470,480,488,1101,1147,1167,1175,1176,1184,1486 'authent':366 'avoid':1038 'awar':870 'bad':517,1017,1024 'base':895,1139,1664,1691 'behavior':193,475,549,644,996,999,1180,1224,1509,1599,1636,1700,1711,1735 'behind':676 'benefit':178 'best':1608 'better':179 'block':588,1446 'boundari':660,1059,1225,1230,1525,1687 'branch':1518 'break':175 'broader':1667 'broken':952 'bug':1114,1571 'build':979 'builder':972 'busi':212,749,1211,1632 'calcul':563,1102 'calculatetot':316 'call':639,692,1016,1030 'camelcas':584 'cannot':695 'capabl':863 'care':1712 'case':478,586,1056,1066,1074,1747 'catch':1117 'chang':734,1156 'charact':1076 'character':1593 'characterist':229,292,331,384 'check':168,268,918,1160 'checkout':409 'ci':833 'ci/cd':862,1437 'clariti':152 'class':43,298,320 'clean':144,605,1269,1493 'cleanup':1554 'clear':269,429,531,1329,1737,1755 'client':1201 'clock':1542 'close':276 'code':44,51,123,142,203,207,279,444,737,867,876,922,1300,1327,1591 'collect':1064 'column':714 'comment':941,1294 'commented-out':940 'commit':1282,1445 'common':974,1713 'communic':1728 'compat':812 'compil':1624 'compile-tim':1623 'complet':379,412 'complex':983 'compon':289,330,334 'comprehens':184,1574,1652,1724 'comput':641 'concept':472,485 'condit':436,539,551,1060,1559 'confid':194,400,1606 'connect':769 'consid':1661 'consider':1390,1671 'constraint':725,809 'container':830 'context':1765 'continu':1435 'contract':348,1659 'convent':583,1331 'core':35 'correct':699,719,801,824,886,1012,1162,1628 'coverag':13,186,199,204,218,221,1305,1463,1603,1668,1725 'creat':968,1259,1487 'createtestus':438 'createvalid':440 'criteria':245,1086,1088 'critic':209 'cross':917 'cross-check':916 'current':647 'cycl':89,93 'data':434,682,688,697,716,746,753,756,775,790,795,807,822,853,874,920,971,1072,1152,1263,1382,1491,1550,1658 'databas':338,361,632,724,814,828,831,838,850,1051,1199,1420 'debug':1299,1772 'dedic':848 'default':188 'delet':933,947,1295 'depend':236,304,630,779,818,857,1198,1265,1705 'describ':532 'describe/it':587 'descript':525,1738 'design':17,23,180,416,903,1476 'detail':244 'determinist':68,1312,1536,1678 'develop':82 'dialect':843 'didn':173 'differ':844 'direct':1042,1195 'directori':1361 'discount':564 'doc':904 'document':190,912,1726,1731,1733 'doubl':623 'drift':732 'driven':81 'duplic':148 'dynam':1649 'e2e':375,1358,1374 'easier':1773 'edg':1055,1073,1746 'effect':1050,1681,1684 'element':892 'elimin':147 'email':496,558 'empti':1063,1249 'end':372,374,1376,1378 'end-to-end':371,1375 'endpoint':364,1014 'engin':829 'enough':128 'ensur':106,159,613,1089,1551,1723 'entir':386,948 'environ':600,817,834,860,1455 'environment-depend':816 'equal':48,1125 'error':502,506,556,765,1065,1749,1757 'even':616 'everi':425,1168,1444,1478,1570 'everyth':522 'exampl':313,356,402,552,1338,1742 'except':572,1047 'execut':300,442,1267,1467 'exist':1598 'expect':192,452,542,548,670,1007,1082,1094,1103,1123,1734,1762 'expens':1424 'explicit':907,1656 'extern':303,306,629,674,1196,1523 'extract':973 'extrem':1077 'fail':98,109,118,619,934,1287,1450 'failur':770,937,1752 'fast':53,253,299,840,1367 'feedback':54,62,841 'fewest':396 'file':339,368,574,633,989,1052,1202,1320,1336 'filter':721,803 'final':1142 'first':42,100,1600 'first-class':41 'fix':931,944,1286,1297,1544,1572 'fixtur':1380,1384 'flaki':1309,1470,1532 'flow':407 'focus':134,612,667,994,1629 'follow':91,578,701,1326,1332 'foreign':729 'format':497,546 'found':576 'frequent':1405 'full':165,262,1401,1440,1578 'function':295,317,467,978,1005,1587,1672,1676 'generat':414,866,873,882,1462 'goal':227 'good':492,1002,1009 'gradual':1601 'green':87,120 'group':723,805,1348,1349 'guardrail':1477 'guid':224 'hallucin':880 'handl':766,1750 'happi':1079 'hardcod':1097 'heavi':640 'heighten':878 'helper':965,977,986,1385 'highest':399 'hook':596,603 'http':1200 'i/o':1197,1524 'identifi':1469 'idiom':465 'immedi':61,938,1289 'implement':105,126,146,797,1001,1108,1111,1206,1528 'improv':141,149,1602 'in-memori':835,1417 'includ':9,337,906,1171,1481,1741,1759 'independ':72,234,241,590,1105,1120,1254 'individu':288 'input':248,498,1068,1233,1250 'instead':1222,1539,1547 'insuffici':788 'integr':258,324,808,1357,1371,1372,1397,1436 'interact':328,392 'interfac':1037,1512,1703 'intern':662,1020,1208,1530 'invalid':560,1067,1244,1248,1644 'invari':1694 'isol':78,291,1278,1368,1454,1506 'issu':847 'join':720,802 'keep':153,608,663,928,949,1513,1581 'key':730 'languag':5,31,463,1611,1617,1638,1647,1720 'language-agnost':4,30 'layer':683,689,698,757,823,1708 'least':1173,1483 'left':1301 'legaci':1590 'level':401 'leverag':1622,1688,1719 'libraries/frameworks':675 'limit':686 'liter':1093,1098 'live':189 'log':1053 'logic':213,750,1212,1347,1515,1531,1633 'loop':1520 'lose':954 'maintain':45,957,1091,1573 'major':308 'make':130,136,736,1311,1771 'manual':272 'mask':846 'maximum':1238,1247 'may':336,845,884 'meaning':215,1166,1485 'meet':1306 'memori':837,1419 'merg':1447 'messag':1753,1758 'method':296,466,1029,1041 'migrat':731,811 'millisecond':301 'min/max':1061 'minim':122,610 'minimum':201,1235,1243 'minut':265,1407 'mirror':1322 'mismatch':711 'miss':1071 'mitig':902 'mock':305,620,627,628,635,642,649,656,658,664,669,679,685,690,707,742,758,786,894,1126,1158,1192,1194,1215,1423,1521,1538,1704 'mock-bas':893 'mock-on':706 'modul':350 'monitor':1472 'multipl':333,479 'must':232,1170,1177,1258,1480 'name':150,527,529,582,713,715,1330,1740 'need':963 'network':638 'nonexist':890 'normal':1081 'note':842 'noth':1133 'null':727,1069 'number':398 'object':1696 'object-ori':1695 'observ':998,1145,1179,1508 'occur':1136 'ok':481 'one':469,474,1174,1484 'oper':637,1425 'optim':1408,1432 'option':819 'order':510,1026,1268,1503 'organ':1319,1328,1364 'orient':1697 'outcom':453,543,1146 'output':252,1008,1046,1151 'over-mock':1213 'paid':514 'paradigm':1612,1670 'parallel':1413 'parsed':322 'parti':654 'pass':125,133,156,163,702,897,1165,1186,1274,1285,1498 'pass/fail':270 'path':210,507,767,1080 'pattern':18,419,693,1337 'pend':512 'per':471,476 'percentag':219 'perform':1316,1389 'perspect':383 'phase':430 'philosophi':37 'pipelin':370 'platforms/versions':1459 'polymorph':1710 'portion':352 'possibl':1415 'practic':927,1609 'premium':568 'prepar':598 'prevent':1565,1643 'primit':1562 'principl':3,8,34,417,657,1714 'priorit':208,214 'privat':1028,1040 'procedur':468 'process':369,410 'produc':250 'product':50,206,1323 'profil':1430 'program':1669 'project':580,859,1333 'proper':1552 'properti':1663,1690 'property-bas':1662,1689 'provid':60,1188,1754 'public':1032,1036,1511,1702 'pure':1675 'purpos':286,326,377 'qualiti':12,29,47,197,926,1085 'queri':718,800,883 'quick':58,956 'race':1558 'random':645,1549 'rang':1234 'real':390,813,827,1205,1527,1541 'reason':113 'receiv':752 'recommend':545 'red':86,95 'red-green-refactor':85 'reduc':1216 'refactor':88,140,172,196,960,1596,1604 'refer':889,909 'regardless':898 'registr':406 'regress':170,1563,1566 'regular':1580 'relat':1350 'relev':672 'reliabl':64,1090 'remov':939,1589 'report':413,1461,1464 'repositori':760,793 'reproduc':70,246 'requir':183,198,1280,1438 'resolut':1534 'resolv':936,1557 'resourc':607,1553 'result':447,1138,1143 'result-bas':1137 'result.isvalid':455 'return':501,555,1006,1044,1127,1149 'reusabl':969 'review':27,924 'right':112 'risk':881 'run':57,76,164,615,951,1276,1314,1404,1410,1439,1451,1500,1577 'runtim':1635,1653 'scenario':984 'schema':710,733,869,879,891,900,908,913 'scope':314,357,403,1193 'see':239 'seed':852,1545 'self':267 'self-check':266 'separ':490,1353,1360 'servic':307,504,651,655,763,1341,1345 'set':1023 'setup':432,591,595,609,975 'share':985,1386 'show':1745 'side':1049,1680,1683 'simpl':665,1516 'simul':389,768 'singl':294,484 'skill' 'skill-testing-principles' 'skip':1292 'slow':636,1427,1433 'slower':343 'slowest':393 'smaller':351 'snake':585 'source-shinpr' 'special':1075 'speed':1392 'split':486,1426 'stack':388 'standard':14,200,1307 'state':515,1155,1273,1497,1645 'static':1619 'still':162 'strategi':25,1409,1717 'strength':1721 'structur':143,424,460,1321,1324 'subject':782 'suit':167,263,312,355,959,1363,1402,1429,1442,1576,1579 'sync':740 'synchron':1561 'syntax':887 'system':340,634,1154,1203,1614,1621,1641,1686 'tabl':712 'target':1458 'tdd':10,83,177 'teardown':593,602,614,1556 'test':2,7,11,16,22,24,28,33,36,39,46,55,65,74,80,99,103,108,115,132,155,161,166,185,228,231,238,240,255,259,281,282,285,287,293,311,315,318,321,325,327,332,346,354,358,362,367,376,378,385,394,404,408,411,415,426,433,446,473,477,483,491,493,500,508,518,521,526,528,536,553,561,569,589,599,618,622,684,709,748,761,764,773,784,792,806,810,815,849,896,925,929,935,943,950,953,958,961,964,970,980,988,993,997,1003,1010,1018,1025,1031,1034,1039,1043,1048,1054,1058,1084,1092,1116,1131,1169,1182,1217,1227,1228,1253,1257,1262,1284,1288,1291,1303,1304,1310,1313,1318,1325,1335,1342,1343,1351,1354,1362,1365,1370,1373,1379,1381,1387,1391,1394,1398,1411,1422,1428,1434,1441,1449,1452,1456,1460,1466,1471,1473,1475,1479,1490,1507,1514,1533,1564,1568,1575,1583,1586,1594,1597,1607,1630,1655,1657,1665,1674,1682,1692,1699,1709,1716,1729,1732,1739,1751,1770 'test-driven':79 'testabl':182 'testing-principl':1 'third':653 'third-parti':652 'thorough':1677 'three':428 'threshold':1317 'throw':571 'time':274,648,1468,1537,1625 'timeout':771 'togeth':335,1352 'topic-agent-skills' 'topic-agentic-ai' 'topic-ai-agents' 'topic-automation' 'topic-claude-code' 'topic-claude-code-plugin' 'topic-code-quality' 'topic-developer-tools' 'topic-development-workflow' 'topic-llm-orchestration' 'topic-productivity' 'topic-prompt-engineering' 'track':1465 'transform':1135 'transit':509,516 'trend':1474 'true':456 'type':283,395,717,1355,1613,1620,1640,1650 'unavail':505,650 'unchang':1129 'undetect':704 'uniqu':728 'unit':254,284,345,772,1356,1366,1369,1393 'unless':1584 'unpredict':643 'unrel':487 'usag':1083,1744 'use':19,220,461,594,601,626,885,1096,1204,1416,1526,1535,1543,1637,1736 'user':382,391,405,437,449,495,520,566,1340,1344 'userservic':359 'userservice.test':1339 'userservicetest':1346 'uservalid':319 'util':323,967,981,1209,1388,1615 'valid':171,439,494,499,519,691,1178,1232,1236,1239,1654,1660 'validator.validate':448 'valu':646,955,1045,1062,1070,1078,1095,1099,1104,1124,1128,1150,1190,1218,1226,1237,1240,1546,1763 'variabl':1021 'verif':242,273,1121,1140,1159,1255,1279,1626 'verifi':114,158,347,451,668,696,799,821,1132,1141,1220 'via':1706 'vs':1761 'wire':1221 'within':1315 'without':271,1183 'work':138 'workflow':380 'wrap':673 'write':21,96,101,121 'written':275","prices":[{"id":"9e25e608-c91e-40fe-b774-473439f90c86","listingId":"da64b902-bcc5-450b-8467-b04e8d69ab66","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"shinpr","category":"claude-code-workflows","install_from":"skills.sh"},"createdAt":"2026-04-18T22:03:20.752Z"}],"sources":[{"listingId":"da64b902-bcc5-450b-8467-b04e8d69ab66","source":"github","sourceId":"shinpr/claude-code-workflows/testing-principles","sourceUrl":"https://github.com/shinpr/claude-code-workflows/tree/main/skills/testing-principles","isPrimary":false,"firstSeenAt":"2026-04-18T22:03:20.752Z","lastSeenAt":"2026-05-02T18:53:53.588Z"}],"details":{"listingId":"da64b902-bcc5-450b-8467-b04e8d69ab66","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"shinpr","slug":"testing-principles","github":{"repo":"shinpr/claude-code-workflows","stars":327,"topics":["agent-skills","agentic-ai","ai-agents","automation","claude-code","claude-code-plugin","code-quality","developer-tools","development-workflow","llm-orchestration","productivity","prompt-engineering","skills"],"license":"mit","html_url":"https://github.com/shinpr/claude-code-workflows","pushed_at":"2026-05-02T15:39:17Z","description":"Production-ready development workflows for Claude Code, powered by specialized AI agents.","skill_md_sha":"20190d9c0a4309cc3a60ac08ade78422cd5decf8","skill_md_path":"skills/testing-principles/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/shinpr/claude-code-workflows/tree/main/skills/testing-principles"},"layout":"multi","source":"github","category":"claude-code-workflows","frontmatter":{"name":"testing-principles","description":"Language-agnostic testing principles including TDD, test quality, coverage standards, and test design patterns. Use when writing tests, designing test strategies, or reviewing test quality."},"skills_sh_url":"https://skills.sh/shinpr/claude-code-workflows/testing-principles"},"updatedAt":"2026-05-02T18:53:53.588Z"}}