基于Virtual DOM与Diff DOM的测试代码生成
尽管是在年末,并且也还没把书翻译完,也还没写完书的第一稿。但是,我还是觉得这是一个非常不错的话题——测试代码生成。
当我们在写一些UI测试的时候,我们总需要到浏览器去看一下一些DOM的变化。比如,我们点击了某个下拉菜单,会有另外一个联动的下拉菜单发生了变化。而如果这个事件更复杂的时候,有时我们可能就很难观察出来他们之间的变化。
Virtual DOM
尽管这里的例子是以Jasmine作为例子,但是我想对于React也会有同样的方法。
一个Jasmine jQuery测试
如下是一个简单的Jamine jQuery的测试示例:
describe("toHaveCss", function (){beforeEach(function (){setFixtures(sandbox())})it("should pass if the element has matching css", function (){$("#sandbox").css("display", "none")$("#sandbox").css("margin-left", "10px")expect($("#sandbox")).toHaveCss({display: "none", "margin-left": "10px"})})
});
在beforeEach的时候,我们设定了固定的DOM进去,按照用户的行为做一些相应的操作。接着依据这个DOM中的元素变化 ,来作一些断言。
那么,即使我们已经有一个固定的DOM,想要监听这个DOM的变化就是一件容易的事。在我们断言之前,我们就会有一个新的DOM。我们只需要Diff一下这两个DOM的变化,就可以生成这部分测试代码。
virtual-dom与HyperScript
在寻觅中发现了virtual-dom这个库,一个可以支持创建元素、diff计算以及patch操作的库,并且它效率好像还不错。
virtual-dom可以说由下面几部分组成的:
createElement,用于创建virtual Node。
diff,顾名思义,diff算法。
h,用于创建虚拟树的DSL——HyperScript。HyperScript是一个JavaScript的HyperText。
patch,用于patch修改的内容。
举例来说,我们有下面一个生成Virtual DOM的函数:
function render(count) {return h('div', {style: {textAlign: 'center',lineHeight: (100 + count) + 'px',border: '1px solid red',width: (100 + count) + 'px',height: (100 + count) + 'px'}}, [String(count)]);
}
render函数用于生成一个Virtual Node。在这里,我们可以将我们的变量传进去,如1。就会生成如下图所示的节点:
{"children": [{"text": "1"}],"count": 1,"descendantHooks": false,"hasThunks": false,"hasWidgets": false,"namespace": null,"properties": {"style": {"border": "1px solid red","height": "101px","lineHeight": "101px","textAlign": "center","width": "101px"}},"tagName": "DIV"
}
其中包含中相对应的属性等等。而我们只要调用createElement就可以创建出这个DOM。
如果我们修改了这个节点的一些元素,或者我们render了一个count=2的值时,我们就可以diff两个DOM。如:
virtualDom.diff(render(2), render(1))
根据两个值的变化就会生成如下的一个对象:
{"0": {"patch": {"style": {"height": "101px","lineHeight": "101px","width": "101px"}},"type": 4,"vNode": {...}},"1": {"patch": {"text": "1"},"type": 1,"vNode": {"text": "2"}},...
}
第一个对象,即0中包含了一些属性的变化。而第二个则是文本的变化——从2变成了1。我们所要做的测试生成便是标记这些变化,并记录之。
标记DOM变化
由于virtual-dom依赖于虚拟节点vNode,我们需要将fixtures转换为hyperscript。这里我们就需要一个名为html2hyperscript的插件,来解析html。接着,我们就可以diff转换完后的DOM:
var leftNode = "", rightNode = "";
var fixtures = '<div id="example"><h1 class="hello">Hello World</h1></div>';
var change = '<div id="example"><h1 class="hello">Hello World</h1><h2>fs</h2></div>';
parser(fixtures, function (err, hscript) {leftNode = eval(hscript);
});parser(change, function (err, hscript) {rightNode = eval(hscript);
});var patches = diff(leftNode, rightNode);
接着,我们需要调用patch函数来做一些相应的改变。
luffa.patch(virtualDom.create(leftNode), patches)
并且,我们可以尝试在patch阶段做一些处理——输出修改:
function printChange(originRootNodeHTML, applyNode) {var patchType;for (var patchIndex = 0; patchIndex < applyNode.newNodes.length; patchIndex++) {patchType = applyNode.newNodes[patchIndex].method;switch (patchType) {case 'insert':printInsert(applyNode);break;case 'node':printNode(applyNode, originRootNodeHTML, patchIndex);break;case 'remove':printRemove(applyNode, originRootNodeHTML, patchIndex);break;case 'string':printString(applyNode, originRootNodeHTML, patchIndex);break;case 'prop':printProp(applyNode, originRootNodeHTML, patchIndex);break;default:printDefault(applyNode, originRootNodeHTML, patchIndex);}}
}
根据不同的类型,作一些对应的输出处理,如pringNode:
function printNode(applyNode, originRootNodeHTML, patchIndex) {var originNode = $(applyNode.newNodes[patchIndex].vNode).prop('outerHTML') || $(applyNode.newNodes[patchIndex].vNode).text();var newNode = $(applyNode.newNodes[patchIndex].newNode).prop('outerHTML');console.log('%c' + originRootNodeHTML.replace(originNode, '%c' + originNode + '%c') + ', %c' + newNode, luffa.ORIGIN_STYLE, luffa.CHANGE_STYLE, luffa.ORIGIN_STYLE, luffa.NEW_STYLE);
}
用Chrome的console来标记修改的部分,及添加的部分。
最后,我们似乎就可以生成相应的测试代码了。。。
其他
源码见:https://github.com/phodal/luffa
原文:基于Virtual DOM与Diff DOM的测试代码生成
基于Virtual DOM与Diff DOM的测试代码生成相关推荐
- 【Virtual DOM】虚拟 DOM 和 Snabbdom 库
前言 笔记来源:拉勾教育 大前端高薪训练营 阅读建议:建议通过左侧导航栏进行阅读 Virtual DOM 基本介绍 什么是 Virtual DOM Virtual DOM(虚拟 DOM),是由普通的的 ...
- 探秘vue核心之虚拟DOM与diff算法
探秘vue核心之虚拟DOM与diff 一.真实DOM和其解析流程 所有的浏览器渲染引擎工作流程大致分为5步: 创建 DOM 树 -> 创建 Style Rules -> 构建 Render ...
- 浏览器性能优化(2)React 虚拟 dom与diff算法
随着前端技术快速发展,现在的mvvm几大框架遍布前端行业,那么它们对浏览器的性能到底影响多大?与传统的jq相比做了哪些优化呢? 文章目录: React中的虚拟DOM是什么? 虚拟DOM的简单实现(di ...
- virtual DOM和真实DOM的区别_让虚拟DOM和DOMdiff不再成为你的绊脚石
来源 | https://juejin.im/post/5c8e5e4951882545c109ae9c Keep Moving 时至今日,前端对于知识的考量是越来越有水平了,逼格高大上了 各类框架大 ...
- 虚拟DOM和Diff算法 - 入门级
什么是虚拟Dom 我们知道我们平时的页面都是有很多Dom组成,那虚拟Dom(virtual dom)到底是什么,简单来讲,就是将真实的dom节点用JavaScript来模拟出来,而Dom变化的对比,放 ...
- diff算法_Virtual Dom和Diff算法
前言 这是一篇很长的文章!!!坚持看到最后有彩蛋哦!!! 文章开篇,我们先思考一个问题,大家都说 virtual dom 这,virtual dom 那的,那么 virtual dom 到底是啥? 首 ...
- 【总结】1135- 图解虚拟 DOM 之 DIff 算法
原文: https://juejin.cn/post/7000266544181674014 1. 目录 1. 相关知识点: 2. 虚拟DOM(Virtual DOM) 2.1. 什么是虚拟DOM 2 ...
- vue--mixin混入以及虚拟DOM和diff算法
mixin混入 使用它的好处: 将 options 中的配置项可以单独抽离出来,单独管理,这样方便维护 使用: 新建一个对象用来保存 options 中某一个配置项,比如: methods 接下来要将 ...
- 既然Vue通过数据劫持可以精准探测数据变化,为什么还需要虚拟DOM进行diff检测差异?
既然Vue通过数据劫持可以精准探测数据变化,为什么还需要虚拟DOM进行diff检测差异? 考点: Vue的变化侦测原理 前置知识: 依赖收集.虚拟DOM.响应式系统 现代前端框架有两种方式侦测变化,一 ...
最新文章
- Windows 8部署系列PART6:准备模板计算机配置
- tensowflow 训练 远程提交_深度解析AutoML工具——NNI:带上超参一起训练
- 认识VC++类向导的使用
- 欢迎使用Markdown编辑器写博客
- Tarjan的求双连通分量算法
- Quartz简单实例
- java nio 系列教程 四_Java NIO系列教程(四) Scatter/Gather
- kubernetes英语怎么读_英语音标怎么读?如何从零基础英语音标入门英语口语学习...
- 想转行数据分析,看完这篇再做决定
- 如何实现大批量UKEY远程连接管控?
- ATmega128单片机](熔丝修改后无法烧录程序情况)
- 测试计划报告---5W1H
- c语言变量报存在bss段,浅谈c语言代码段 数据段 bss段
- SAP GOS cl_gos_manager 添加附件功能
- c语言计算输入20个有符号整数,统计正整数,零,负整数的个数.操作,输入20个有符号整数,统计正整数.零.负整数的个数.并分别计算之和...
- 流利阅读 2019.1.22 Top S. Korean animal rights group slammed for destroying dogs
- \n和endl的区别
- http 301 302 303 307 308 傻傻分不清
- 从目标检测到小目标检测
- 为什么要给网桥分配IP地址
热门文章
- Android之ListActivity(一):布局与数据绑定
- 2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)
- sql语句中having的作用是?
- shell脚本之 if,case,for的用法
- 谷歌邮箱上不了的情况下怎么登录谷歌邮箱
- QQ远程协助没动静?QQ版本有讲究
- OSPF-网络类型(ip ospf network ?)
- gprs发送信号对方如何接收_和接收缓冲区比较:Netty发送缓冲区是如何设计的,why?...
- 自学成才翁_作为一名自学成才的开发者从“我的旅程”中吸取的教训
- 什么是棉绒,它如何节省您的时间?