JimmyLv / jimmylv.github.io

:bowtie: Agile Learning based on GitHub issues, KEEP Retrospection and Introspection! Thanks to @GitHub https://jimmylv.github.io/issues/
https://blog.jimmylv.info
MIT License
704 stars 114 forks source link

致Cypress:前端 TDD 的正确姿势到底是怎么样的? #322

Open JimmyLv opened 6 years ago

JimmyLv commented 6 years ago

重点研究一下 Cypress 并实践 ATDD。

最近要重温html css js 意识到一个东西,tdd实践本身有可能确实不适用于前端大规模应用 它和后端的上下文还有不同

是的呢 而且为什么需要测试呢? 我指的是 测那么多技术复杂度没有意义呀?

只有小步迭代和快速反馈的核心是不变的

技术复杂度为什么要我们开发来测试呀? 比如说,REST API的测试, 少一个字段多一个字段,这种测起来有何意义? 为什么不能直接用直接让invoker来决定到底有多少字段

我就在想,有没有一种方式,让测试更有意义,测到该测的地方去。

而TDD也是一样的,对哪些内容该TDD,还是说所有东西都TDD呢? 还是Tasking+验证方式,最为关键。

至于验证方式,是不是UT,我觉得可以有更多讨论。

假如我们有秒级反应的CI作为流水线, 假如我们有秒级反应的AI作为“真实”用户, 那我每写完一行代码,立马CI构建出“真实”产品,然后AI帮我测完所有“真实”场景,然后给我一个反馈,是不是也很完美?

你的理解很准确啊,tasking加验证方式。验证方式这里,tdd以前在后端适用,我觉得离不开spring java这个上下文,完全的面向对象,我们现在的测试模型也多来自这里

嗯,Spring帮我们autowried,凡是依赖都可以mock掉 但其实js里面所有import也可以mock掉,🤣

对。但面向对象这个上下文在js里是不纯的

前端的反馈,我觉得还是不如搞个4屏吧

也就是说,前端ut在具体实践上需要更具体的指导,有些实践可能要弱化

哈哈哈,设计稿、Chrome显示页面、IDE、Chrome DevTool

dev tool也要一屏卧槽

当然要呀,🤣 最好,devtool和file system连起来 试验CSS的时候可以直接save

哈哈哈哈 前端是重ui,交互,页面,布局的东西

我觉得提升前端工作效率 最需要着重的点 反而是 CSS 能力 这些东西复杂不在逻辑,反馈都是hot reload,跟tdd都没关系

CSS 阻碍了一切效率 尽管我优化查文档的效率可以达到秒级,但又有何用?还不是要查

看到一篇 e2e testing driven的文章 我觉得值得推荐下,Learn TDD in Vue | Learn TDD

EthanLin-TWer commented 6 years ago

哼,你看你不跳槽都不怎么讨论 TDD 的…

JimmyLv commented 6 years ago

因为以前直接做就是了呀,哪有这么多bbb的…🤣

JimmyLv commented 6 years ago

项目上的 Cypress Dashboard 已经搭建好放到 CI,团队层面的重构正在进行当中:

image.png

而个人的 E2E TEST 还有待进一步实践:

  1. E2E 测试的颗粒度到底要多大?多细?
  2. 如何 Group 测试用例,按Feature?按Page?
  3. E2E 的测试结果反馈有多快?
  4. E2E(Cypress) 的报错是否友好?
  5. 开发时心情是否愉悦?
JimmyLv commented 5 years ago

前端单元测试,真的很迷茫。 TDD到底该怎么玩, 每次看着Cypress的例子很动心,但是又感觉这样的E2E反馈相对会慢,而且E2E应该尽量少啊 那么就放弃最开始就写E2E,改成最开始只给组件单独做UT,但是组件级别的UT又很细节和冗余,修改频繁 那么如果不是给组件做UT,给vuex/redux store做TDD又很不容易坚持,而且BFF把大部分数据逻辑转移到了后端, 而前端大部分时间都在Styling和build配置上🤣

但是 前端花费过多时间在 Styling和 Build 配置上的状况也在改善中,CLI 之类的基础设施和开源 UI 库都在随着社区越变越好,借助 AntDesign Pro 就是个典型例子, 前端 TDD 其实我也还在一直探索中,「大前端」(包括BFF,特指由前端有能力来写的Node BFF)的能力和话语权越来越重,可以 TDD 的机会也在变多。

按照测试金字塔分层,这样的具体实践是比较合理的:

  1. Page 页面层级的 E2E 测试驱动开发 (Cypress)
  2. UI 组件驱动开发 和 快照测试(Storybook & Storyshot)
  3. Data 模块化后的数据流级别的 单元测试驱动开发 (Jest)
JimmyLv commented 5 years ago

所以衍生出来的问题就是,为了更方便在前端做 TDD,基础设施一定要搭建完好。

  1. UI 库的低维度组件应该遵循「设计系统」,其样式应该是参数化的,其变化应该是系统性的,其修改成本是牵一发而动全身从而相对较低的,剩下的是回归和approve的流程应该尽可能自动化起来。再者,具备品牌特征的主题色应当是 UI 库本身所能支持直接修改的,UI 库的核心不应包括 theme,作为设计语言的一部分而独立存在。参考:色彩 - Ant Design
  2. Build 基础设施一定要好,包括两部分:SSR(默认配置好Webpack/Babel/PWA的设置) + CI/CD(含团队规范),这样前端团队才不至于专门招聘一个 Webpack 配置工程师。而现在社区主流框架的趋势也是尽可能得提供开箱即用+插件式扩展的 CLI 工具(create-react-app或vue-cli),或者是 build即框架本身 的一些框架,比如 nuxt.js/next.js 或是 umi.js
  3. GraphQL BFF,数据获取这样的技术复杂度应该尽可能少,要知道 vuex/redux 的 action 不是专门拿来做数据请求 fetch 的!但是现实中很多人不过是把 actions 作为 API 的一层wrapper,居然还直接把 API response 作为 action 的输出(return)。理想情况下,组件应当尽可能快得获取到任何自己想要的数据,如果只是 render data 这样就变得非常纯粹,且发挥了 GraphQL 作为查询语言的机制,即 Siri。
  4. 说完组件根据 query data 的全量渲染(通过 VituralDOM 优化实际DOM变更),问题就回到了最复杂的数据 流/变化 操作,在 GraphQL 里面做 mutation 跟用 REST 提 POST 是没啥优势的,除了做 body 的 Type 校验提前检查错误而已。而根据 CQRS 的概念,这部分的 commands 所导致的数据变更才是最容易 TDD 和最有价值 TDD 的,即多种 commands 所导致的不同结果,不同 state 变化都是能直接通过测试完美覆盖的。
JimmyLv commented 5 years ago

👍: 另外e2e级别做TDD的路数,我不确定方向是不是对"


E2E 级别做 TDD,我的理解和想尝试的点就在于: 我一个页面只写一个 T,然后就先放着, 然后我把组件的骨架先搭出来,带上 [data-cy='cypress-id'] 然后就通过 UTDD 把数据操作撸出来,并且产出mock data即业务fixtures 然后再通过 Storybook 把具体的组件样式撸完,刚好注入前面的业务fixtures,然后打个快照,

前面谈论的是初写的时候,如果是修改代码,也分几个层级:

  1. 流程性的: 那就先改 E2E 测试,再改具体代码
  2. 数据操作细节上的:那就补一个 mutation/reducer UT,再改具体代码
  3. 样式上的:那就直接改Storybook对应的组件,对比和approve新快照即可

再者,我们如果用了antd这样的UI组件的话,那其实 Storybook 中的低维度组件需要自己真实去写的部分很少的,更多的是如何拼装出自己的业务UI组件(即UI+业务数据),而Snapshot快照的是 Antd组件集合+我们自己的theme就好。

我是特别想要试试,在项目上搞起来,感觉每个环节都有了反馈,大的小的,快的慢的。