Kaynağa Gözat

📝 docs(testing): 更新Taro测试框架文档及相关引用

- 修正Taro测试工具引用,更新为实际使用的Jest + @testing-library/react + 自定义Taro组件mock框架
- 移除对@tarojs/test-utils-react的依赖说明
- 更新测试配置示例和测试用例写法
- 修正架构文档中测试策略文档的路径引用
- 添加版本历史记录和更新日志
- 更新文档最后修改日期为2025-10-20
yourname 3 ay önce
ebeveyn
işleme
420cbf587e
3 değiştirilmiş dosya ile 133 ekleme ve 92 silme
  1. 7 5
      docs/architecture.md
  2. 6 2
      docs/architecture/testing-strategy.md
  3. 120 85
      docs/taro-test.md

+ 7 - 5
docs/architecture.md

@@ -3,6 +3,7 @@
 ## 版本信息
 | 版本 | 日期 | 描述 | 作者 |
 |------|------|------|------|
+| 3.2 | 2025-10-20 | 修正Taro测试工具引用,更新为实际使用的测试框架 | Winston |
 | 3.1 | 2025-10-15 | 更新乘客信息支持多种证件类型 | Winston |
 | 3.0 | 2025-10-15 | 更新为出行服务项目架构 | Winston |
 | 2.4 | 2025-09-20 | 完善BMAD全栈架构规范,添加高层架构图、API规范、安全架构 | Winston |
@@ -30,6 +31,7 @@
 ### 变更日志
 | 日期 | 版本 | 描述 | 作者 |
 |------|------|------|------|
+| 2025-10-20 | 3.2 | 修正Taro测试工具引用,更新为实际使用的测试框架 | Winston |
 | 2025-10-15 | 3.1 | 更新乘客信息支持多种证件类型(身份证、港澳通行证、台湾通行证、护照等) | Winston |
 | 2025-10-15 | 3.0 | 更新为出行服务项目架构 | Winston |
 | 2025-09-20 | 2.4 | 完善BMAD全栈架构规范,添加高层架构图、API规范、安全架构 | Winston |
@@ -920,18 +922,18 @@ NODE_ENV=development
 - **测试位置**: 统一在 `tests/` 目录中,按类型分层组织
 - **覆盖率目标**: 核心业务逻辑 > 80%
 - **测试类型**: 单元测试、集成测试、E2E测试
-- **测试策略**: 详见 [测试策略文档](./testing-strategy.md)
+- **测试策略**: 详见 [测试策略文档](./architecture/testing-strategy.md)
 
 ### Taro小程序测试策略
-- **测试框架**: 使用Jest + @tarojs/test-utils-react (独立于主项目)
+- **测试框架**: 使用Jest + @testing-library/react + 自定义Taro组件mock (独立于主项目)
 - **测试位置**: `mini/tests/` 目录
 - **测试范围**: 组件测试、页面测试、应用级测试
 - **多端测试**: 支持H5和小程序环境测试
-- **详细规范**: 参见 [Taro测试规范文档](../taro-test.md)
+- **详细规范**: 参见 [Taro测试规范文档](./taro-test.md)
 
 ### 测试策略
 
-详细的测试策略、标准、执行流程和最佳实践请参考 [测试策略文档](./testing-strategy.md)。
+详细的测试策略、标准、执行流程和最佳实践请参考 [测试策略文档](./architecture/testing-strategy.md)。
 
 **实际测试结构**:
 ```text
@@ -1177,7 +1179,7 @@ interface ApiError {
 
 ### 联系方式
 - 架构师: Winston 🏗️
-- 最后更新: 2025-09-20
+- 最后更新: 2025-10-20
 
 ---
 

+ 6 - 2
docs/architecture/testing-strategy.md

@@ -3,6 +3,7 @@
 ## 版本信息
 | 版本 | 日期 | 描述 | 作者 |
 |------|------|------|------|
+| 3.2 | 2025-10-20 | 修正Taro测试工具引用,更新为实际使用的测试框架 | Winston |
 | 3.1 | 2025-10-16 | 修正测试路径描述,更新Taro测试说明 | Winston |
 | 3.0 | 2025-10-15 | 更新为出行服务项目测试策略 | Winston |
 | 2.6 | 2025-10-15 | 完成遗留测试文件迁移到统一的tests目录结构 | Winston |
@@ -55,7 +56,7 @@
 - **范围**: Taro小程序组件
 - **目标**: 验证组件渲染和交互行为
 - **位置**: `mini/tests/**/*.test.{ts,tsx}`
-- **框架**: Jest + @tarojs/test-utils-react
+- **框架**: Jest + @testing-library/react + 自定义Taro组件mock
 - **覆盖率目标**: ≥ 70%
 - **执行频率**: 每次组件变更
 
@@ -63,7 +64,7 @@
 - **范围**: 小程序页面级测试
 - **目标**: 验证页面生命周期和路由
 - **位置**: `mini/tests/pages/**/*.test.{ts,tsx}`
-- **框架**: Jest + @tarojs/test-utils-react
+- **框架**: Jest + @testing-library/react + 自定义Taro组件mock
 - **覆盖率目标**: ≥ 60%
 - **执行频率**: 每次页面变更
 
@@ -341,6 +342,9 @@ describe('UserService', () => {
 ### 更新日志
 | 日期 | 版本 | 描述 |
 |------|------|------|
+| 2025-10-20 | 3.2 | 修正Taro测试工具引用,更新为实际使用的测试框架 |
+| 2025-10-16 | 3.1 | 修正测试路径描述,更新Taro测试说明 |
+| 2025-10-15 | 3.0 | 更新为出行服务项目测试策略 |
 | 2025-10-15 | 2.6 | 完成遗留测试文件迁移到统一的tests目录结构 |
 | 2025-10-14 | 2.5 | 重构测试文件结构,统一到tests目录 |
 | 2025-09-20 | 2.4 | 更新版本与主架构文档一致 |

+ 120 - 85
docs/taro-test.md

@@ -1,12 +1,12 @@
 # Taro小程序测试规范
 
-版本:4.x
+版本:4.x (已更新为实际使用的测试框架)
 
 ## 概述
 
 本文档定义了出行服务项目中Taro小程序的测试规范。Taro测试使用独立的测试体系,与主项目的Vitest测试框架分离。
 
-**测试框架**: Jest + @tarojs/test-utils-react
+**测试框架**: Jest + @testing-library/react + 自定义Taro组件mock
 **测试位置**: `mini/tests/` 目录
 **测试范围**: 组件测试、页面测试、应用级测试、多端测试
 
@@ -18,13 +18,12 @@
 # 进入mini目录
 cd mini
 
-# React:
-npm i @tarojs/test-utils-react --save
-# 安装Jest
-npm i jest --save
+# 安装测试框架
+npm i jest @testing-library/react @testing-library/jest-dom --save-dev
+npm i @types/jest jest-environment-jsdom ts-jest --save-dev
 ```
 
-**注意**: @tarojs/plugin-platform-h5为前置 peerDependencies,请勿删除该依赖申明
+**注意**: Taro 4 项目使用 Jest + @testing-library/react 进行测试,无需安装 @tarojs/test-utils-react
 
 ## 配置
 
@@ -33,21 +32,42 @@ npm i jest --save
 
 ```javascript
 // mini/jest.config.js
-const defineJestConfig = require('@tarojs/test-utils-react/dist/jest.js').default
-
-module.exports = defineJestConfig({
+module.exports = {
+  preset: 'ts-jest',
   testEnvironment: 'jsdom',
-  testMatch: ['<rootDir>/tests/**/*.test.{js,ts,tsx}'],
+  setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
+  moduleNameMapping: {
+    '^@/(.*)$': '<rootDir>/src/$1',
+    '\.(css|less|scss|sass)$': 'identity-obj-proxy',
+    '\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
+      '<rootDir>/tests/__mocks__/fileMock.js'
+  },
+  testMatch: [
+    '<rootDir>/tests/**/*.spec.{ts,tsx}',
+    '<rootDir>/tests/**/*.test.{ts,tsx}'
+  ],
   collectCoverageFrom: [
     'src/**/*.{ts,tsx}',
     '!src/**/*.d.ts',
-    '!src/app.tsx',
-    '!src/app.config.ts'
+    '!src/**/index.{ts,tsx}',
+    '!src/**/*.stories.{ts,tsx}'
   ],
   coverageDirectory: 'coverage',
   coverageReporters: ['text', 'lcov', 'html'],
-  setupFilesAfterEnv: ['<rootDir>/tests/setup.ts']
-})
+  testPathIgnorePatterns: [
+    '/node_modules/',
+    '/dist/',
+    '/coverage/'
+  ],
+  transform: {
+    '^.+\\.(ts|tsx)$': 'babel-jest',
+    '^.+\\.(js|jsx)$': 'babel-jest'
+  },
+  transformIgnorePatterns: [
+    '/node_modules/(?!(swiper|@tarojs)/)'
+  ],
+  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json']
+}
 ```
 
 ### package.json脚本配置
@@ -64,102 +84,117 @@ module.exports = defineJestConfig({
 }
 ```
 
-`defineJestConfig` 已内置了部分初始化配置,需要修改可自行配置覆盖。配置文件参考 [Jest官网](https://jestjs.io/docs/configuration)。
-
-编写测试用例
-组件级别
-// __test__/main/index.test.js
-import TestUtils from '@tarojs/test-utils-react'
-import Hello from '../../src/components/Hello.tsx'
-const testUtils = new TestUtils()
-describe('App', () => {
-  it('RenderComponent', async () => {
-    // React跟Vue相同用法
-    await testUtils.mount(Hello, {
-      props: {
-        // 配置项
-        a: 1,
-      },
-    })
-    // 等待页面出现.btn这个节点
-    const btn = await testUtils.queries.waitForQuerySelector('.btn')
-    // 等待react的渲染更新完成
-    await testUtils.act(() => {
-      // 触发点击事件
-      testUtils.fireEvent.click(btn)
-    })
-    // 打印渲染结果
-    expect(testUtils.html()).toMatchSnapshot()
-    // <div class="hello">...
+配置文件参考 [Jest官网](https://jestjs.io/docs/configuration)。
+
+## 编写测试用例
+
+### 组件级别测试
+```typescript
+// tests/components/button.test.tsx
+import { render, screen, fireEvent } from '@testing-library/react'
+import Button from '../../src/components/Button'
+
+describe('Button Component', () => {
+  it('应该渲染按钮并响应点击事件', () => {
+    const handleClick = jest.fn()
+
+    render(<Button onClick={handleClick}>点击我</Button>)
+
+    const button = screen.getByRole('button', { name: '点击我' })
+    expect(button).toBeInTheDocument()
+
+    fireEvent.click(button)
+    expect(handleClick).toHaveBeenCalledTimes(1)
   })
 })
+```
 
-运行测试
-# package.json
-# scripts: {
-#   "test": "jest",
-# }
-npm run test
+### 页面级别测试
+```typescript
+// tests/pages/index.test.tsx
+import { render, screen } from '@testing-library/react'
+import Index from '../../src/pages/index'
 
-应用级别
-// __test__/main/index.test.js
-import TestUtils from '@tarojs/test-utils-react'
-import Taro from '@tarojs/taro'
-import App from '../../src/app.ts'
-const testUtils = new TestUtils()
-describe('App', () => {
-  it('RenderApp', async () => {
-    await testUtils.createApp()
-    // 监听/pages/index/index这个页面路由的onShow生命周期触发
-    await testUtils.PageLifecycle.onShow('/pages/index/index')
-    // 跳转到第二个页面
-    Taro.navigateTo({ url: '/pages/second/index' })
-    // 监听/pages/second/index这个页面路由的onShow生命周期触发
-    await testUtils.PageLifecycle.onShow('/pages/second/index')
-    // 当/pages/second/index触发onShow后,打印页面内容
-    expect(testUtils.html()).toMatchSnapshot()
-    // <body><div class="taro_router" id="app">...
+describe('Index Page', () => {
+  it('应该渲染首页内容', () => {
+    render(<Index />)
+
+    expect(screen.getByText('欢迎使用出行服务')).toBeInTheDocument()
+    expect(screen.getByRole('button', { name: '开始使用' })).toBeInTheDocument()
   })
 })
+```
+
+### 运行测试
+```bash
+# 在mini目录下执行
+npm run test
+```
+
+## 多端测试
 
-多端
 对于小程序的测试,我们提供了环境变量对 Jest 环境进行区分:TARO_ENV_JEST,我们可以在调用 jest 测试时设置对应的环境变量
 
+```json
 // package.json
-scripts: {
-  "test": "jest",
-   "test:weapp": "export TARO_ENV_JEST=weapp && jest"
+{
+  "scripts": {
+    "test": "jest",
+    "test:h5": "export TARO_ENV_JEST=h5 && jest",
+    "test:weapp": "export TARO_ENV_JEST=weapp && jest"
+  }
 }
+```
 
 这里会有几点差异:
 
-环境差异
-这里会将运行代码中的process.env.TARO_ENV切换为TARO_ENV_JEST的值,主要用于一些"环境判断"比如下面的代码将会在test:weapp执行:
+### 环境差异
+这里会将运行代码中的 `process.env.TARO_ENV` 切换为 `TARO_ENV_JEST` 的值,主要用于一些"环境判断"比如下面的代码将会在 `test:weapp` 执行:
 
+```typescript
 if (process.env.TARO_ENV === 'weapp') {
   // ....setState(....)
   console.log('this is weapp')
 }
+```
 
-标签差异
-除此之外html()输出的节点内容也会改变,将以小程序标签的形式输出,例如:
+### 标签差异
+Taro 组件会根据环境变量渲染不同的标签,例如:
 
-<!-- h5 -->
-<taro-core-view className="cls">
-  <taro-image-view src="xxx">
-    <img src="xxx" />
-  </taro-image-view>
-</taro-core-view>
+```typescript
+// 在 H5 环境中
+<View className="cls">
+  <Image src="xxx" />
+</View>
 
-<!-- weapp -->
-<view className="cls">
+// 在微信小程序环境中会渲染为
+<view class="cls">
   <image src="xxx" />
 </view>
+```
 
-因为这是一个在线运行的测试工具,主要目的也是对用户行为和外部表现进行测试断言,在测试环境使用的还是以 h5 的形式来模拟整个程序的运行,对于其他小程序特有的生命周期和 API,我们推荐以下做法:
+### 模拟小程序 API
+对于小程序特有的生命周期和 API,我们推荐以下做法:
 
-生命周期: 使用PageLifecycle的triggerXxxxx进行生命周期的触发
-API: 使用jest提供的mock方法来模拟@tarojs/taro的 api,模拟小程序的返回值
+```typescript
+// 模拟 Taro API
+jest.mock('@tarojs/taro', () => ({
+  navigateTo: jest.fn(),
+  request: jest.fn(),
+  getStorage: jest.fn(),
+  setStorage: jest.fn(),
+}))
+
+// 在测试中使用模拟的 API
+import Taro from '@tarojs/taro'
+
+describe('小程序功能', () => {
+  it('应该调用导航API', () => {
+    Taro.navigateTo({ url: '/pages/index' })
+    expect(Taro.navigateTo).toHaveBeenCalledWith({ url: '/pages/index' })
+  })
+})
+```
 
 ## 项目特定测试指导