测试(单元或集成)是编程中非常重要的一部分。在当今的软件开发中,单元/功能测试已经成为软件开发不可或缺的一部分。随着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;index
