IME 自动化测试开源方案
测试自动化··12 分钟阅读
IME 自动化测试方案总结
现状:IME 测试自动化是个业界难题
- Headless 模式下没有操作系统 IME 可用
- 即使有 GUI 环境,程序化控制 IME 候选词选择非常困难
- CDP 除 Input.insertText 外,也提供实验性的 Input.imeSetComposition 接口,可设置组合输入,传入空字符串可取消组合。具体支持情况要按目标浏览器和协议版本核对。这仍不等于自动操作系统输入法的候选词窗口,也不能据此宣称已经覆盖真实输入法的完整交互。
现有开源方案
两种验证层次:事件处理与真实输入法
策略1:页面事件处理测试(轻量,不需要真实 IME) 手动构造 CompositionEvent 可检查页面是否依据 compositionstart/compositionend 维护组合状态,但不会启动真实输入法。下面的教学用例会等待完整防抖窗口,确认组合期间未跳转;结束时显式设置中文值并断言 URL 参数等于“啊”。fill() 不保证生成 isComposing=true 的 InputEvent,compositionend.data 也不会自动修改输入值。运行前须按目标页面配置地址、选择器、搜索参数及防抖时长;这不是本站或真实操作系统输入法已经通过的测试记录。
typescript
import { test, expect } from '@playwright/test';
// 教学用例:页面事件处理测试,不是真实操作系统 IME 测试。
// 按被测页面调整这三个配置;此处不是本站实测记录。
const PAGE_URL = 'http://localhost:3000/blog';
const SEARCH_PARAM = 'search';
const DEBOUNCE_MS = 300; // 必须与应用实际搜索防抖时间一致
test('组合期间不搜索,结束后提交最终中文', async ({ page }) => {
await page.goto(PAGE_URL);
const input = page.locator('input[placeholder*="搜索"]');
const initialURL = page.url();
await input.evaluate(el => {
el.dispatchEvent(new CompositionEvent('compositionstart', { bubbles: true }));
});
// fill 本身不保证生成 isComposing=true 的 InputEvent。
// 本例检查应用是否依据 compositionstart/end 维护组合状态。
await input.fill('a');
// 故意覆盖一个完整防抖窗口,不能只在 fill 后立即断言。
await page.waitForTimeout(DEBOUNCE_MS + 100);
await expect(page).toHaveURL(initialURL);
// compositionend.data 不会替我们修改 input.value。
await input.fill('啊');
await expect(input).toHaveValue('啊');
await input.evaluate(el => {
el.dispatchEvent(new CompositionEvent('compositionend', {
bubbles: true,
data: '啊',
}));
});
// 检查最终值,不只检查是否出现参数;poll 等待应用防抖提交。
await expect.poll(
() => new URL(page.url()).searchParams.get(SEARCH_PARAM),
{ timeout: Math.max(5000, DEBOUNCE_MS + 1000) },
).toBe('啊');
});
策略2:Adobe IMPACT(重量级,需要 GUI 环境) 如果你需要测试真实 IME 的完整行为(包括候选词窗口、多步选择等),IMPACT 是目前最专业的方案。但它需要:
-
Windows/macOS GUI 环境(不能 headless)
-
安装对应语言的系统 IME
-
Python + Selenium 环境
- 事件注入适合检查组合输入期间是否误触发搜索或跳转,可放进 CI。
- 最终仍应在目标浏览器和真实输入法中检查候选词选择、确认、取消与焦点切换。
- 本文的方案介绍与示例,不等于这些环境已经全部验证通过。参考资料见下方链接。