Macaca 提供多端录制回放工具 UIRecorder,录制回放工具无疑是最受用户欢迎的工具。录制是生产用例最低成本的方式,测试用例在这个过程中已经变成了“中间产物”。
跨多端设计
UIRecorder 支持 PC 和移动端,能够支持所有平台是因为 UIRecorder 在操作层和 Webdriver 服务端做了良好的解耦设计。UIRecorder 在 PC 端重度依赖 Chrome Extension 的事件拦截,移动端直接则与 Macaca Server 通信。
运行原理
- 启动 Macaca Server,提供 Webdriver 服务
- UIRecorder 在启动时会启动 ChromeDriver 服务
- 并加载内置的 Chrome 扩展程序
事件处理
用户端事件相对复杂的是 drag
手势,当操作左侧截图图片时,会执行如下的事件处理。
screenshot.addEventListener('click', function(event) {
var upX = event.offsetX, upY = event.offsetY;
var clickDuration = new Date().getTime() - downTime;
if (Math.abs(downX - upX) < 20 && Math.abs(downY - upY) < 20) {
var cmdData = getNodeInfo(Math.floor(upX * scaleX), Math.floor(upY * scaleY));
if (isSelectorMode) {
if (cmdData.path) {
showExpectDailog(cmdData.path);
}
} else {
var pressTime = new Date().getTime() - downTime;
cmdData.duration = (pressTime / 1000).toFixed(2);
saveCommand(clickDuration> 500 ? 'press' : 'click', cmdData);
}
downTime = 0;
}
});
screenshot.addEventListener('mousedown', function(event) {
downX = event.offsetX;
downY = event.offsetY;
downTime = new Date().getTime();
event.stopPropagation();
event.preventDefault();
});
screenshot.addEventListener('mouseup', function(event) {
var upX = event.offsetX, upY = event.offsetY;
if (downX >=0 && downY >= 0 &&
upX >= 0 && upY >= 0 &&
(Math.abs(downX - upX) >= 20 || Math.abs(downY - upY) >= 20)) {
var dragTime = new Date().getTime() - downTime;
saveCommand('drag', {
fromX: Math.floor(downX * scaleX),
fromY: Math.floor(downY * scaleY),
toX: Math.floor(upX * scaleX),
toY: Math.floor(upY * scaleY),
duration: (dragTime / 1000).toFixed(2)
});
downTime = 0;
}
event.stopPropagation();
event.preventDefault();
});
document.addEventListener('mouseup', function(event) {
if (downTime !== 0) {
var upX = event.clientX < screenshot.offsetLeft ? 0 : screenshot.width -1;
var upY = event.clientY;
var dragTime = new Date().getTime() - downTime;
saveCommand('drag', {
fromX: Math.floor(downX * scaleX),
fromY: Math.floor(downY * scaleY),
toX: Math.floor(upX * scaleX),
toY: Math.floor(upY * scaleY),
duration: (dragTime / 1000).toFixed(2)
});
downTime = 0;
}
});
screenshot.addEventListener('mousemove', function(event) {
var bestNodeInfo = {
node: null,
boundSize: 0
};
var x = Math.floor(event.offsetX * scaleX);
var y = Math.floor(event.offsetY * scaleY);
getBestNode(appTree, x, y, bestNodeInfo);
var node = bestNodeInfo.node;
if (node) {
var offsetLeft = screenshot.offsetLeft;
var offsetTop = screenshot.offsetTop;
var left = node.startX / scaleX;
var top = node.startY / scaleY;
var width = node.endX / scaleX - left;
var height = node.endY / scaleY - top;
showLine(left + offsetLeft, top + offsetTop, width, height);
} else {
hideLine();
}
});
document.addEventListener('keypress', function(event) {
if(!isLoading && !isShowDialog){
showTextDailog(event.key);
event.stopPropagation();
event.preventDefault();
}
});
录制是双刃剑
录制工具可以量产用例,将测试用例的生产成本降到最低,但从实质上看产生的测试用例可维护性也降低了,同时无法模块化,二次维护成本却提高了,只能重新录制。对于功能固化,不需要频繁维护的场景可以适当使用录制。