skills/testing-best-practice/SKILL.md
--- name: testing-best-practice description: A Skill for writing, reviewing, and refactoring tests using Artem-style principles: test intent over implementation, mock boundaries not internals, avoid flakiness, prefer integration tests, and use `using` for cleanup. --- # Testing Best Practice ## Instructions When the user asks for help with tests (writing new tests, improving existing ones, or defining testing standards), follow these rules: 1. **Test intent, not implementation** - Make te
npx skillsauth add adrianbrowning/agent-skills skills/testing-best-practiceInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
When the user asks for help with tests (writing new tests, improving existing ones, or defining testing standards), follow these rules:
Test intent, not implementation
Favour high-signal, low-maintenance tests
it("allows a customer to update their email", async () => {})
Avoid flakiness with strict control of nondeterminism
Mock boundaries, not internals
Prefer integration tests where possible
Refactor for testability
Use the using keyword for resource cleanup
using for disposable resources such as:
Symbol.disposeusing over manual afterEach cleanup when possible.Example:
it("handles a temporary directory", async () => {
using tmp = createTempDir();
await writeFile(tmp.path + "/a.txt", "hello");
expect(await readFile(tmp.path + "/a.txt")).toBe("hello");
});
Recommended test layout
describe("FeatureName", () => {
it("states the requirement", async () => {
// Arrange
const user = buildUser();
// Act
const result = await updateEmail(user.id, "[email protected]");
// Assert
expect(result.email).toBe("[email protected]");
});
});
Golden rules summary
using for automatic cleanup of disposable resources.When responding, ensure that any example tests you write or refactor obey these rules by default. If the user’s existing tests violate these rules, explain what to change and why.
User prompt
I have a function
updateEmail(userId, email)that calls an HTTP API. Can you write tests for it?
What to do
updateEmail as the user would.apiClient.get.Example response snippet
describe("updateEmail", () => {
it("updates the user email when the API succeeds", async () => {
// MSW handler: mock boundary, not internal client
server.use(
http.put("/users/:id/email", () => HttpResponse.json({ email: "[email protected]" }))
);
const result = await updateEmail("user-123", "[email protected]");
expect(result.email).toBe("[email protected]");
});
it("throws a helpful error when the API fails", async () => {
server.use(
http.put("/users/:id/email", () => HttpResponse.text("Server error", { status: 500 }))
);
await expect(updateEmail("user-123", "[email protected]"))
.rejects
.toThrow(/unable to update email/i);
});
});
User prompt
My test keeps breaking whenever I refactor. It spies on
apiClient.putand checks the exact arguments. How can I make it better?
What to do
Example response snippet
// Instead of:
expect(apiClient.put).toHaveBeenCalledWith("/users/123/email", { email: "[email protected]" });
// Prefer:
const result = await updateEmail("123", "[email protected]");
expect(result.email).toBe("[email protected]");
Explain that this test will only fail when the behavioural contract changes, not just when apiClient usage is refactored.
/tdd-integration - TDD Red-Green-Refactor cycle for feature development/mw-mr-mf - Make it Work/Right/Fast workflow for iterative developmentdevelopment
Best practices for TypeScript types, interfaces, assertions, and type safety. Use when writing or reviewing TypeScript code.
development
Enforce Test-Driven Development with strict Red-Green-Refactor cycle using integration tests. Auto-triggers when implementing new features or functionality. Trigger phrases include "implement", "add feature", "build", "create functionality", or any request to add new behavior. Does NOT trigger for bug fixes, documentation, or configuration changes.
development
React Router v7 loader performance optimization techniques. Use when optimizing TTFB, eliminating waterfalls, consolidating database queries, or streaming secondary data in loaders. Triggers on "slow loaders", "optimize TTFB", "speed up React Router", "loader performance", or when loaders exceed 500ms response time.
development
Convert project plans to JSONL format (issues + dependencies). Use when users ask "convert plan to jsonl", "create jsonl from plan", "export plan as json" or "convert plan to taks", "create tasks from plan", "export plan as tasks".