folio:可定制的测试框架来构建您自己的测试框架

2021-05-11 02:43:46

可自定义的测试框架来构建您自己的测试框架。 剧作家测试跑步者的基础。 Folio可在预览中获得,并在积极开发中。 打破变化可能会发生。 我们欢迎您对1.0展到的反馈。 folio侧重于测试隔离和灵活性。 这使得快速,可靠,能够适应您的特定需求。 folio默认情况下并行运行测试,使您的测试套件更快。 由于孤立,Folio重新使用多个测试,套件和文件的过程,这使得它更快。 可以重新检测不显着的开销,因为folio只会重试失败,而不是整个套件。 重构测试和移动它们是轻松的,因为隔离的测试没有依赖性。 定义多种测试类型,例如慢速测试或烟雾测试,并以不同的方式运行它们。

Folio遵循传统的BDD风格。但是,folio中的每个测试都接收具有测试参数的对象。这些论点与其他测试隔离,这给了作品组织众多的优势。

测试('插入条目' isync({table})=> {await表。插入({username:' folio'密码:'测试' }); const条目=等待表。查询({username:' folio'});期望(条目。密码)。Tobe('测试');});

在上面的测试中,表是为每个测试创建的数据库表,所以在并行运行的多个测试中运行' t彼此跳跃'脚趾。

// folio.config.ts导入*从' folio' ; //配置folio查看此目录中的测试,并为每个测试提供20秒。对开。 setconfig({testdir:__dirname,超时:20000}); //创建测试类型。对于最简单的设置,您可以使用默认设置。出口const test = folio。测试 ; //使用两个重试运行测试。测试 。 runwith({tag:' basic'重试:2});

// math.spec.ts导入{test} from' ./ folio.config' ;测试('检查加法',()=> {test。期望(1 + 1)。TOBE(42);});

通常,您需要一些测试环境来运行测试。这可以是测试数据库,DEV服务器,模拟用户数据或其他测试需求的其他功能。 folio支持创建要用于多个测试的环境。

让' s请参阅如何基于【示例添加配置文件部分添加环境。

// folio.config.ts导入*从' folio' ;对开。 setconfig({testdir:__dirname,超时:20000}); class databaseenv {database:数据库;表:数据数据; async beforeall(){//连接到数据库一次,它很昂贵。这 。数据库= await connecttotestdatabase(); } async presseach(){//为每个测试创建一个新表并返回它。这 。表=等待这一点。数据库。 createTable(); //从此方法返回的任何内容都可供测试。在我们的情况下,"表"返回{表:此。桌子 } ; } Async juildeA(){//不要留下额外的表格。等待这个。桌子 。降低 ( ) ; } Async wherlall(){等待这一点。数据库。 disconnect(); }} //我们的测试类型附带了数据库环境,因此每个测试都可以使用A"表"争论。出口const test = folio。测试 。扩展(新的Databaseenv()); //运行我们的测试。测试 。 runwith({tag:'数据库'});

在此示例中,我们看到测试使用为测试提供参数的环境。

folio使用工作进程来运行测试文件。您可以使用--workers命令行选项指定最大工人数。通过使用BeforeAll和WhileAll方法,环境可以设置昂贵的资源,以在每个工作进程中的测试之间共享。如果其环境匹配,Folio将为尽可能多的测试文件重用工人流程。

不幸的是,测试并不总是通过。 folio支持测试注释,以处理尚未准备好的故障,片状和测试。

测试('基本' async({table})=> {test。跳过(版本==' v2''此测试崩溃在v2中的数据库,更好没有运行它。'); //测试到了这里。});测试('可以插入多行',异步({表})=> {test。失败('破碎的测试,但我们应该修复它!'); //测试走到这里。});

注释可以是有条件的,在这种情况下,它们仅在条件是真实时适用。注释可能取决于测试参数。在同一测试中可能有多个注释,可能是不同的配置。

跳过标记为无关紧要的测试。 folio没有运行这种测试。使用此注释在某些配置中不适用于测试时。

失败将测试标记为失败。 folio将运行此测试并确保确实失败。如果测试没有失败,那么Folio将抱怨。

FIXME将测试标记为失败。 folio不会运行此测试,与故障注释相反。运行测试时使用FIXME是慢或崩溃的。

Folio涉及翻转的片状测试。在运行测试时传递最大重试次数,或在配置文件中设置它们。

失败的测试将多次重试,直到它们通过,或直到达到最大重试次数。 folio将报告至少一次失败的测试:

传递给NPX folio的参数被视为测试文件的过滤器。例如,NPX Folio My-Spec将仅在名称中使用My-spec运行测试。

- 仅限INETBID:是否禁止测试.ONLY独家测试。对CI有用。从配置文件中覆盖config.forbidonly选项。

- Global-timeout< number&gt ;:整个测试运行的总超时以毫秒为单位。默认情况下,没有全局超时。从配置文件中覆盖config.globaltimeout选项。

--grep< grep>或-g< grep&gt ;:才能运行与此正则表达式匹配的测试,例如/my.*test/i或我的测试。从配置文件中覆盖config.grep选项。

--max-failures< n>或-x:在第一个n测试失败后停止。首次发生故障后通过-X停止。从配置文件中覆盖Config.MaxFailures选项。

--output< dir&gt ;:用于测试生成的工件的目录,默认为测试结果。从配置文件中覆盖Config.Outputir选项。

--quiet:是否从测试中抑制stdout和stderr。覆盖配置文件中的Config.quiet选项。

- 每个< number&gt ;:指定运行每个测试的次数。默认为一个。从配置文件中覆盖config.repeateach选项。

- 箴言<记者&gt ;.指定要使用的报告员逗号分隔,可以是点,json,jun,行,列表和null的某种组合。有关更多信息,请参阅记者。

--RETRIES< number&gt ;:每个胶囊测试的最大重试次数,默认为零(无重试)。从配置文件中覆盖CONFIG.RETRIES选项。

--Shard< shard&gt ;:碎片测试并仅执行选定的碎片,在表单/全部,基于,例如3/5中指定。从配置文件中覆盖config.shard选项。

--snapshot-dir< dir&gt ;: snapshots目录,相对于测试目录。默认为__snapshots__。从配置文件中覆盖Config.snapshotdir选项。

--tag<标签...&gt ;:才运行标有一个指定标记的测试。默认为运行配置文件中定义的所有可用标记。

--test-dir< dir&gt ;: folio应该搜索测试的目录,默认为当前目录。只有匹配的文件--test-match被识别为测试文件。从配置文件中覆盖config.testdir选项。

--test-Ignore<模式&gt ;:用于忽略测试文件的模式,默认为node_modules。定期表达式(例如,/ node_modules /)或Glob模式(例如,** / icigore-dir / *)。从配置文件中覆盖config.testignore选项。

- 最低匹配<模式>:用于查找测试文件的模式,默认为以.spec.js,.test.js,.spec.ts或.test.ts结尾的文件。定期表达式(例如,/ my-test- \ d + / i)或glob模式(例如,?(*。)+(spec |测试)。[JT] s)。从配置文件中覆盖config.testmatch选项。

- 时间< number&gt ;:每个测试的最大超时以毫秒为单位,默认为10秒。从配置文件中覆盖Config.TimeOut选项。

- update-snapshots或-u:是否使用实际结果更新快照而不是比较它们。当快照期望发生变化时,使用此功能。从配置文件中覆盖config.updatesnapshot选项。

- Workers<工人>或-j< workers&gt ;:最大的并发工作人员进程数。从配置文件中覆盖Config.workers选项。

folio包括生产和比较快照的能力。为此,使用期望()。tomatchsnapshot()。 folio自动检测内容类型,包括用于文本,PNG和JPEG图像的内置匹配器,以及任意二进制数据。

默认情况下,快照存储在__snapshots__目录下,可配置通过命令行或配置对象。

每个工人进程都会创建一个用于运行测试的新环境。不同的环境始终在不同的工人中运行。默认情况下,folio尽可能多地重用工作人员,以便更快地测试,但在重试测试后,它将创建一个新工人,以便在任何测试失败后初始化新环境,或者如果工作人员限制,则仅加快测试执行没有到达。

每个工人进程都分配了一个唯一顺序索引,可通过WorkerInfo对象访问。

Folio可以拆下测试套件,以便它可以在多台机器上执行。为此,将--Shard = x / y到命令行。例如,要将套件拆分为三个碎片,每次运行三分之一的测试:

配置文件使用SetConfig函数来为folio提供全局配置。 它可能包含以下属性: FORBIDONLY:布尔 - 是否禁止测试.OONLY独家测试。 对CI有用。 仅覆盖 - Forbid-ock命令行选项。 GlobalTimeout:Number - 整个测试运行的总超时为毫秒为单位。 覆盖 - global-timeout命令行选项。 Grep:Regexp | Regexp [] - 根据其标题过滤测试的模式。 由--grep命令行选项覆盖。 MaxFailures:数字 - 达到最大故障次数后停止测试。 由--max-fallures命令行选项覆盖。 OutputDir:String - 要放置测试生成的任何工件的目录。 由--output命令行选项覆盖。 安静:布尔 - 是否从测试中抑制stdout和stderr。 Quiet命令行选项覆盖。

重复员:号码 - 每次测试都会多次重复。 由--Repeat-ever命令行选项覆盖。 碎片:{总数:数字,当前:号码} | null - 碎片信息。 覆盖 - archard命令行选项。 SnapshotDir:String - Snapshots目录,相对于Tests目录。 覆盖--snapshot-dir命令行选项。 testdir:string - folio应该搜索测试的目录。 覆盖--test-dir命令行选项。 Testignore:String | regexp | (String | Regexp)[] - 要忽略测试文件的模式。 由--test-Ignore命令行选项覆盖。 testmatch:string | regexp | (String | Regexp)[] - 要匹配测试文件的模式。 覆盖--Test-match命令行选项。 UpdateNapshots:Boolean - 是否更新快照而不是比较它们。 覆盖 - update-snapshots命令行选项。

工人:号码 - 并发工作进程的最大数量。由--workers命令行选项覆盖。

// folio.config.ts导入*从' folio' ;对开。 setconfig({//通常,您' d place folio.config.ts在测试目录中。testdir:__dirname,//每次测试20秒。超时:20000,//禁止测试。禁止上CI。 !进程。env。CI,//每个测试的两次重试。重试:2,});

有几种方法可以改变测试超时 - 每个测试的每毫秒内的时间量。在其中任何一个中传递零超时禁用超时。

根据配置和故障,FOLIO可能会使用不同数量的工人进程来运行所有测试。例如,在故障测试后,FOLIO将始终启动新的工人流程。

环境和钩子在BeforeAll中接收WorkerInfo和浏览次数。可以从WorkerInfo访问以下信息:

考虑每个人员进程运行新的HTTP服务器的示例,并使用WorkerIndex生成唯一的端口号:

导入*作为http from' http' ; class serverenv {server:http。服务器 ; async beforeall(workerinfo){这个。 server = http。 createserver();这 。服务器 。听(9000 + WorkerInfo。WorkerIndex);等待新的承诺(就绪=>这个。服务器。曾经('聆听'准​​备好)); } Async presseach(){//将服务器作为测试参数提供。返回{服务器:此。服务器 } ; } async wherlall(){等待新的承诺(done =>这个。服务器。关闭(完成)); }}

环境和挂钩在前后拨打之前接收TestInfo。它也可用于测试功能作为第二个参数。

除了来自WorkerInfo的一切,在测试之前和期间可以访问以下信息:

预计:'通过' | '失败' | ' timedout' - 是否预计此测试将通过,失败或超时。

数据:对象 - 您' d喜欢附加到测试的任何其他数据,它将出现在报告中。

SnapshotPath(...路径:String []) - 返回测试的特定快照的完整路径的函数。

OpertPath(...路径:String []) - 返回特定输出工件的完整路径的函数。

测试('我的测试需要文件',async({table},testinfo)=> {//用表格... // ......然后保存内容。const filepath = testinfo。输出路径(' table.dat');等待桌子。Saveto(Filepath);});

导入*从&#39调试;调试' ;导入*从' fs' ; class logenv {async presseach(){this。 logs = [];调试。 log =(... args)=>这 。日志。推(args。地图(字符串)。加入(''));调试。启用(' mycomponent'); } async intereach(testinfo){if(testinfo。状态!== testinfo。预期的status)fs。 writefilesync(testinfo。输出路径(' logs.txt')。日志。加入(' \ n'),' utf8'); }}

通常是需要不同类型的测试,例如使用数据库表的通用测试,或者一些需要更多详细设置的专业测试。在多种配置中运行测试也是常见的。 folio允许您通过编写代码来配置所有内容以获得最大的灵活性。

立即添加环境而不是使用test.extend(),而不是使用test.declare()来声明测试参数和test.runwith()给它实际的环境和配置。

// folio.config.ts导入*从' folio' ;导入*从' fs' ; // 20秒超时,默认为3重试。对开。 setconfig({testdir:__dirname,超时:20000,重试:3}); //环境具有一些测试值。类Mockedenv {async presseach(){return {value:'一些测试价值' }; }} //从文件中读取的另一个环境。 class fileenv {constructor(){this。 value = fs。 readfilesync(' data.txt'' utf8'); } async presseach(){return {value:this。价值 } ; }} //我们的测试需要一个常见的字符串值。 const valuetest = folio。测试 。声明< {value:string}> (); //现在声明尽可能多的测试类型和我们喜欢。 //使用两个不同的环境运行通用测试,没有特定的配置。出口const test = ValueTest。宣布 ( ) ;测试 。 runwith(new mockedenv());测试 。 runwith(new fileenv()); //在单个环境中运行缓慢的超时,在一个环境中增加超时。出口const strectest = Valesest。宣布 ( ) ;慢一点。 runwith(new mockedenv(),{timout:100000}); //在没有重试的情况下运行烟雾测试 - 这些不能是片状的。 //添加标签允许使用使用`npx folio -tag =烟雾测试运行烟雾测试。出口const smopetest = Valesest。宣布 ( ) ; Spoxest。 runwith(new mockedenv(),{重试:0,标签:'烟雾'}); //这些测试也得到了一个" foo"争论。导出const sitect = valuetest。扩展({presseach(){return {foo:42};}}); //虽然我们已经添加了给出的环境" foo"我们仍然必须提供//#34;价值"宣布为valeestest。最镜头。 runwith(new mockedenv(),{tag:' foo'});

//某些.spec.ts导入{test,slowtest,spostest,octest} from' ./ folio.config' ;测试('只是一个测试',异步({value})=> {//将重试该测试。期望(value)。tobe('错误的值');} );慢动站('做很多',async({value})=> {for(让我= 0; i< 100000; i ++)期望('一些测试价值');}); Smoketest('烟雾测试' async({value})=> {//将无法重试。期望(value)。tobe('一些测试值') ;});最镜头('烟雾测试',异步({foo})=> {//注意不同的测试参数。期望(foo)。TOBE(42);});

要在运行所有测试之前设置何种内容,请使用配置文件中的GlobalSetup挂钩。同样,使用GlobalTeardown在所有测试后运行一次。

// folio.config.ts导入*从' folio' ;导入*作为应用程序来自' ../ my-app' ;导入*作为http from' http' ;让服务器:HTTP。服务器 ;对开。 globalsetup(async()=> {server = http。createRver(App);等待新的承诺(DONE =>服务器。侦听(完成));进程。env。server_port = string(服务器。地址()。端口) ; //将端口暴露在测试中。});对开。 GlobalTeardown(Async()=> {等待新的承诺(DONE =>服务器。关闭(完成));});对开。 setconfig({testdir:__dirname});出口const test = folio。 newtesttype();测试 。 runwith();

根据各种测试需求,测试环境是可配置的。 根据Usecase,有三种不同的方法可以在Folio中配置环境。 在需要以多种配置运行测试时,请使用此方法。 有关更多详细信息,请参阅多种测试类型和配置。 // folio.config.ts导入*从' folio' ; 对开。 setconfig({testdir:__dirname}); //此环境提供A"您好" class helloenv {constructor(name){this。 name = name; } async prefeach(){return {hello:`hello,$ {the。 名称}!`}; } //测试期待A"你好" 价值。 出口const test = folio。 测试 。 声明< {hello:string}> (); //现在,以两种配置运行测试。 测试 。 runwith(新的helloenv('世界')); 测试 。 runwith(new helloenv(' test')); // folio.config.ts导入*从&#39的folio; ......