this demo generated by the create-react-app
+ Typescript
, contains a complete component:
We should get a answer for those questions:
- Which part of our code should write unit testing
- Using this repo, I would try several strategies, we could compare the differences via PR, Then we could see the coverage and other indicators
- How could make test case writing more effective
- Using this repo, we could choose one way, which should be simply writing and quick test
- How do we choose testing tools
- How do we understand the boundary between unit testing with E2E testing
A complete component contains:
-
Only care about the first render
- useEffect
- Call hooks
- Call selectors
- Dispatch action
- Handle event
- render
-
using the
@testing-library/react-hooks
+react-test-render
we could simply mock a component (without any child render) and execute the hooks, then test it as a pure function- Call selector ✅
- Dispatch action ✅
- Converter ✅
-
We can simply mock the state, and call selectors as a pure function
-
We use the
createSlice
instead of template code of actions, reducers, we don't need to care about what we done in reducers and actions , we should focus on the thunk action functions- Actions
- Call services
- Reducers
- Manage State logic
- Actions
-
- Call API ✅ we can simply mock the request function, focus on the logic inside service
- Some response calculation ✅ keep its an pure function
-
- pure tool function ✅
When choosing testing tools, it is worth considering a few tradeoffs:
- Iteration speed vs Realistic environment: Some tools offer a very quick feedback loop between making a change and seeing the result, but don’t model the browser behavior precisely. Other tools might use a real browser environment, but reduce the iteration speed and are flakier on a continuous integration server.
- How much to mock: With components, the distinction between a “unit” and “integration” test can be blurry. If you’re testing a form, should its test also test the buttons inside of it? Or should a button component have its own test suite? Should refactoring a button ever break the form test?
Different answers may work for different teams and products.
https://zhuanlan.zhihu.com/p/72627206 React单元测试策略及落地
key point:
-
为什么要写单元测试
人员会流动,应用会变大。人员一定会流动,需求一定会增加,直至再也没有一个人能够了解应用的所有功能,那时对应用做出修改的成本将变得很高。因此,意图依赖人、依赖手工的方式来应对响应力的挑战首先是低效的,从时间维度上来讲也是不可能的。因此,为了服务于“高响应力”这个目标,随时重构整理代码是必须的,这就需要我们有一套自动化的测试套件,它能帮我们提供快速反馈,做质量的守卫者。唯解决了人工、质量的这一环,开发效率才能稳步提升,团队和企业的高响应力才可能达到。
-
TDD
单元测试应该由开发者,在开发软件的同时编写对应的单元测试。它应该是内建的,而不是后补的:也即在编写实现的同时完成单元测试,而不是写完代码再一次性补足。测试先行,这正是TDD的做法。使用TDD开发方法是得到可靠单元测试的唯一途径。
长久以来,大家都认为单测是单测,TDD是TDD,说单测必须要有,但是否使用TDD(测试先行)应该尊重开发者的习惯爱好。但事实是,且不说测试很难补,补出来的测试也几乎不可能完整覆盖我们对重构和质量的要求。TDD和单元测试是全有或全无:不做TDD,难以得到好的单元测试;TDD是获得可靠的单元测试的的唯一途径。除此之外别无捷径,想抛开TDD而获得一个好的单元测试套件是迷思,难以成功。
-
单元测试的价值原则
- 只关注输入输出,不关注内部实现
- 只测一条分支
- 表达力极强
- 看到测试时,你就知道它测的业务点是啥
- 测试挂掉时,能清楚地知道失败的业务场景、期望数据与实际输出的差异
- 不包含逻辑
- 测试需要都是简单的声明:准备数据、调用函数、断言,让人一眼就明白这个测试在测什么
- 运行速度快
https://hacks.mozilla.org/2018/04/testing-strategies-for-react-and-redux/ Testing Strategies for React and Redux
key point:
- We dispatch real Redux actions to test application state changes.
- We test each component only once using shallow rendering.
- We resist full DOM rendering (with
mount()
) as much as possible. - We test component integration by checking properties.
- Static typing helps validate our component properties.
- We simulate user events and make assertions about what action was dispatched.