PromucFlow_constructor/.cursor/rules/testing/test-generator.mdc

295 lines
7.7 KiB
Plaintext
Raw Normal View History

refactor: restructure .cursor directory for improved organization and clarity (#40196) # refactor: restructure .cursor directory for improved organization and clarity ## Description This PR refactors the `.cursor` directory to enhance organization, clarity, and maintainability. ### Problem The existing `.cursor` directory lacked clear organization, making it difficult to find specific files, understand their purpose, and add new components consistently. ### Solution A comprehensive restructuring: #### New Directory Structure ``` .cursor/ ├── settings.json # Main configuration file ├── docs/ # Documentation │ ├── guides/ # In-depth guides │ ├── references/ # Quick references │ └── practices/ # Best practices ├── rules/ # Rule definitions │ ├── commit/ # Commit-related rules │ ├── quality/ # Code quality rules │ ├── testing/ # Testing rules │ └── verification/ # Verification rules └── hooks/ # Git hooks and scripts ``` #### Key Changes 1. **Logical Categorization**: Organized files into clear categories based on purpose 2. **Improved Documentation**: Added comprehensive README files for each directory 3. **Standardized Naming**: Implemented consistent kebab-case naming convention 4. **Reference Updates**: Updated all internal references to point to new file locations ### Benefits - **Easier Navigation**: Clear categorization makes finding files intuitive - **Improved Understanding**: Comprehensive documentation explains purpose and usage - **Simplified Maintenance**: Logical structure makes updates and additions easier - **Better Onboarding**: New team members can quickly understand the system This refactoring sets a solid foundation for all Cursor AI-related configurations and rules, making it easier for the team to leverage Cursor's capabilities.
2025-04-11 06:34:33 +00:00
---
description:
globs:
alwaysApply: true
---
# Test Generator
```yaml
name: Test Generator
description: Automatically generates appropriate tests for code changes
author: Cursor AI
version: 1.0.0
tags:
- testing
- automation
- quality
activation:
always: true
event:
- file_change
- command
triggers:
- file.created
- file.modified
- command: "generate_tests"
```
## Rule Definition
This rule analyzes code changes and generates appropriate test cases to ensure proper test coverage.
## Test Generation Logic
```javascript
// Main function to generate tests for code changes
function generateTests(files, codebase) {
const testPlans = [];
// Process each changed file
for (const file of files) {
if (shouldGenerateTestsFor(file)) {
const testPlan = createTestPlan(file, codebase);
testPlans.push(testPlan);
}
}
return {
testPlans,
summary: `Generated ${testPlans.length} test plans`
};
}
// Determine if we should generate tests for a file
function shouldGenerateTestsFor(file) {
// Skip test files, configuration files, etc.
if (file.path.includes('.test.') || file.path.includes('.spec.')) {
return false;
}
// Skip certain file types
const skipExtensions = ['.md', '.json', '.yml', '.yaml', '.svg', '.png', '.jpg'];
if (skipExtensions.some(ext => file.path.endsWith(ext))) {
return false;
}
return true;
}
// Create a test plan for the file
function createTestPlan(file, codebase) {
const testType = determineTestType(file);
const testCases = analyzeFileForTestCases(file, codebase);
return {
sourceFile: file.path,
testType,
testFile: generateTestFilePath(file, testType),
testCases,
testFramework: selectTestFramework(file)
};
}
// Determine the appropriate type of test
function determineTestType(file) {
if (file.path.includes('app/client')) {
if (file.path.includes('/components/')) {
return 'component';
} else if (file.path.includes('/utils/')) {
return 'unit';
} else if (file.path.includes('/api/')) {
return 'integration';
}
return 'unit';
} else if (file.path.includes('app/server')) {
if (file.path.includes('/controllers/')) {
return 'controller';
} else if (file.path.includes('/services/')) {
return 'service';
} else if (file.path.includes('/repositories/')) {
return 'repository';
}
return 'unit';
}
return 'unit'; // Default
}
// Analyze file to determine test cases needed
function analyzeFileForTestCases(file, codebase) {
// This would contain complex analysis of the file
// to determine appropriate test cases
const testCases = [];
// Example test cases for different file types
if (file.path.includes('.tsx') || file.path.includes('.jsx')) {
testCases.push(
{ type: 'render', description: 'should render correctly' },
{ type: 'props', description: 'should handle props correctly' },
{ type: 'interaction', description: 'should handle user interactions' }
);
} else if (file.path.includes('.java')) {
testCases.push(
{ type: 'normal', description: 'should execute successfully with valid input' },
{ type: 'exception', description: 'should handle exceptions with invalid input' }
);
}
return testCases;
}
// Generate path for the test file
function generateTestFilePath(file, testType) {
if (file.path.includes('app/client')) {
const basePath = file.path.replace(/\.(ts|tsx|js|jsx)$/, '');
return `${basePath}.test.${file.path.split('.').pop()}`;
} else if (file.path.includes('app/server')) {
return file.path.replace(/\.java$/, 'Test.java');
}
return file.path + '.test';
}
// Select appropriate test framework
function selectTestFramework(file) {
if (file.path.includes('app/client')) {
if (file.path.includes('/cypress/')) {
return 'cypress';
}
return 'jest';
} else if (file.path.includes('app/server')) {
return 'junit';
}
return 'jest'; // Default
}
// Generate actual test code based on the test plan
function generateTestCode(testPlan) {
// This would create the actual test code based on the framework and test cases
// This is a placeholder that would contain complex logic to generate tests
return "// Generated test code would go here";
}
// Run on activation
function activate(context) {
// Register event handlers
context.on('file.created', (event) => {
const file = context.getFileContent(event.file.path);
const codebase = context.getCodebase();
return generateTests([file], codebase);
});
context.on('file.modified', (event) => {
const file = context.getFileContent(event.file.path);
const codebase = context.getCodebase();
return generateTests([file], codebase);
});
context.registerCommand('generate_tests', (args) => {
const filePath = args.file || context.getCurrentFilePath();
if (!filePath) {
return {
status: "error",
message: "No file specified"
};
}
const file = context.getFileContent(filePath);
const codebase = context.getCodebase();
return generateTests([file], codebase);
});
}
// Export functions
module.exports = {
activate,
generateTests,
generateTestCode,
shouldGenerateTestsFor,
createTestPlan
};
```
## When It Runs
This rule can be triggered:
- When code changes are made and tests need to be created
- When a new file is created
- When an existing file is modified
- When a developer runs the `generate_tests` command in Cursor
- When submitting a PR with code changes that lack tests
## Usage Example
1. Make code changes to a file
2. Run `generate_tests` in Cursor
3. Review the generated test plan
4. Accept or modify the suggested tests
5. Run the tests to verify your changes
## Test Generation Best Practices
### Frontend Tests
For React components, tests should typically verify:
- Component renders without crashing
- Props are correctly handled
- User interactions work as expected
- Edge cases are handled properly
Example Jest test for a React component:
```jsx
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import Button from './Button';
describe('Button component', () => {
it('renders correctly', () => {
render(<Button label="Click me" />);
expect(screen.getByText('Click me')).toBeInTheDocument();
});
it('calls onClick handler when clicked', () => {
const handleClick = jest.fn();
render(<Button label="Click me" onClick={handleClick} />);
fireEvent.click(screen.getByText('Click me'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
});
```
### Backend Tests
For Java services, tests should typically verify:
- Methods return expected results for valid inputs
- Proper exception handling for invalid inputs
- Business logic is correctly implemented
- Edge cases are handled properly
Example JUnit test for a Java service:
```java
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void testCreateUser_ValidInput_ReturnsCreatedUser() {
User user = new User("test@example.com", "password");
User result = userService.createUser(user).block();
assertNotNull(result);
assertNotNull(result.getId());
assertEquals("test@example.com", result.getEmail());
}
@Test
public void testCreateUser_DuplicateEmail_ThrowsException() {
User user = new User("existing@example.com", "password");
// First creation should succeed
userService.createUser(user).block();
// Second attempt with same email should fail
StepVerifier.create(userService.createUser(user))
.expectError(DuplicateUserException.class)
.verify();
}
}