当前位置: 首页 > 科技观察

通过构建自己的JavaScript测试框架来了解JS测试

时间:2023-03-19 10:09:12 科技观察

测试(单元或集成)是编程中非常重要的一部分。在当今的软件开发中,单元/功能测试已经成为软件开发不可或缺的一部分。随着Nodejs的出现,我们看到了很多超级JS测试框架的发布:Jasmine、Jest等。如果您的测试使用了一些外部资源(例如网络或数据库),则它不是单元测试。单元测试框架试图以人类可读的格式描述测试,以便非技术人员可以理解正在测试的内容。但是,即使您是技术人员,BDD格式的阅读测试也会让您更容易理解发生了什么。例如,如果我们要测试这个函数:functionhelloWorld(){return'Helloworld!';}我们会像这样写一个jasmine测试规范:describe('Helloworld',()=>{①it('sayshello',()=>{②expect(helloWorld())③.toEqual('Helloworld!');④});});描述:describe(string,function)it(string,function)安装和反汇编有时为了测试一个函数,我们需要一些设置,可能会创建一些测试对象。此外,我们可能需要在完成测试后执行一些清理活动,也许我们需要从硬盘驱动器中删除一些文件。这些活动称为“设置和拆卸”(用于清理),Jasmine有几个函数可以简化此操作:beforeAll在运行describe测试套件中的所有规范之前调用一次该函数。afterAll此函数将在测试套件中的所有规范完成后调用一次。beforeEach这个函数在每个测试规范之前被调用,它的函数已经运行。afterEach此函数在每个测试规范运行后调用。Node中的使用在Node项目中,我们在src文件夹同目录下的test文件夹中定义单元测试文件:node_prjsrc/one.jstwo.jstest/one.spec.jstwo.spec.jspackage.json测试包含Specification文件,这些规范文件是对src文件夹中文件的单元测试,package.json在脚本部分进行测试。{...,"script":{"test":"jest"//or"jasmine"}}如果在命令行运行npmruntest,jest测试框架会运行test文件夹下的所有spec文件,并在命令行显示结果。现在我们知道期望和构建什么,我们继续创建我们自己的测试框架。我们这个框架会基于Node,也就是会在Node上跑测试,后面会增加浏览器的支持。我们的测试框架将包含一个从命令行运行的CLI部分。第二部分是测试框架的源代码,位于框架的核心lib文件夹中。首先,我们首先创建一个Node项目。mkdirkwuocdkwuonpminit-y安装chalk依赖项,我们需要用它来为测试结果着色:npmichalk。创建一个lib文件夹,用于存放我们的文件。mkdirlib我们创建一个bin文件夹,因为我们的框架将用作NodeCLI工具。mkdirbin首先创建CLI文件。在bin文件夹中创建kwuo文件并添加以下内容:#!/usr/bin/envnodeprocess.title='kwuo'require('../lib/cli/cli')我们将hashbang设置为指向/usr/bin/envnode以便可以在不使用node命令的情况下运行该文件。我们将进程的标题设置为“kwuo”,并需要文件“lib/cli/cli”,这将调用文件cli.js,从而启动整个测试过程。现在,我们创建“lib/cli/cli.js”并填充它。mkdirlib/clitouchlib/cli/cli.js这个文件会搜索test文件夹,获取“test”文件夹下的所有测试文件,并运行测试文件。在实现“lib/cli/cli.js”之前,我们需要设置全局变量。describe,beforeEach,beforeEach,afterAll,beforeAll函数在测试文件中使用:describe('Helloworld',()=>{it('sayshello',()=>{expect(helloWorld()).toEqual('你好世界!');});});但两者都没有在测试文件中定义。如果没有ReferenceError,文件和函数如何工作?因为测试框架会先实现这些函数,并在运行测试文件之前将它们设置为全局变量,所以测试文件在调用测试框架已经设置的函数时不会出错。此外,这使测试框架能够收集测试结果并显示失败或通过的结果。让我们在lib文件夹中创建一个index.js文件:touchlib/index.js这里我们将设置全局变量并实现describe、it、expectEach、beforeEach、afterAll、beforeAll函数。//lib/index.jsconstchalk=require('chalk')constlog=console.logvarbeforeEachs=[]varafterEachs=[]varafterAlls=[]varbeforeAlls=[]varTotaltests=0varpassedTests=0varfailedTests=0varstats=[]varcurrDesc={it:[]}varcurrIt={}functionbeforeEach(fn){beforeEachs.push(fn)}functionafterEach(fn){afterEachs.push(fn)}functionbeforeAll(fn){beforeAlls.push(fn)}functionafterAll(fn){afterAlls.push(fn)}functionexpect(value){return{//MatchorAssertstthatexpectedandactualobjectsaresame.toBe:function(expected){if(value===expected){currIt.expects.push({name:`expect${value}toBe${expected}`,status:true})passedTests++}else{currIt.expects.push({name:`expect${value}toBe${expected}`,status:false})failedTests++}},//Matchtheexpectedandactualresultofthetest.toEqual:function(预期){if(value==expected){currIt.expects.push({name:`expect${value}toEqual${expected}`,status:true})passedTests++}else{currIt.expects.push({名称:`expect${value}toEqual${expected}`,status:false})failedTests++}}}}functionit(desc,fn){Totaltests++if(beforeEachs){for(varindex=0;index0?chalk.bgRed:chalk.bgGreenlog(logTitle('TestSuites'))for(varindex=0;index{it("shouldsubtract1from2",()=>{expect(sub(2,1)).toEqual(1)})it("shouldsubtract2from3",()=>{{expect(sub(3,2)).toEqual(1)})})//test/add.spec.jsconstadd=require('../src/add')describe("Addnumbers",()=>{it("shouldadd1to2",()=>{expect(add(1,2)).toEqual(3)})it("shouldadd2to3",()=>{expect(add(2,3)).toEqual(5)})})describe('ConcatStrings',()=>{letexpected;beforeEach(()=>{expected="Hello";});afterEach(()=>{expected="";});它('addHello+World',()=>{expect(add("Hello","World")).toEqual(expected);});});现在,我们将运行“test”以运行我们的测试框架:{“name”:“math”,“version”:“1.0.0”,“description”:“”,“main”:“index.js”,"scripts":{"test":"kwuo"},"keywords":[],"author":"ChidumeNnamdi","license":"ISC"}我们运行npmrun命令行测试,结果将是这样的:看,它向我们展示了统计数据,通过的测试总数,以及标记为“失败”或“通过”的测试套件列表看到通过的测试期望“添加你好+World",它将返回"HelloWorld",但我们希望返回"Hello"。如果我们更正它并重新运行测试,所有测试都会通过。//test/add.spec.js...describe('ConcatStrings',()=>{letexpected;beforeEach(()=>{expected="Hello";});afterEach(()=>{expected="";});it('addHello+World',()=>{expect(add("Hello","")).toEqual(expected);});});看,我们的测试框架看起来Jest和Jasmine一样工作。它只运行在Node上,在下一篇文章中我们将让它运行在浏览器上。代码在Github上Github仓库地址:philipszdavido/kwuoKwuo你可以使用NPM的框架:cdIN_YOUR_NODE_PROJECTnpminstallkwuo-D将package.json中的“test”改成这样:{...“scripts”:{“test”:“kwuo”...}}总结我们构建了测试框架,在此过程中,我们学习了如何使用全局变量将函数和属性设置为在运行时随处可见。我们看到了如何在我们的项目中使用describe、it、expect和各种匹配函数来运行测试。下次,您使用Jest或Jasmine,您会感到更加自信,因为现在您知道它们是如何工作的。