en un clic
testing-strategies
Systematic testing for confidence without over-testing — the right test at the right level
Menu
Systematic testing for confidence without over-testing — the right test at the right level
Defense-in-depth, PII protection, secrets scanning, and secure packaging for distributed software
Generate consistent visual character references across multiple scenarios using Flux and nano-banana-pro on Replicate
Create professional ultra-wide cinematic banners for GitHub READMEs using Flux and Ideogram models with typography options
Generate professional presentations using the Gamma API with expert storytelling consulting based on Duarte methodology.
Intelligent project persona identification using priority chain detection with LLM and heuristic fallback
Reusable patterns for VS Code extension development.
| name | testing-strategies |
| description | Systematic testing for confidence without over-testing — the right test at the right level |
| applyTo | **/*test*,**/*spec*,**/*.test.*,**/*.spec.* |
Test the behavior, not the implementation. Test the boundaries, not the happy path.
| Level | Volume | Speed | Cost to Maintain | What It Catches |
|---|---|---|---|---|
| Unit | Many (70%) | < 10ms each | Low | Logic errors, edge cases, regressions |
| Integration | Some (20%) | < 1s each | Medium | Wiring bugs, API contracts, data flow |
| E2E | Few (10%) | 5-30s each | High | User journey failures, deployment issues |
Anti-pattern: Inverted pyramid (too many E2E, few unit) → slow CI, flaky tests, hard to debug. Anti-pattern: Ice cream cone (manual testing on top of everything) → doesn't scale.
test('should calculate discount when order exceeds $100', () => {
// Arrange
const order = createOrder({ subtotal: 150, customerTier: 'gold' });
// Act
const discount = calculateDiscount(order);
// Assert
expect(discount).toBe(15); // 10% for gold tier
});
Naming convention: should [expected behavior] when [condition] — reads as a specification.
| Type | Purpose | When to Use | Example |
|---|---|---|---|
| Snapshot | Detect unexpected output changes | UI components, serialized data | expect(render(<Button/>)).toMatchSnapshot() |
| Contract | Verify API shape between services | Microservices, public APIs | Pact, OpenAPI validation |
| Property-based | Find edge cases humans miss | Pure functions, parsers, serializers | fc.assert(fc.property(fc.string(), s => decode(encode(s)) === s)) |
| Mutation | Verify tests actually catch bugs | Critical business logic | Stryker, pitest |
| Performance | Catch regressions in speed/memory | Hot paths, API endpoints | Benchmark before/after |
| Smoke | Verify deployment didn't break basics | Post-deploy, staging | Hit health endpoint + key pages |
| Mock This | Why | Don't Mock This | Why |
|---|---|---|---|
| External HTTP APIs | Unreliable, slow, costly | Your own business logic | You'd be testing your mocks |
| Database in unit tests | Slow, stateful | Database in integration tests | That's the whole point |
Time (Date.now) | Non-deterministic | Pure functions | Already deterministic |
| File system | Side effects | In-memory equivalents | Faster than mocking |
| Random/UUID | Non-deterministic | Framework internals | Not your responsibility |
| Range | Interpretation | Action |
|---|---|---|
| < 50% | Probably missing critical paths | Increase |
| 50-70% | Reasonable for most projects | Focus on changed code |
| 70-85% | Good, diminishing returns starting | Maintain, don't chase |
| 85-100% | Often wasteful unless safety-critical | Review if the effort is worth it |
The real metric: Coverage of changed code in each PR, not overall percentage.
What coverage doesn't tell you: That your tests assert the right things. 100% coverage with no assertions is useless.
| Don't Test | Why | Instead |
|---|---|---|
| Third-party library internals | Not your code | Trust it (or pick a different library) |
| Framework behavior | Already tested upstream | Test your code that uses the framework |
| Private implementation details | Breaks on refactor | Test the public interface |
| Trivial getters/setters | No logic to break | Only if they have side effects |
| Generated code | Changes on regeneration | Test the generator, not the output |
Test files are part of your repository's distribution—they get indexed by search engines (public repos), copied by developers learning from your code, and included in package distributions.
| Anti-pattern | Risk | Secure Alternative |
|---|---|---|
auth: process.env.TOKEN || 'r8_abc123...' | Hardcoded secret triggers GitHub push protection | Validate env var exists, fail with clear error |
const apiKey = "test-key-1234-real-key" | Accidentally commits production credentials | Use environment variables only |
// API endpoint: https://api.example.com?key=sk-live-... | Leaks secrets in comments | Use placeholders: ?key=YOUR_KEY_HERE |
No .env.example for test setup | Developers hardcode to get tests working | Provide template with dummy values |
Anti-pattern (triggers GitHub push protection):
const replicate = new Replicate({
auth: process.env.TOKEN || 'r8_hardcoded_fallback'
});
Secure pattern (explicit validation):
if (!process.env.REPLICATE_API_TOKEN) {
console.error('REPLICATE_API_TOKEN environment variable is required');
console.error('See .env.example for setup instructions');
process.exit(1);
}
const replicate = new Replicate({ auth: process.env.REPLICATE_API_TOKEN });
Benefits:
If GitHub blocks your push due to secrets in test files:
git commit --amend --no-edit (rewrites history locally)git show HEAD should contain no secretsgit push origin mainRule: Never create a second "oops, remove secrets" commit. Use --amend to keep secrets out of history entirely.
| Good Test | Bad Test |
|---|---|
| Fails when behavior breaks | Fails when implementation changes |
| One clear reason to fail | Multiple assertions testing different things |
| Self-contained | Depends on other test order |
| Fast (< 100ms unit) | Slow due to unnecessary setup |
| Readable as documentation | Requires reading source to understand |
| Deterministic | Flaky (passes sometimes) |
| Step | Action | Common Mistake |
|---|---|---|
| Red | Write a failing test | Writing too much test (test the next small behavior) |
| Green | Make it pass with minimal code | Over-engineering the solution |
| Refactor | Clean up while green | Skipping this step (accumulates debt) |
TDD is not always the right choice: It works best for well-understood requirements. For exploratory code, write tests after the design stabilizes.
| Pattern | Likely Cause | Fix |
|---|---|---|
| Fails 1 in 10 runs | Timing/race condition | Add proper waits, remove shared state |
| Fails only in CI | Environment difference | Pin versions, use containers |
| Fails after another test | Test pollution | Isolate setup/teardown |
| Fails on slow machines | Hardcoded timeouts | Use retry with backoff or event-based waits |
See synapses.json for connections.