Solana项目实战_TypeScript测试文件语法与关键词

TypeScript测试文件语法与关键词

实战中发现测试文件ts的语法有很多不懂,集中总结一份供学习和参考备用。。。

1. 基础测试结构

describe('测试组名称', () => {
    it('测试用例名称', () => {
        // 测试代码
    })
})

2. 核心关键词解释

describe - 测试组/测试套件

describe('User Management', () => {
    // 这是一个测试组,包含多个相关的测试用例
    // 所有用户相关的测试都可以放在这里
})

作用:

  • 组织相关的测试用例
  • 提供测试的上下文描述
  • 可以嵌套使用

it - 单个测试用例

it('should validate user state structure', () => {
    // 这是一个具体的测试用例
    // 测试用户状态结构是否正确
})

作用:

  • 定义具体的测试场景
  • 描述测试的目的和期望结果
  • 每个it都是独立的测试

expect - 断言(验证结果)

expect(mockUserState.user).toBe('test-user')
expect(mockUserState.incensePoints).toBe(0n)
expect(mockUserState.incenseBalance).toEqual([])

作用:

  • 验证实际结果是否符合预期
  • 如果断言失败,测试就会失败

3. 常用断言方法

基本断言

expect(value).toBe(expected)           // 严格相等
expect(value).toEqual(expected)        // 深度相等(对象)
expect(value).toBeTruthy()             // 真值
expect(value).toBeFalsy()              // 假值

数值断言

expect(value).toBeGreaterThan(5)       // 大于
expect(value).toBeLessThan(10)         // 小于
expect(value).toBeGreaterThanOrEqual(0) // 大于等于

数组/字符串断言

expect(array).toContain(item)          // 包含
expect(array).toHaveLength(3)          // 长度
expect(string).toMatch(/pattern/)      // 正则匹配

4. 测试生命周期

beforeAll - 所有测试前执行

describe('User Management', () => {
    let payer: any
    let rpc: any

    beforeAll(async () => {
        // 在所有测试开始前执行一次
        const env = await setupTestEnvironment()
        payer = env.payer
        rpc = env.rpc
    })

    it('test 1', () => { /* 使用payer和rpc */ })
    it('test 2', () => { /* 使用payer和rpc */ })
})

beforeEach - 每个测试前执行

beforeEach(() => {
    // 在每个测试用例开始前执行
    // 重置测试状态
})

afterAll / afterEach - 清理函数

afterAll(() => {
    // 在所有测试结束后执行
    // 清理资源
})

5. 实际测试示例解析

import { describe, it, expect } from 'vitest'

describe('User Management', () => {           // 🔸 测试组开始
    it('should validate user state structure', () => {  // 🔸 第一个测试用例
        // 准备测试数据
        const mockUserState = {
            user: 'test-user',
            incensePoints: 0n,
            merit: 0n,
            incenseBalance: [],
            incenseNumber: 0,
            updateTime: 1234567890n,
            dailyIncenseCount: [],
            bump: 255
        }

        // 验证用户地址
        expect(mockUserState.user).toBe('test-user')    // 🔸 断言:用户地址应该等于'test-user'
        
        // 验证初始香火值
        expect(mockUserState.incensePoints).toBe(0n)   // 🔸 断言:香火值应该为0
        
        // 验证功德值
        expect(mockUserState.merit).toBe(0n)           // 🔸 断言:功德值应该为0
        
        // 验证香余额数组
        expect(mockUserState.incenseBalance).toEqual([]) // 🔸 断言:香余额应该是空数组
    })

    it('should handle incense balance operations', () => {  // 🔸 第二个测试用例
        let balance = 100
        
        // 测试增加余额
        balance += 50
        expect(balance).toBe(150)                      // 🔸 断言:100+50=150
        
        // 测试减少余额
        balance -= 30
        expect(balance).toBe(120)                      // 🔸 断言:150-30=120
        
        // 测试余额不足的情况
        const hasEnough = balance >= 200
        expect(hasEnough).toBe(false)                  // 🔸 断言:120 >= 200 应该是false
    })

    it('should validate daily incense limits', () => {     // 🔸 第三个测试用例
        const dailyLimit = 10
        const currentCount = 5
        const requestedAmount = 3

        // 测试是否可以继续烧香
        const canBurn = currentCount + requestedAmount <= dailyLimit
        expect(canBurn).toBe(true)                     // 🔸 断言:5+3 <= 10 应该是true

        // 测试超出限制的情况
        const overLimit = currentCount + 8 > dailyLimit
        expect(overLimit).toBe(true)                   // 🔸 断言:5+8 > 10 应该是true
    })
})

6. 测试命名规范

测试组命名

describe('User Management', () => {})      // ✅ 功能模块
describe('Incense Operations', () => {})   // ✅ 操作类型
describe('Daily Limits', () => {})          // ✅ 业务规则

测试用例命名

it('should initialize user correctly', () => {})        // ✅ 描述期望行为
it('should handle insufficient balance', () => {})      // ✅ 描述边界情况
it('should validate daily limits', () => {})            // ✅ 描述验证逻辑
it('should update incense count', () => {})             // ✅ 描述状态变化

7. 测试运行结果

当你运行测试时,会看到类似这样的输出:

✓ User Management
  ✓ should validate user state structure
  ✓ should handle incense balance operations  
  ✓ should validate daily incense limits

Test Results: 3 passed, 0 failed

8. 为什么使用这种语法?

  1. 结构化 - 清晰的测试组织方式
  2. 可读性 - 英文描述容易理解
  3. 标准化 - 行业通用的测试格式
  4. 工具支持 - IDE和测试框架原生支持
  5. 报告友好 - 生成美观的测试报告

9. 运行测试的命令

# 运行所有测试
npm test

# 运行单元测试
npm run test:unit

# 运行特定测试文件
npx vitest anchor/tests/unit/user.test.ts

# 监听模式(文件变化自动运行)
npx vitest --watch