Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

🤖 Repeat tests. Repeat tests. Repeat tests.

License

NotificationsYou must be signed in to change notification settings

ehmicky/test-each

Repository files navigation

test-each logo

NodeBrowsersTypeScriptCodecovMinified sizeMastodonMedium

🤖 Repeat tests. Repeat tests. Repeat tests.

Repeats tests using different inputs(Data-Driven Testing):

Hire me

Pleasereach outif you're looking for a Node.js API or CLI engineer (11 years of experience).Most recently I have beenNetlify Build'sandNetlify Plugins'technical lead for 2.5 years. I am available for full-time remote positions.

Example

// The examples use Ava but any test runner works (Jest, Mocha, Jasmine, etc.)importtestfrom'ava'importmultiplyfrom'./multiply.js'import{each}from'test-each'// The code we are testing// Repeat test using different inputs and expected outputseach([{first:2,second:2,output:4},{first:3,second:3,output:9},],({ title},{ first, second, output})=>{// Test titles will be://    should multiply | {"first": 2, "second": 2, "output": 4}//    should multiply | {"first": 3, "second": 3, "output": 9}test(`should multiply |${title}`,(t)=>{t.is(multiply(first,second),output)})},)// Snapshot testing. The `output` is automatically set on the first run,// then re-used in the next runs.each([{first:2,second:2},{first:3,second:3},],({ title},{ first, second})=>{test(`should multiply outputs |${title}`,(t)=>{t.snapshot(multiply(first,second))})},)// Cartesian product.// Run this test 4 times using every possible combination of inputseach([0.5,10],[2.5,5],({ title},first,second)=>{test(`should mix integers and floats |${title}`,(t)=>{t.is(typeofmultiply(first,second),'number')})})// Fuzz testing. Run this test 1000 times using different numbers.each(1000,Math.random,({ title},index,randomNumber)=>{test(`should correctly multiply floats |${title}`,(t)=>{t.is(multiply(randomNumber,1),randomNumber)})})

Install

npm install -D test-each

This package works in both Node.js >=18.18.0 andbrowsers.

This is an ES module. It must be loaded usinganimport orimport() statement,notrequire(). If TypeScript is used, it must be configured tooutput ES modules,not CommonJS.

Usage

import{each}from'test-each'constinputs=[['red','blue'],[0,5,50],]each(...inputs,(info,color,number)=>{})

Firescallback once for each possible combination ofinputs.

Eachinput can be anarray, afunction or aninteger.

A common use case forcallback is to define tests (using any test runner).

info is anobject whose properties can be used to generatetest titles.

Test titles

Each combination of parameters is stringified as atitle available in thecallback'sfirst argument.

Titles should be included in test titles to make them descriptive and unique.

Long titles are truncated. An incrementing counter is appended to duplicates.

Any JavaScript type isstringified,not just JSON.

You can customize titles either by:

import{each}from'test-each'each([{color:'red'},{color:'blue'}],({ title},param)=>{// Test titles will be://    should test color | {"color": "red"}//    should test color | {"color": "blue"}test(`should test color |${title}`,()=>{})})// Plain objects can override this using a `title` propertyeach([{color:'red',title:'Red'},{color:'blue',title:'Blue'},],({ title},param)=>{// Test titles will be://    should test color | Red//    should test color | Bluetest(`should test color |${title}`,()=>{})},)// The `info` argument can be used for dynamic titleseach([{color:'red'},{color:'blue'}],(info,param)=>{// Test titles will be://    should test color | 0 red//    should test color | 1 bluetest(`should test color |${info.index}${param.color}`,()=>{})})

Cartesian product

If severalinputs are specified, theircartesian product is used.

import{each}from'test-each'// Run callback five times: a -> b -> c -> d -> eeach(['a','b','c','d','e'],(info,param)=>{})// Run callback six times: a c -> a d -> a e -> b c -> b d -> b eeach(['a','b'],['c','d','e'],(info,param,otherParam)=>{})// Nested arrays are not iterated.// Run callback only twice: ['a', 'b'] -> ['c', 'd', 'e']each([['a','b'],['c','d','e'],],(info,param)=>{},)

Input functions

If afunction is used instead of an array, each iteration fires it and usesits return value instead. Thefunction is called with thesame argumentsas thecallback.

The generated values are included intest titles.

import{each}from'test-each'// Run callback with a different random number each timeeach(['red','green','blue'],Math.random,(info,color,randomNumber)=>{})// Input functions are called with the same arguments as the callbackeach(['02','15','30'],['January','February','March'],['1980','1981'],(info,day,month,year)=>`${day}/${month}/${year}`,(info,day,month,year,date)=>{},)

Fuzz testing

Integers can be used instead of arrays to multiply the number of iterations.

This enablesfuzz testing when combinedwithinput functions and libraries likefaker.js,chance.js orjson-schema-faker.

importfakerfrom'faker'// Run callback 1000 times with a random UUID and color each timeeach(1000,faker.random.uuid,faker.random.arrayElement(['green','red','blue']),(info,randomUuid,randomColor)=>{},)// `info.index` can be used as a seed for reproducible randomness.// The following series of 1000 UUIDs will remain the same across executions.each(1000,({ index})=>faker.seed(index)&&faker.random.uuid(),(info,randomUuid)=>{},)

Snapshot testing

This library works well withsnapshot testing.

Any library can be used(snap-shot-it,Ava snapshots,Jest snapshots,Node TAP snapshots, etc.).

import{each}from'test-each'// The `output` is automatically set on the first run,// then re-used in the next runs.each([{first:2,second:2},{first:3,second:3},],({ title},{ first, second})=>{test(`should multiply outputs |${title}`,(t)=>{t.snapshot(multiply(first,second))})},)

Side effects

Ifcallback'sparameters are directly modified, they should becopied to prevent side effects for the next iterations.

import{each}from'test-each'each(['green','red','blue'],[{active:true},{active:false}],(info,color,param)=>{// This should not be done, as the objects are re-used in several iterationsparam.active=false// But this is safe since it's a copyconstnewParam={ ...param}newParam.active=false},)

Iterables

iterable() can be used to iterate over each combinationinstead of providing a callback.

import{iterable}from'test-each'constcombinations=iterable(['green','red','blue'],[{active:true},{active:false}],)for(const[{ title},color,param]ofcombinations){test(`should test color |${title}`,()=>{})}

The return value is anIterable.This can be converted to an array with the spread operator.

constarray=[...combinations]array.forEach(([{ title},color,param])=>{test(`should test color |${title}`,()=>{})})

API

each(...inputs, callback)

inputs:Array | function | integer (one orseveral)
callback:(info, ...params) => void

Firescallback with each combination ofparams.

iterable(...inputs)

inputs:Array | function | integer (one orseveral)
Return value:Iterable<[info, ...params]>

Returns anIterablelooping through each combination ofparams.

info

Type:object

info.title

Type:string

Likeparams but stringified. Should be used intest titles.

info.titles

Type:string[]

Likeinfo.title but for eachparam.

info.index

Type:integer

Incremented on each iteration. Starts at0.

info.indexes

Type:integer[]

Index of eachparams inside each initialinput.

params

Type:any (one orseveral)

Combination of inputs for the current iteration.

Support

For any question,don't hesitate tosubmit an issue on GitHub.

Everyone is welcome regardless of personal background. We enforce aCode of conduct in order to promote a positive andinclusive environment.

Contributing

This project was made with ❤️. The simplest way to give back is by starring andsharing it online.

If the documentation is unclear or has a typo, please click on the page'sEditbutton (pencil icon) and suggest a correction.

If you would like to help us fix a bug or add a new feature, please check ourguidelines. Pull requests are welcome!


[8]ページ先頭

©2009-2025 Movatter.jp