本文作者 海杰(肖是杰)
源起---Field---value初始化踩坑记
问题背景
在做中后台需求时,遇到的坑
经过大量代码编写后,自测感觉良好,兴致勃勃地提测了
结果测试同学直接提了个bug:
点击添加应用信息,无法新增
通过debbuger发现
出bug的情况是传给自增组件applyInfo的value 为undefined, 而重构弹窗之前的时候是正常情况,它的value 为一个[] 空数组
(bug)
(正常情况)
出bug的原因是currentRecord在新建的时候初始化为{},因此取不到applyInfo,所以applyInfo为undefined
--->解决方法,加一个[]空数组进行兜底
下面是数据源的schema ,语义是 把this.props.currentRecord.applyInfo || [] 这个值传给TableEditAdd组件
问题是解决了,但是我感觉这块问题很难发现,因为一开始出bug的时候,我点击添加应用信息,没有任何报错,完全不知道哪里出了问题
这次解决方法是通过和之前未抽象成组件的时候,没有爆出问题的dialog进行了对比,发现value不同,所以才解决了
这个是点击添加应用信息按钮的代码
问题主要是出现在addArrayValue的时候,没有生效
因此,接下来我们就开始揭秘Fusion组件Field的神秘面纱
探索fusion组件
定位问题
其实上述问题的产生,主要是因为fusion组件value入参为undefined 而不是[]
因此我就去找了fusion的field对undefined 的错误拦截实现代码
1)对上述问题代码进行了debugger,可以看到this.getValue返回的是undefined,导致g.splice没有执行,从而阻塞了功能
2)找到Fusion 的 Field的源代码 ,一开始我看源码我就猜想了,是这个getValue的问题,猜测可能是这个方法返回了undefined,果不其然,一debug,终于定位到问题源码出现在这
知道原因后,改起来也就方便了
解决问题:
对于这种value为undefined的情况下,组件功能就不能使用了,是一个没有进行兜底处理的组件,就算是jsError也捕获不到这类型的错误(当时我想排查的时候,发现控制台什么错也没报,很诡异)
点击应用信息按钮时,调用了addArrayValue,没有生效
也就是说在调用this.props.field.addArrayValue(this.props.name, value.length ||0,{}); 的时候,需要保证props的value为【】空数组而不是undefined
查了fusion的文档,貌似并没有给开发者这样的 提示
建议fusion官方可以解决一下这个问题
1)要么做一个兜底处理,p为undefined的时候,默认赋值为空数组,这样报错不至于被吞掉
2)fusion 的官方文档加个注释,提示用户,initValue的时候不要为undefined
复盘:
记录一次踩坑,文档有时候并不完善,不过有没有可能field在设计的时候就默认用户传的一定不是undefined?
但是使用的人,有各种方法去用,所以很难覆盖全这样的细节,因此需要踩坑,需要有人真正去用,才能发现问题,这也是只有实际应用场景开发的时候才能发现。
而这个问题的发现,完全是靠测试同学在进行功能回归测试的时候才发现的
和e2e测试的爱恨情仇
那么有没有什么工具能发现上述的错误呢?能捕获到这样的错误?
答案是目前jsError捕获不到这样的错误
因此我思考了上述问题应该如何发现,我就想到这不是测试同学回归功能的时候发现的吗?
这不就可以用e2e回归测试来发现问题吗?
于是我着手对我的页面进行了e2e测试
e2e测试-TestCook
这里顺便安利一下好用的e2e测试cypress插件Cypress recorder 0.0.3
我直接点击页面,就可以记录到我的操作,生成e2e测试代码
// e2e测试代码编写
describe('测试添加应用信息功能', function() {
it('应用信息table需要新增一条', function() {
cy.get('#ice-container > .luna-page > div > .next-btn > .next-btn-helper').click()
cy.get('.next-form > .next-row > .next-col > .next-input > #name').click()
cy.get('.next-form > .next-row > .next-col > .next-input > #name').type('2222')
cy.get('.next-col > #applyInfo > div > .next-btn > .next-btn-helper').click()
cy.get('.next-table-cell:nth-child(1) > .next-table-cell-wrapper > .next-row > .next-col > .next-select > .next-input > .next-select-values > .next-select-trigger-search > input').should('be.visible')
cy.get('.next-form > .next-row > .next-col > .next-input > #defaultValue').click()
cy.get('.next-form > .next-row > .next-col > .next-input > #defaultValue').type('sss')
cy.get('.next-select > .next-input > .next-select-values > .next-select-trigger-search > #tagIdsStr').click()
cy.get('.next-select > .next-input > .next-select-values > .next-select-trigger-search > #tagIdsStr').type('sss')
cy.get('.next-form > .next-row > .next-col > .next-input > #description').click()
})
})
然后将测试代码放到仓库的cypress文件夹里
结果执行了testcook run ,立马测试完->
这个视频可不是我录制的哈,是cypress自带的录制视频的功能,非常方便好用
先看下正常情况下,重构之前的e2e测试后的录屏,一切正常
然后再看重构之后有问题的代码,进行e2e回归测试后,迅速曝出问题,方便我定位问题,下图便是screenshots
cypress还帮我们做了报错地方的截图,更快更清晰地定位问题
从图中,我们可以清晰地看到功能被阻塞了,因此我们就可以快速知道问题出在哪,及时解决
这里只是演示给大家看,实际上功能回归测试的时候,比我写的这段简单的e2e测试要复杂一些
我这里只是提前加了断言,点击新增后,对应的新增dom元素 should be visible
录屏也给我提示出上述问题了,方便我快速定位问题
总结
如果双11有自动化测试,我就不会踩坑了,我可以在e2e自动化测试后,立马定位到问题
我们可以通过TestCook的e2e测试功能,录制好测试case,在编写完代码之后进行功能回归测试的时候发现,这样就可以节省测试同学的大量回归测试时间
经过大量的代码重构之后,自己感觉没啥问题,也自测过了,但是测试同学还是发现了这个问题
事实证明回归测试很重要,而这种情况e2e测试完全就可以快速发现问题,
所以推荐一手TestCook,目前已经完成了e2e测试的功能链路,欢迎体验
另外我们要敬畏发布,安全生产无小事,回归测试有必要
TestCook主要采用的是cypress的e2e测试功能
why cypress
- 时间旅行(Time Travel)
- 会记录测试脚本运行的整个流程,生成对应的logs
- 实时加载
- 使用了异步编程的思想
-
结果一致性
-
调试功能
- 含debug工具
- 自动等待
- 类似Jest中的wait
- 网络控制
- 可手动发起网络请求
-
截图和录频
cypress还是开箱即用的,不需要再像selenium/webdriver需要安装框架选择断言库的复杂操作
Cypress enables you to write all types of tests:
-
Integration tests
-
Unit tests
Cypress can test anything that runs in a browser. ----摘自官网(so confident)