> For the complete documentation index, see [llms.txt](https://jimmylv.gitbook.io/tdd-frontend/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jimmylv.gitbook.io/tdd-frontend/coding/00-project-commentbox/05-outside-in-global-tdd-cycle.md).

# 任务 4：由外到内的前端 TDD

Hey，你好，我是 JimmyLv 吕靖，这是你开始 前端 TDD 练习的第 14 天，今天我们会重新练习一遍 CommentBox 项目，完整得把所有学到的东西用上，由外到内得把整个 TDD 流程串通起来，把 TDD 的纪律贯彻到底。

## TDD 的纪律

1. 没有失败的测试就不能写任何功能代码
2. 每次只允许写⼀个刚好失败的测试
3. 只允许写「刚好让失败的测试通过」的功能代码

总结一下，我们已经有了不同层级的 UI Testing：

1. E2E Testing （E2E Cypress 自动化处理主流程，同时可视化出来进行人为 check，通常是 BDD assertion 风格）
2. Interaction Testing （组件交互行为，通常跟 Testing-Library 来模拟用户行为，不过注意是单元层面，TDD assertion 风格）
3. Structural Testing （判断元素是否存在即可，比如动态数据的变化导致结构变化等，在 `2.` 中我们验证其数据，而在 `4.` 我们验证其样式）
4. CSS/Style Testing （组件样式，通常以 Design 设计为准，追求 100% 像素级还原，或者引入设计系统组件库统一风格）

![](https://2897586075-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LquCgGNObzQ8HY5Og1P%2F-M1jB6hekAeEzuJfbO3s%2F-M1jB7MFeN8_7j1KJCNp%2Ftest-pyramid.png?generation=1583487159297458\&alt=media)

## 练习目标

遵循 Cypress -> Testing Library -> Components Implementation -> Stroybook -> Cypress 的顺序：

1. 写一个失败的 E2E 测试，Cypress 模拟真实用户行为
2. 回到页面组件树，提取组件到独立的 `[Component].js` 文件，新建对应的 `[Component].test.js`
3. 写一个失败的 Component 测试，Testing Library 验证组件接口，实现功能并重构改善代码
4. 回到 Cypress E2E 测试，业务主流程功能已完成，重构并持续改善代码质量
5. 提取 `[Component].test.js` 测试中的组件渲染，新建对应的 `[Component].stories.js`
6. 写一个常用的 story 场景，回到组件进行样式调整，实现样式并通过 Storybook 截图快照测试

![SbE and TDD](https://2897586075-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LquCgGNObzQ8HY5Og1P%2F-M1jB6hekAeEzuJfbO3s%2F-M1jB7MHyS8Son1MoqJF%2FSbE%20and%20TDD.jpg?generation=1583487159502072\&alt=media)

动起手来，让我们重新撸一遍，以 YouTube 留言板为例：

![](https://2897586075-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LquCgGNObzQ8HY5Og1P%2F-M1NuYdz-gKpakD5Mcvb%2F-M1NuZOlB3q4YoJDFxpS%2Fyoutube-comments.jpg?generation=1583113456756837\&alt=media)

### 功能 1：基础评论框

一个最基本的评论框组件，带有作者头像、文本输入框，以及取消或评论操作按钮。

### 功能 2：留言列表

多个评论能够显示列表，并且包含列表数量和排序，并且每一条评论可以进行点赞或踩的操作。

### 功能 3：嵌套评论

评论可以嵌套，并且可以再次回复，保留 2 个层级，或可以支持无限层级的嵌套。

### 功能 4：回复框

回复评论框组件需要相同样式，想一想怎么复用呢？当然也需要支持自定义回复框。

![YouTube Comments](https://2897586075-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LquCgGNObzQ8HY5Og1P%2F-M1NuYdz-gKpakD5Mcvb%2F-M1NuZOnttBvmYJG1-oy%2Fyoutube-comments-reply.jpg?generation=1583113456685958\&alt=media)

## 思考一下

在你的心目中，什么是驱动式的前端开发工作流？什么是好的测试策略？

前端需要兼顾的东西太多，先写什么后写什么真的很重要。

而且需求变化，业务人员第一触及的都是前端，可能还得你来回答后端是否支持，由此多一层思考负担。

### 快照测试，真的有用吗？

很多人用快照测试的动机就是我不会测试我不想测试我想一键完成好像很酷炫的样子，然后打完快照发现啥都没测到而且伤害了开发体验。

* 我不会测试，
* 我不想测试，
* 我不会也不想学测试，
* 我会也不想写测试，
* 我想但是不会测试。

```javascript
const tree = renderer.create(<App />).toJSON()
expect(tree).toMatchSnapshot()
```

上述快照测试的动机，可以有一个，就是瞬间 90% 以上的测试覆盖率，因为整个 `<App />` 组件都被 render 了呢。

可能是因为领导们，要求项目测试覆盖率必须上 90%，然后你就顺手一个 Snapshot 测顶层 App，hmm...收获 90% 覆盖率。

但是，你再停下来想一想，这样的快照测试，真的有用吗？
