一、什么是 Weex 测试?
想象一下,你的蛋糕店决定开拓新业务:生产"预制蛋糕卷" ,卖给便利店。
- 传统的 Web:你的蛋糕是在自家厨房(浏览器)里现做现卖的。
- Weex :它是一个"蛋糕卷预制工厂"。你写的还是那份 Vue 食谱(
.vue
文件),但这个工厂会把你的食谱编译和打包成一种特殊的、便利店烤箱(移动端原生渲染引擎)能加热的半成品(JS Bundle) 。
Weex 测试 就是用来检验你这个"预制工厂"的:
- 转换得对不对:给你的 Vue 食谱,你能不能正确地转换成预制蛋糕卷的配方(生成正确的 JS Bundle)?
- 加热后效果好不好:便利店用他们的烤箱(Native 引擎)加热这个预制蛋糕卷后,出来的成品形态、口味对不对(渲染的UI和交互是否正确)?
- 体验是否一致:最终顾客在便利店买到的蛋糕卷,和在你店里吃到的现做蛋糕,味道和体验应该是一样的(保证 Web 和 Native 体验一致性)。
Weex 测试的核心是验证同一套 Vue 代码被转换成 Weex 格式后,在移动端原生环境下的渲染正确性和功能完整性。
二、Vue 2 Weex 测试的运行机制(流程图)
官方仓库(2.6 分支)里所有 Weex 相关测试 全部跑在 Jasmine 里,没有 Jest、也没有真机/模拟器参与;是通过「mock 的 Weex JS Runtime + 断言渲染结果 JSON」来完成的。在 Node.js 里完成「模板编译 → 虚拟 DOM → 原生指令」全链路验证。
Vue 2 的 Weex 测试核心是 "平台无关性" 和 "渲染器抽象" 验证,即同一套 Vue 核心代码通过不同的渲染器(Renderer)在不同平台(Platform)上运行。
以下是 Vue 2 Weex 测试的完整流程图:

-
编译时测试 (Compiler Test)
-
工具:
jasmine
(npm run test:weex
) -
位置:
test/weex/compiler/*.spec.js
-
过程:
- 把 Vue 模板喂给
compile(template, { target: 'weex' })
; - 拿到生成的
render
函数字符串; - 断言字符串里是否包含期望的
createElement('container', ...)
、staticStyle
等。
• 特点:只验证 编译输出,不执行渲染。
- 把 Vue 模板喂给
-
-
运行时测试 (Renderer Test)
-
工具:同样 Jasmine ,但会:
-- 引入
weex/runtime
里的 mock 实现(weex-vdom
,weex-env
);-- 在 Node.js 里模拟 Weex 的 DOM 和原生模块。
-
位置:
test/weex/runtime/*.spec.js
-
过程:
-
new Vue(options)
挂载到 mock 容器; -
触发 patch → 收集「原生渲染指令」数组;
-
断言:
- 指令数组里出现
{ type: 'container', style: { ... } }
; - 事件回调被正确注册;
- 生命周期钩子顺序正确。
• 特点:
-- 所有原生调用都是 JS 对象快照 ,无真机渲染;
-- 因此运行速度快,CI 可直接跑。
- 指令数组里出现
-
-
三、简单示例:测试一个组件在 Weex 下的转换
假设我们有一个简单的 Vue 2 组件。
源码 (src/components/Hello.weex.vue
)
xml
<template>
<div class="container">
<text class="message">{{ message }}</text>
<button @click="handleClick">Click me!</button>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello, Weex!'
}
},
methods: {
handleClick() {
this.message = 'Clicked!';
}
}
}
</script>
<style scoped>
.container {
justify-content: center;
align-items: center;
}
.message {
font-size: 48px;
color: #42b983;
}
</style>
Weex 编译测试 (tests/weex/compiler.spec.js
)
scss
// 1. 引入必要的依赖
import { compile } from 'weex-compiler'; // 假设的 Weex 编译模块
describe('Weex Compiler', () => {
it('should transform Vue template to Weex JSON structure', () => {
// Arrange: 准备 Vue 模板代码
const vueTemplate = `
<div class="container">
<text class="message">{{ message }}</text>
<button @click="handleClick">Click me!</button>
</div>
`;
// Act: 调用 Weex 编译器进行转换
const weexJson = compile(vueTemplate);
// Assert: 断言转换后的结构符合 Weex 规范
// 例如,div 被转换成了 container
expect(weexJson.type).toBe('container');
// 包含一个 text 子节点
expect(weexJson.children[0].type).toBe('text');
expect(weetJson.children[0].attr.class).toBe('message');
// 包含一个 button 子节点
expect(weexJson.children[1].type).toBe('button');
expect(weexJson.children[1].event.click).toBe('handleClick'); // 事件被正确绑定
});
});
Weex 运行时测试 (概念性,tests/weex/runtime.spec.js
)
less
// 这是一个非常概念性的示例,真实环境复杂得多
describe('Hello.vue Weex Runtime', () => {
it('should render correctly and respond to click', async () => {
// 1. 在模拟的 Weex JS Framework 环境中初始化 Vue 实例
const vm = createWeexVueInstance(HelloWeexComponent);
// 2. 断言:初始状态下的 Native 渲染指令是否正确发送
// 例如,模拟环境会记录调用了哪些原生模块API
expect(nativeModuleMock.createBody).toHaveBeenCalledWith(
expect.objectContaining({
type: 'container',
children: [
expect.objectContaining({
type: 'text',
attr: { value: 'Hello, Weex!' } // 初始文本正确
})
]
})
);
// 3. Act: 模拟触发按钮的 click 事件
triggerEvent(vm, 'button', 'click');
// 4. 等待 Vue 的异步更新队列刷新
await waitForUpdate();
// 5. Assert: 断言更新后的渲染指令
// 文本节点的 value 应该更新为 'Clicked!'
expect(nativeModuleMock.updateText).toHaveBeenCalledWith(
expect.anything(),
{ value: 'Clicked!' }
);
});
});
四、Vue 2 源码自身的 Weex 测试
Vue 2 源码本身包含了大量针对其 Weex 平台能力的测试,这些测试是保证其核心功能在 Weex 模式下表现一致且正确的关键:
- 平台模块注入 (Module Injection) :测试 Weex 环境下,特定的原生模块(如
dom
,stream
,navigator
)是否能被正确注入并替换 Web 环境的 API。 - 样式解析 (Style Parsing) :测试 Weex 有限的样式支持(如不支持部分 CSS 选择器)是否能被正确解析并转换为 Native 的样式模型。
- 事件系统 (Event System) :测试 Vue 的事件监听器(如
v-on
)是否能正确映射到 Weex 的原生事件上,并能正常触发回调。 - 渲染器差异 (Renderer Difference) :测试
Vue.prototype.$createElement
等渲染函数在 Weex 环境下是否生成正确的节点类型(如text
而不是span
)。 - 生命周期适配 (Lifecycle Adaptation) :测试某些生命周期(如
mounted
)在 Weex 环境下的行为是否与 Web 端一致。
Vue 2 源码中 Weex 测试的一个简化概念:
scss
// 测试平台模块的注入
it('should use weex module for DOM operations', () => {
// 模拟 Weex 环境
const weexDocument = { createElement: jest.fn() };
global.weex = { document: weexDocument };
// 强制 Vue 使用 Weex 平台
const Vue = createVueForWeex();
// 挂载一个组件会触发 DOM 操作
mountComponent();
// 断言:Vue 调用了 Weex 的 document.createElement,而不是浏览器的
expect(weexDocument.createElement).toHaveBeenCalled();
expect(document.createElement).not.toHaveBeenCalled(); // 浏览器的方法未被调用
});
总结
特性 | Weex 测试 |
---|---|
测试什么 | Vue 代码被编译为 Weex 格式 的正确性,及其在原生环境中的运行时行为 |
核心挑战 | 平台差异 (Web vs. Native)、样式兼容 、事件映射 、生命周期一致性 |
关键阶段 | 1. 编译时转换 2. 运行时渲染与交互 |
主要断言 | 1. 代码转换是否正确(结构比对) 2. 原生UI是否正确渲染、样式是否正确、事件是否响应 |
比喻 | 测试"预制工厂"能否把现做蛋糕的食谱正确转换成蛋糕卷的配方,并且便利店烤箱能把它加热成美味的产品。 |
结论 :
Vue 2 的 Weex 测试是保证其"一次编写,多端运行"能力的关键。它通过编译时测试来验证语法转换的正确性 ,再通过复杂的运行时测试验证在原生环境下的功能与体验,确保开发者能够用熟悉的 Vue 语法开发出高质量的原生应用。对于 Vue 2 源码本身,这些测试覆盖了从模板编译器、渲染器到平台适配层的每一个细节,是 Vue 生态跨端能力稳定性的基石。