diff --git a/.qwen/skills/create-game-module/SKILL.md b/.qwen/skills/create-game-module/SKILL.md index 60d57e0..2940856 100644 --- a/.qwen/skills/create-game-module/SKILL.md +++ b/.qwen/skills/create-game-module/SKILL.md @@ -105,7 +105,7 @@ kitten,white,8 kitten,black,8 cat,white,8 cat,black,8 -- ``` +``` ```typescript import parts from "./parts.csv"; @@ -207,40 +207,114 @@ async function turn(game: Game, turnPlayer: PlayerType, turnNumber: number) { ### 4. 创建测试 -基于 `createGameContext` 来测试游戏逻辑。 +测试文件位于 `tests/samples/` 目录下,命名格式为 `.test.ts`。 -- 为每种游戏结束条件准备至少一条测试 -- 为每种玩家行动准备至少一条测试 -- 使用 `createTestContext()` 和 `createTestRegion()` 测试辅助函数 +#### 测试要求 +**覆盖范围:** +- 每种游戏结束条件至少一条测试 +- 每种玩家行动至少一条测试 +- 边界条件和异常情况至少一条测试 +- 胜利和失败场景各至少一条测试 + +**测试结构:** ```typescript +import { describe, it, expect } from 'vitest'; import { createGameContext } from '@/core/game'; -import { createInitialState, registry, start } from './my-game'; +import { registry, createInitialState } from './my-game'; describe('My Game', () => { - it('should detect horizontal win for X', async () => { - const ctx = createGameContext({ - initialState: createInitialState(), - registry, + // 测试辅助函数 + function createTestContext() { + return createGameContext(registry, createInitialState()); + } + + // 测试工具函数 + describe('Utils', () => { + it('should calculate correct values', () => { + // 测试纯函数逻辑 + }); + }); + + // 测试命令 + describe('Commands', () => { + it('should perform action correctly', async () => { + const game = createTestContext(); + // 设置初始状态 + // 执行命令 + // 验证状态变化 }); - // 执行一系列操作 - await ctx.run('play X 0 0'); - await ctx.run('play O 1 0'); - await ctx.run('play X 0 1'); - await ctx.run('play O 1 1'); - await ctx.run('play X 0 2'); + it('should fail on invalid input', async () => { + const game = createTestContext(); + // 测试错误输入 + const result = await game.run('invalid-command'); + expect(result.success).toBe(false); + }); + }); - expect(ctx.value.winner).toBe('X'); + // 测试完整游戏流程 + describe('Game Flow', () => { + it('should complete a full game cycle', async () => { + // 模拟完整游戏流程 + }); }); }); ``` +**测试规范:** +- 使用 `createGameContext(registry, initialState)` 创建测试上下文 +- 使用 `game.run('command args')` 执行命令 +- 验证 `game.value` 的状态变化,而非命令返回值 +- 不要使用 `console.log` 或其他调试输出 +- 使用 `describe` 分组相关测试 +- 测试命名使用 `should...` 格式描述预期行为 +- 异步测试使用 `async/await` + +**命令测试示例:** +```typescript +it('should deal damage to enemy', async () => { + const game = createTestContext(); + setupTestGame(game); // 自定义测试设置 + + const enemyHpBefore = game.value.currentEnemy!.hp; + await game.run('play player1 card_1'); + + // 验证状态变化 + expect(game.value.currentEnemy!.hp).toBeLessThan(enemyHpBefore); + expect(game.value.playerHands.player1).not.toContain('card_1'); +}); + +it('should fail if card not in hand', async () => { + const game = createTestContext(); + setupTestGame(game); + + const result = await game.run('play player1 invalid_card'); + expect(result.success).toBe(false); + if (!result.success) { + expect(result.error).toContain('不存在'); + } +}); +``` + +**运行测试:** +```bash +# 运行所有测试 +npm run test:run + +# 运行特定测试文件 +npx vitest run tests/samples/my-game.test.ts + +# 运行特定测试用例 +npx vitest run -t "should deal damage" tests/samples/my-game.test.ts +``` + ## 完整示例 参考 `src/samples/boop/` 获取完整的`boop`游戏实现。 +参考 `src/samples/regicide/` 获取卡牌游戏的完整示例。 ## 相关资源 - [API 参考](./references/api.md) - 完整的 API 文档 -- [AGENTS.md](../../AGENTS.md) - 项目代码规范和架构说明 \ No newline at end of file +- [AGENTS.md](../../AGENTS.md) - 项目代码规范和架构说明