DevUI是一支兼具设计视角和工程视角的团队,服务于华为云DevCloud平台和华为外部数个中后盾零碎,服务于设计师和前端工程师。
官方网站:devui.design
Ng组件库:ng-devui(欢送Star)
官网交换:增加DevUI小助手(devui-official)
DevUIHelper插件:DevUIHelper-LSP(欢送Star)
引言
作为一个成熟的web前端工程师,咱们都熟知,编写单元测试用例,对前端而言,的确收益不大,业务代码还写不完呢,写什么测试用例呐,大略这是诸多web前端工程师的现状。
那么为什么我还要介绍单元测试用例编写呢?
在开发侧发现产品质量问题,对于开发来说,是老本最低的一种保障上线产品质量的办法。
在开发时编写测试用例,就是诸多从开发侧发现问题的策略之一。
在对devui组件库进行单元测试用例编写的时候,会思考两点:
- 首先开源库曾经有了组件的实现,测试驱动开发的场景比拟弱;
- 如果基于开源组件库进行开发应用,咱们仅关怀咱们本人罕用的一些性能是否可能保障。
本文将以组件库中的Button组件为例,开展对于DevUI开源组件库单元测试用例编写的介绍。
1 编写单元测试用例前的筹备
Step 1: 克隆ng-devui源码
先将ng-devui组件库源码克隆下来,装置依赖包后保障npm start可能启动我的项目:
Step 2: 找到启动单元测试的命令
我的项目启动后,返回package.json文件,能够看到有两个test命令:
这个时候可能有些读者有点懵逼,这两个命令,我该运行哪个呢?
通过查看angular.json查看应该运行的命令,拉到angular.json文件底部,能够查看到默认运行的是devui,我的项目中有三个我的项目:devui
、devui-e2e
、devui-lib
。
devui的根门路是src
,devui-lib的根门路是devui
,而DevUI组件库的所有组件都在devui门路之下:
根据上述判断可知,DevUI组件库的我的项目应该是devui-lib
。
因而咱们应该运行的package.json
中的test:lib
命令:
npm run test:lib
Step 3: 运行单元测试
运行完npm run test:lib
命令,能够看到DevUI组件库蕴含666个单元测试用例,其中5个跳过,661个胜利,0个失败。
2 开始编写Button组件的单元测试用例
Step 1: 找到Button组件的单元测试文件
关上button组件的源码目录,点击进入button的测试文件button.spec.ts,将遇到的第一个describe改写成fdescribe,从新运行npm run test:lib
,此时会发现只有15个运行胜利的用例,在button.spec.ts文件中搜寻it,会发现有15个it字段。
实际上,一个it即为一个单元测试用例,fdescribe示意,运行的时候只运行整个fdescribe下蕴含的it单元测试用例。
Step 2: 布局测试并筹备数据
为了保障文章的不那么冗余,这里只抛砖引玉,仅对button的局部性能进行单元测试,理解了单元测试用例运行的根本形式之后,就能够开始着手单元测试用例的编写。
编写前将现有的button.spec.ts文件内容删除,以便咱们从0开始编写单元测试用例。
编写测试用例时,要先将button组件引入,其中,beforeEach示意每个it单元测试用例执行前都会执行的操作。
@Component({ template: ` <d-button></d-button> `})class TestButtonAutoFocusComponent {}fdescribe('Button', () => { let fixture: ComponentFixture<any>; beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ButtonModule], declarations: [TestButtonComponent, TestButtonAutoFocusComponent] }).compileComponents(); })); ...});
这里将会对button的根本款式,common款式、按钮点击性能及禁用状态进行测试,因而,咱们会在TestButtonComponent测试组件中的button上加上款式、是否禁用、点击函数三个性能。
@Component({ template: ` <d-button [bsStyle]="style" (btnClick)="isClick()" [disabled]="disabled"></d-button> `})class TestButtonComponent { style = 'primary'; disabled = false; hasClick = false; isClick() { this.hasClick = true; }}
为了测试button相干的性能,咱们须要创立一个TestButtonComponent的实例,之后还要可能获取到这个实例中应用到的button元素,测试时往往会用到四个变量。
let fixture: ComponentFixture<any>;let testComponent: TestButtonComponent;let buttonDebug: DebugElement;let buttonNative: HTMLElement;beforeEach((() => { fixture = TestBed.createComponent(TestButtonComponent); testComponent = fixture.debugElement.componentInstance; buttonDebug = fixture.debugElement.query(By.css('d-button')); buttonNative = buttonDebug.nativeElement; fixture.detectChanges();}));
Step 3: 测试Button组件实例创立
为了保障button组件没有语法类的致命谬误,首先应该可能保障组件实例可能创立胜利,这也是咱们第一步须要进行的测试。
it('Button demo has created successfully', () => { expect(testComponent).toBeTruthy();});
Step 4: 测试Button款式
保障button组件的款式,则须要晓得组件可能正确的利用到款式类。
a) 通过查看button.component.html文件可知,正确的利用devui-btn,devui-btn-primary两个类即可示意button可能正确利用到款式类。这样,只有款式文件中的款式类正确,款式就正确。
b) 正确利用devui-btn,devui-btn-common两个类即示意common类型的button款式正确。
it('Button should apply css classes', () => { let buttonHtml = buttonDebug.query(By.css('button')); expect(buttonInsideNativeElement.classList.contains('devui-btn')).toBeTruthy(); expect(buttonInsideNativeElement.classList.contains('devui-btn-primary')).toBeTruthy(); testComponent.style = 'common'; fixture.detectChanges(); buttonHtml = buttonDebug.query(By.css('button')); expect(buttonInsideNativeElement.classList.contains('devui-btn')).toBeTruthy(); expect(buttonInsideNativeElement.classList.contains('devui-btn-common')).toBeTruthy();});
Step 5: 测试Button点击性能
保障button性能失常,则须要晓得点击button后,是否触发绑定的isClick事件,触发click事件胜利,则hasClick的值将由false变更为true。
a)首先,咱们应该判断一下hasClick的初始赋值是否正确;
b)接着,模仿点击button按钮所绑定的点击事件。
it('Button click', () => { expect(testComponent.hasClick).toBeFalsy(); let buttonHtml = buttonDebug.query(By.css('button')); buttonHtml.nativeElement.click(); fixture.detectChanges(); expect(testComponent.hasClick).toBeTruthy();});
Step 6: 测试禁用性能
对于disabled状态下,点击有效是其性能上的一大特点,同时disabled状态的button具备disabled属性,所以咱们的单元测试也是分为两个局部:
a)点击生效
b) button元素具备disabled属性
it('Button disabled should have disabled attribute', () => { testComponent.disabled = true; fixture.detectChanges(); // 点击生效 expect(testComponent.hasClick).toBeFalsy(); let buttonHtml = buttonDebug.query(By.css('button')); buttonHtml.nativeElement.click(); fixture.detectChanges(); expect(testComponent.hasClick).toBeFalsy(); // 具备disabled款式 expect(buttonHtml.nativeElement.hasAttribute('disabled')).toBeTruthy();});
3 对品质的敬畏之心
(1)作为前端开发,置信大多数开发都在业务开发中摸爬滚打,如果你遇到的业务对品质要求极高,任何一个重大事故都可能影响到诸多客户,拉低客户的效率,给客户造成损失。这种状况,你该如何保障你的代码品质?
(2)还有一种情景,你开发任何一个小的组件,比方一个小小的按钮,都可能会在几十,上百个业务中应用,你的任何一个失误,都有如落入湖水的石子,荡起整个湖面的涟漪。
以上两种情景,如果开发者没有测试充沛,贸然上线,都会造成重大损失。
稳固:是这两种开发场景第一需要。
这个时候,心愿上述单元测试用例的编写可能对读者有所启发,当然啦,咱们最终的指标仍然是以最小的老本解决更多的问题!
退出咱们
咱们是DevUI团队,欢送来这里和咱们一起打造优雅高效的人机设计/研发体系。招聘邮箱:muyang2@huawei.com。
文/DevUI 莫奈的关门弟子
往期文章举荐
《当初开始为你的Angular利用编写测试(二)》
《当初开始为你的Angular利用编写测试(一)》
《手把手教你搭建一个灰度公布环境》