1
1
+++
2
2
title = " 重新造轮子系列(一):从0开发单元测试框架"
3
3
date = 2025-02-16T22:27:00-08:00
4
- lastmod = 2025-02-17T11:19:56 -08:00
4
+ lastmod = 2025-02-17T11:31:32 -08:00
5
5
tags = [" reinvent" ]
6
6
categories = [" ReInvent: 重新造轮子系列" ]
7
7
draft = false
@@ -49,27 +49,6 @@ Javascript 比较流行的测试框架是 [Mocha](https://mochajs.org/) 和 [Jes
49
49
50
50
我们用以下的状态机来判断测试的结果:
51
51
52
- ``` plantuml
53
- @startuml
54
-
55
- start
56
-
57
- if (是否抛出异常) then (yes)
58
- if (异常是否是assert.AssertionError) then (yes)
59
- #yellow:Fail;
60
- else (no)
61
- #red:Error;
62
- endif
63
- else (no)
64
- #palegreen:Pass;
65
-
66
- endif
67
-
68
- stop
69
-
70
- @enduml
71
- ```
72
-
73
52
{{< figure src="/ox-hugo/unit_test_result_state.png" >}}
74
53
75
54
我们把要实现的单元测试框架命名为 ` Hope ` , 根据上面的状态机,我们很快就可以写出一个原型:
@@ -201,7 +180,8 @@ export default new Hope()
201
180
2 . 那么是否意味着,每个 ` import ` 语句都会运行一下 ` new Hope() ` 呢? 并不是,Node会缓存导入的 ` module ` ,也就是说无论一个 ` module ` 被导入多少次, 它也只会执行一次代码。
202
181
203
182
只要导入 ` hope.ts ` 之后, 就可以使用 ` hope.test() ` 会注册单元测试用例,以便后续执行:
204
- ![ ] ( /ox-hugo/unit_test_hope_structure.svg )
183
+
184
+ {{< figure src="/ox-hugo/unit_test_hope_structure.svg" >}}
205
185
206
186
最后, 我们只需要再实现下输出测试结果的功能,既支持输出一行的简短结果,又可以支持详尽的输出. 如果需要的话,后续还可以支持输出JSON, CSV, 或者HTML 格式的结果:
207
187
@@ -298,20 +278,6 @@ main(process.argv.slice(2))
298
278
299
279
整个框架的工作流程如下:
300
280
301
- ` ` ` plantuml
302
- @startuml
303
- pray .ts - > hope .ts : 1. import
304
- hope .ts - > hope .ts : 2. 创建hope实例
305
- pray .ts - > pray .ts : 3. 扫描所有的测试文件
306
- pray .ts - > test_add .ts : 4 import
307
- test_add .ts - > hope .ts : 5. import
308
- test_add .ts - > hope .ts : 6. 注册测试case
309
- pray .ts - > hope .ts : 7. run (), 运行注册的测试case
310
- pray .ts - > hope .ts : 8. 输出测试结果
311
- @enduml
312
-
313
- ` ` `
314
-
315
281
{{< figure src="/ox-hugo/unit_test_workflow.png" >}}
316
282
317
283
大功告成,现在就来运行下我们的单元测试:
@@ -330,16 +296,16 @@ errors:
330
296
331
297
#### <span class="section-num">3.4.1</span> 增加运行时间 {#增加运行时间}
332
298
333
- 我们还可以记录每个测试用例的运行时间:
299
+ 我们还可以记录每个测试用例的运行时间, 纳秒有点太小了,就精确到微秒即可 :
334
300
335
301
` ` ` js
336
302
run () {
337
303
this .todo .forEach (([comment , test ]) => {
338
304
try {
339
305
const now = process .hrtime .bigint ();
340
306
test ();
341
- const elapsedInMacro = (process .hrtime .bigint () - now) / (BigInt (1000 ));
342
- this .passes .push (comment + ` , execution time: ${ elapsedInMacro } us` );
307
+ const elapsedInMicro = (process .hrtime .bigint () - now) / (BigInt (1000 ));
308
+ this .passes .push (comment + ` , execution time: ${ elapsedInMicro } us` );
343
309
} catch (e) {
344
310
if (e instanceof assert .AssertionError ) {
345
311
this .fails .push (comment);
@@ -635,8 +601,8 @@ class Hope {
635
601
636
602
const now = microtime .now ();
637
603
test ();
638
- const elapsedInMacro = microtime .now () - now;
639
- this .passes .push (comment + ` , execution time: ${ elapsedInMacro } us` );
604
+ const elapsedInMicro = microtime .now () - now;
605
+ this .passes .push (comment + ` , execution time: ${ elapsedInMicro } us` );
640
606
641
607
if (this .teardownFn ) {
642
608
this .teardownFn ();
@@ -726,8 +692,8 @@ class Hope {
726
692
test ();
727
693
}
728
694
729
- const elapsedInMacro = (process .hrtime .bigint () - now) / (BigInt (1000 ));
730
- this .passes .push (comment + ` , execution time: ${ elapsedInMacro } us` );
695
+ const elapsedInMicro = (process .hrtime .bigint () - now) / (BigInt (1000 ));
696
+ this .passes .push (comment + ` , execution time: ${ elapsedInMicro } us` );
731
697
732
698
if (this .teardownFn ) {
733
699
if (this .isAsync (this .teardownFn )) {
0 commit comments