货拉拉JS SDK 一体化测试方案的快速实践
一、框架搭建:统一测试工程实现
1. 工程结构设计
创建以Vue为基础的“壳”工程,核心目录结构如下:
js-sdk-test-platform/ ├── src/ │ ├── components/ # 全局组件(含测试通用组件) │ ├── views/ # 测试页面 │ │ ├── testFunctional/ # 功能测试用例目录 │ │ │ ├── testCases/ # 具体测试用例文件 │ │ │ └── index.vue # 测试页面入口 │ │ ├── testPerformance/ # 性能测试用例 │ │ ├── testAutomation/ # 自动化框架 │ │ └── testReport/ # 测试报告页面 │ └── main.ts # 应用入口 ├── playwright/ # 自动化测试执行引擎 │ ├── tests/ │ │ ├── functional/ # 功能测试脚本 │ │ └── performance/ # 性能测试脚本 │ └── reports/ # 测试报告存储
2. 关键技术实现
- 统一编译与部署: 使用Vue打包方案(如Vite)实现多环境兼容,基于Docker镜像构建轻量化部署流程,避免重复环境搭建。
- 版本与资源管理: 通过统一代码库管理测试对象(SDK接口)、测试数据与用例,消除多工程资源割裂问题。
二、功能测试:API二次开发与用例管理
1. 用例拆分与加载机制
- 代码分离实现:
通过
import.meta.glob动态读取测试用例TS文件,实现前端页面与测试逻辑解耦:
// 读取所有测试用例文件
const allOptionsPath = import.meta.glob('./**.ts', { eager: true });
// 解析并排序用例
const allOptions = Object.keys(allOptionsPath).map(path => {
return Object.values(Object.assign({}, allOptionsPath[path]))[0];
}).sort((a, b) => {
if (a.groupName === b.groupName) return a.label.length - b.label.length;
return a.groupName.localeCompare(b.groupName);
});
- 用例分组展示: 通过Vue组件将用例按功能分组(如“基础操作”“图像渲染”),生成可交互测试菜单:
// 用例分组示例
export const MENU_OPTIONS = [{
label: '分组一',
key: 'comObj',
children: allOptions.map(item => ({
label: item.label,
key: `comObj_${item.key}`
}))
}];
2. 测试用例编写规范
- 核心结构示例:
export default {
label: '基础操作',
key: 'baseOptions',
children: [
{
label: 'zIndex减5',
key: 'declineZIndex',
methods(controller) {
checkAndDoAction(controller, (marker) => {
const currentZIndex = marker.getZIndex();
if (typeof currentZIndex === 'number') {
marker.setZIndex(Math.max(0, currentZIndex - 5));
message.success(`操作后ZIndex为: ${newZIndex}`);
}
});
}
}
]
}
三、接口自动化测试:Jasmine+MSW实现
1. 技术选型依据
- Jasmine优势: 自带断言库(expect),无需额外集成;支持浏览器内直接运行,适配SDK图像渲染场景(Jest需额外配置浏览器环境,Mocha集成度低)。
2. 核心实现示例
- 基础接口测试(同步/异步):
describe('baseMap Test suite', () => {
let mapInstances: IMap[];
it('setCenter()/getCenter()', done => {
const promises = mapInstances.map(async map => {
map.setCenter({ lng: 116.45, lat: 39.91 });
await utils.sleep(1000);
expect(map.getCenter().lng).toBeCloseTo(116.45, 3);
});
Promise.all(promises).then(done).catch(done.fail);
});
});
- 异常场景模拟(MSW拦截请求):
import { http, setupWorker } from 'msw';
const worker = setupWorker();
it('searchPoi()异常测试', async () => {
// 定义Mock响应
const proxy = http.post('https://api.test.com', async ({ request }) => {
// 校验请求参数
const params = new URLSearchParams(request.url.split('?')[1]);
expect(params.get('cityId')).toBe('1001');
// 返回错误响应
return HttpResponse.json(
{ ret: -9, msg: '网络错误' },
{ status: 500 }
);
});
// 启动Mock服务
await worker.start();
worker.use(proxy);
try {
await searchPoi({ cityId: '1001' });
} catch (err) {
expect(err.message).toContain('错误码:-9');
} finally {
await worker.stop();
}
});
四、性能测试:Stats.js+Playwright集成
1. 数据采集实现
- 帧率/内存监测:
import Stats from 'stats.js';
const stats = new Stats();
stats.showPanel(0); // 0: FPS, 1: 毫秒, 2: 内存
document.body.appendChild(stats.dom);
// 定时采集数据
function collectPerformanceData() {
stats.begin();
// 执行性能测试代码
stats.end();
requestAnimationFrame(collectPerformanceData);
}
collectPerformanceData();
2. 自动化执行链路
- Playwright脚本示例:
// performance.spec.ts
import { test, expect } from '@playwright/test';
test('连续setZoom性能测试', async ({ page }) => {
// 进入测试页面
await page.goto('http://test-platform/performance');
// 执行测试操作
await page.click('#start-test');
// 等待测试完成
await page.waitForSelector('#test-complete', { timeout: 30000 });
// 提取性能数据
const fpsData = await page.evaluate(() => {
// 从Stats.js获取数据
return window.performanceStats.getData();
});
// 断言性能指标
expect(fpsData.avg).toBeGreaterThan(50); // 平均帧率需>50
});
五、智能测试代码生成:DeepSeek API对接
1. 函数定义规范
- 工具函数结构化描述:
{
"type": "function",
"function": {
"name": "addMarker",
"description": "添加地图标记点",
"parameters": {
"type": "object",
"properties": {
"position": {
"type": "object",
"description": "经纬度坐标,格式{lng: number, lat: number}"
},
"content": {
"type": "string",
"description": "标记点显示内容"
},
"color": {
"type": "string",
"description": "标记点颜色(可选)"
}
},
"required": ["position", "content"]
}
}
}
2. 前后端交互流程
- 后端服务逻辑: 接收前端自然语言需求(如“在上海添加3个标记点”);调用DeepSeek V3 API,携带工具函数定义(如上);解析模型返回的函数调用参数,生成可执行代码:
// Spring Boot服务示例
@PostMapping("/generate-code")
public SseEmitter generateCode(@RequestBody UserRequest request) {
// 构造工具函数列表
List<ToolFunction> tools = getSdkFunctionList();
// 调用DeepSeek API
String code = deepSeekClient.call(
request.getRequirement(),
tools
);
// 流式返回代码
emitter.send(SseEmitter.event().name("code").data(code));
return emitter;
}
- 前端接收与渲染: 通过SSE流式接收代码片段,实时展示并支持语法高亮:
六、关键技术对比与实践要点
框架搭建 | Vue + Playwright | 多环境兼容、组件化复用 | 需统一测试数据格式与版本管理 |
功能测试 | import.meta.glob动态加载 | 用例与页面解耦,便于维护 | 需规范用例编写模板,避免逻辑冗余 |
自动化测试 | Jasmine + MSW | 浏览器原生支持、异常模拟便捷 | 异步测试需正确处理done()回调 |
性能测试 | Stats.js + Playwright | 实时数据采集、自动化链路完整 | 需设置合理的测试时长与性能阈值 |
智能生成 | DeepSeek + Function Calling | 自然语言转代码,降低开发门槛 | 需完善工具函数定义,补充参数约束说明 |
测试开发知识汇总 文章被收录于专栏
一些面试当中总结的知识点和测试框架技术选型以及AI赋能测试的内容
