139 lines
9.4 KiB
Plaintext
139 lines
9.4 KiB
Plaintext
---
|
|
description: This rule provides guidelines for writing clean, maintainable, and effective tests using Jest. It covers code organization, performance, common pitfalls, and best practices for testing JavaScript and TypeScript projects.
|
|
globs: *.js,*.jsx,*.ts,*.tsx,*.mjs,*.cjs,*.mts,*.cts
|
|
---
|
|
- **Organize tests by feature or module:**
|
|
- Group tests into files or directories that correspond to the features or modules they are testing. This makes it easier to locate and maintain tests.
|
|
- Create a `__tests__` directory alongside your source code files. This is a common convention that Jest recognizes.
|
|
|
|
- **Use descriptive test names:**
|
|
- Write test names that clearly describe what the test is verifying. This makes it easier to understand the purpose of each test and to diagnose failures.
|
|
- Use the `describe` and `it` blocks to structure your tests and provide context.
|
|
- Example: `describe('User authentication', () => { it('should log in a user with valid credentials', () => { /* ... */ }); });`
|
|
|
|
- **Keep tests isolated and independent:**
|
|
- Each test should be independent of other tests. Avoid sharing state or dependencies between tests.
|
|
- Use `beforeEach` and `afterEach` hooks to set up and tear down the environment for each test.
|
|
|
|
- **Avoid testing implementation details:**
|
|
- Focus on testing the public API of your code, rather than the internal implementation details.
|
|
- This makes your tests more resilient to changes in the implementation.
|
|
- Test the "what", not the "how".
|
|
|
|
- **Use setup and teardown methods:**
|
|
- Use `beforeAll`, `afterAll`, `beforeEach`, and `afterEach` hooks to set up and tear down the environment for your tests.
|
|
- `beforeAll` and `afterAll` run once before and after all tests in a `describe` block.
|
|
- `beforeEach` and `afterEach` run before and after each test in a `describe` block.
|
|
|
|
- **Mock external dependencies:**
|
|
- Use mocking to isolate your code from external dependencies, such as network requests or database connections.
|
|
- Jest provides built-in mocking capabilities with `jest.mock` and `jest.spyOn`.
|
|
- Consider using a library like `axios-mock-adapter` for mocking HTTP requests.
|
|
|
|
- **Write tests that are easy to read and maintain:**
|
|
- Keep your tests concise and focused.
|
|
- Use clear and consistent formatting.
|
|
- Add comments to explain complex logic.
|
|
- Refactor your tests regularly to keep them up to date.
|
|
|
|
- **Aim for high test coverage, but prioritize meaningful tests over quantity:**
|
|
- Aim for high test coverage to ensure that your code is well-tested.
|
|
- However, prioritize writing meaningful tests that verify the core functionality of your code.
|
|
- Don't just aim for 100% coverage without considering the value of each test.
|
|
|
|
- **Use Jest's built-in matchers effectively:**
|
|
- Jest provides a rich set of matchers for asserting different conditions.
|
|
- Use matchers like `toBe`, `toEqual`, `toBeGreaterThan`, `toContain`, `toHaveBeenCalled`, etc.
|
|
- Explore the Jest documentation for the full list of matchers.
|
|
|
|
- **Handle asynchronous code correctly:**
|
|
- Use `async/await` or Promises to handle asynchronous code in your tests.
|
|
- Use the `resolves` and `rejects` matchers to assert that a Promise resolves or rejects.
|
|
- Example: `expect(myAsyncFunction()).resolves.toBe(expectedValue);`
|
|
|
|
- **Test error handling:**
|
|
- Write tests to verify that your code handles errors correctly.
|
|
- Use the `toThrow` matcher to assert that a function throws an error.
|
|
- Example: `expect(() => myDangerousFunction()).toThrow(Error);`
|
|
|
|
- **Use snapshots sparingly:**
|
|
- Snapshots can be useful for verifying the output of a component or function.
|
|
- However, they can also be brittle and difficult to maintain if used excessively.
|
|
- Use snapshots strategically and review them carefully when they change.
|
|
|
|
- **Configure Jest correctly:**
|
|
- Configure Jest using the `jest.config.js` or `jest.config.ts` file.
|
|
- Configure settings such as test environment, module file extensions, and coverage thresholds.
|
|
- Consider using presets like `ts-jest` or `babel-jest` for TypeScript or Babel support.
|
|
|
|
- **Leverage code coverage reports:**
|
|
- Use Jest's code coverage reports to identify areas of your code that are not well-tested.
|
|
- Aim to increase coverage in critical areas of your codebase.
|
|
- Use the `--coverage` flag to generate coverage reports.
|
|
|
|
- **Keep test data separate from test logic:**
|
|
- Externalize test data to improve readability and maintainability.
|
|
- Use fixtures or factories to generate test data.
|
|
- Avoid hardcoding data directly in your tests.
|
|
|
|
- **Consider using test-driven development (TDD):**
|
|
- Write tests before you write code to drive the development process.
|
|
- This can help you write more testable and well-designed code.
|
|
|
|
- **Run tests frequently:**
|
|
- Run your tests frequently to catch errors early.
|
|
- Use Jest's watch mode to automatically run tests when files change.
|
|
- Integrate tests into your CI/CD pipeline.
|
|
|
|
- **Document your tests:**
|
|
- Add comments to explain the purpose of each test and the expected behavior.
|
|
- This will make it easier for others to understand and maintain your tests.
|
|
|
|
- **Code Organization and Structure:**
|
|
- **Directory structure best practices:** Organize test files alongside the component/module they test (e.g., `src/components/MyComponent/MyComponent.test.js`)
|
|
- **File naming conventions:** Use `.test.js` or `.spec.js` suffixes for test files (e.g., `MyComponent.test.js`, `MyModule.spec.ts`).
|
|
- **Module organization:** Keep test files close to the modules they are testing. Use a consistent naming convention for test files.
|
|
- **Component architecture:** Test components in isolation, mocking dependencies where necessary.
|
|
- **Code splitting strategies:** Ensure tests cover all code paths in dynamically imported modules.
|
|
|
|
- **Common Patterns and Anti-patterns:**
|
|
- **Design patterns specific to Jest:** Use Page Object Model (POM) for UI tests, Factory pattern for test data generation.
|
|
- **Recommended approaches for common tasks:** Use `jest.mock` for mocking modules, `jest.spyOn` for spying on methods, and `fakeTimers` for controlling time-dependent behavior.
|
|
- **Anti-patterns and code smells to avoid:** Avoid testing implementation details, relying on global state, and creating brittle snapshots.
|
|
- **State management best practices:** Mock external state dependencies and verify state changes using `expect` assertions.
|
|
- **Error handling patterns:** Test for specific error messages and ensure error boundaries are properly tested.
|
|
|
|
- **Performance Considerations:**
|
|
- **Optimization techniques:** Use `jest.clearAllMocks` and `jest.resetAllMocks` in `beforeEach` blocks to prevent state leakage and improve test performance.
|
|
- **Memory management:** Avoid creating large data structures in tests that are not necessary. Manually trigger garbage collection in tests where large objects are created and released.
|
|
- **Rendering optimization:** Mock expensive rendering logic to speed up tests that involve React components.
|
|
- **Bundle size optimization:** Not applicable, as Jest primarily tests individual modules or components.
|
|
- **Lazy loading strategies:** Ensure tests cover all code paths in dynamically imported modules.
|
|
|
|
- **Security Best Practices:**
|
|
- **Common vulnerabilities and how to prevent them:** Avoid using sensitive data in test snapshots. Sanitize test data to prevent potential injection attacks.
|
|
- **Input validation:** Test input validation logic and ensure that invalid inputs are handled correctly.
|
|
- **Authentication and authorization patterns:** Mock authentication and authorization logic to test different user roles and permissions.
|
|
- **Data protection strategies:** Not directly applicable, as Jest primarily focuses on functional testing.
|
|
- **Secure API communication:** Mock API calls and verify that data is transmitted securely.
|
|
|
|
- **Testing Approaches:**
|
|
- **Unit testing strategies:** Test individual functions, classes, or components in isolation.
|
|
- **Integration testing:** Test interactions between different modules or components.
|
|
- **End-to-end testing:** Use tools like Cypress or Playwright for end-to-end tests.
|
|
- **Test organization:** Group tests into logical suites based on functionality or module.
|
|
- **Mocking and stubbing:** Use `jest.mock` and `jest.spyOn` to create mocks and stubs for dependencies.
|
|
|
|
- **Common Pitfalls and Gotchas:**
|
|
- **Frequent mistakes developers make:** Forgetting to mock dependencies, testing implementation details, and creating brittle snapshots.
|
|
- **Edge cases to be aware of:** Testing asynchronous code correctly, handling errors, and testing different input types.
|
|
- **Version-specific issues:** Be aware of breaking changes in Jest updates and update your tests accordingly.
|
|
- **Compatibility concerns:** Ensure tests are compatible with different browsers or environments.
|
|
- **Debugging strategies:** Use `console.log` statements, debuggers, or Jest's interactive mode to debug tests.
|
|
|
|
- **Tooling and Environment:**
|
|
- **Recommended development tools:** VS Code, WebStorm, Jest Runner extension.
|
|
- **Build configuration:** Configure Jest using `jest.config.js` or `package.json`.
|
|
- **Linting and formatting:** Use ESLint and Prettier to enforce code style and prevent errors.
|
|
- **Deployment best practices:** Integrate tests into your CI/CD pipeline to ensure code quality.
|
|
- **CI/CD integration:** Use tools like GitHub Actions, Jenkins, or CircleCI to automate testing and deployment. |