symref
Version:
Static code checker for AI code agents (Windsurf, Cline, etc.)
176 lines (164 loc) • 5.92 kB
JavaScript
/**
* テストプロンプトを生成するクラス
*/
export class TestPromptGenerator {
/**
* テストプロンプトを生成する
* @param context 生成コンテキスト
* @returns 生成されたプロンプト
*/
generate(context) {
const { callGraph, fromRefs, toRefs, framework } = context;
return `# テストコード生成支援情報
## 1. 検証対象の呼び出し経路
${this.formatCallPath(callGraph)}
## 2. シンボル情報
### 開始シンボル: ${fromRefs.symbol}
- 定義: ${fromRefs.definition.filePath}:${fromRefs.definition.line}
- 種類: ${fromRefs.type}
- 参照数: ${fromRefs.references.length}
### 終了シンボル: ${toRefs.symbol}
- 定義: ${toRefs.definition.filePath}:${toRefs.definition.line}
- 種類: ${toRefs.type}
- 参照数: ${toRefs.references.length}
## 3. テスト要件
1. エントリーポイントからの呼び出しフローを検証
2. 各シンボルの呼び出しをspyで検証
3. 呼び出し順序の確認
4. エラーケースの検証
## 4. 推奨テスト構造
\`\`\`typescript
${this.generateTestStructure(context)}
\`\`\`
## 5. テストデータ
${this.generateTestData(context)}
## 6. 注意事項
- テストケースは実際のユースケースに合わせて調整してください
- モックの設定は必要に応じて追加してください
- 非同期処理の場合は適切な待機処理を追加してください
`;
}
/**
* 呼び出し経路をフォーマットする
* @param callGraph 呼び出しグラフ
* @returns フォーマットされた呼び出し経路
*/
formatCallPath(callGraph) {
if (!callGraph.paths || callGraph.paths.length === 0) {
return '呼び出し経路が見つかりませんでした。';
}
return callGraph.paths.map(path => {
return path.nodes.map((node, index) => {
const prefix = index === 0 ? '' : ' '.repeat(index - 1) + '└─ ';
return `${prefix}${node.symbol}`;
}).join('\n');
}).join('\n\n');
}
/**
* テスト構造を生成する
* @param context 生成コンテキスト
* @returns 生成されたテスト構造
*/
generateTestStructure(context) {
const { framework, fromRefs, toRefs } = context;
const isJest = framework === 'jest';
return `describe('${fromRefs.symbol} to ${toRefs.symbol} の呼び出し経路', () => {
// スパイとモックの設定
const spies = {
${this.generateSpySetup(context)}
};
// テストケース
it('正常系: 呼び出し経路が正しく実行されること', async () => {
// テストの実装
${this.generateTestImplementation(context)}
});
it('異常系: エラーが発生した場合の処理', async () => {
// エラーケースの実装
${this.generateErrorCase(context)}
});
});`;
}
/**
* スパイの設定を生成する
* @param context 生成コンテキスト
* @returns 生成されたスパイ設定
*/
generateSpySetup(context) {
const { callGraph } = context;
if (!callGraph.paths || callGraph.paths.length === 0) {
return '';
}
// 呼び出し経路から一意のシンボルを抽出
const uniqueSymbols = new Set();
callGraph.paths.forEach((path) => {
path.nodes.forEach((node) => uniqueSymbols.add(node.symbol));
});
return Array.from(uniqueSymbols)
.map(symbol => `${symbol}: ${context.framework === 'jest' ? 'jest.spyOn()' : 'sinon.spy()'}`)
.join(',\n ');
}
/**
* テスト実装を生成する
* @param context 生成コンテキスト
* @returns 生成されたテスト実装
*/
generateTestImplementation(context) {
const { fromRefs, toRefs } = context;
return `// ${fromRefs.symbol}を呼び出し
await ${fromRefs.symbol}();
// 呼び出し順序の検証
${this.generateCallOrderVerification(context)}`;
}
/**
* 呼び出し順序の検証を生成する
* @param context 生成コンテキスト
* @returns 生成された呼び出し順序検証
*/
generateCallOrderVerification(context) {
const { callGraph, framework } = context;
if (!callGraph.paths || callGraph.paths.length === 0) {
return '';
}
const isJest = framework === 'jest';
const path = callGraph.paths[0]; // 最初の経路を使用
return path.nodes.map((node, index) => {
const expectFunc = isJest ? 'expect' : 'assert';
return `${expectFunc}(spies.${node.symbol}).toHaveBeenCalled();`;
}).join('\n');
}
/**
* エラーケースを生成する
* @param context 生成コンテキスト
* @returns 生成されたエラーケース
*/
generateErrorCase(context) {
const { framework } = context;
const isJest = framework === 'jest';
return `// エラーを発生させる
${isJest ? 'jest.spyOn()' : 'sinon.stub()'}.mockRejectedValue(new Error('テストエラー'));
// エラーハンドリングの検証
${isJest ? 'expect' : 'assert'}(async () => {
await ${context.fromRefs.symbol}();
}).rejects.toThrow('テストエラー');`;
}
/**
* テストデータを生成する
* @param context 生成コンテキスト
* @returns 生成されたテストデータ
*/
generateTestData(context) {
return `## テストデータ例
\`\`\`typescript
const testData = {
// テストデータをここに定義
};
\`\`\`
## モックデータ例
\`\`\`typescript
const mockData = {
// モックデータをここに定義
};
\`\`\``;
}
}
//# sourceMappingURL=TestPromptGenerator.js.map