From e1a8911d557b987d10a5b06736bb8d1e68ee559a Mon Sep 17 00:00:00 2001 From: Jonatan Nilsson Date: Wed, 1 Apr 2020 17:16:46 +0000 Subject: [PATCH] Add skip/only/timeout on entire describe level --- README.md | 39 +++++++++-- lib/eltro.mjs | 40 ++++++----- package.json | 2 +- test/eltro.test.mjs | 159 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 217 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 0dfa956..f967a37 100644 --- a/README.md +++ b/README.md @@ -155,11 +155,20 @@ will output: √ #someFunction() should always return true ``` -### t.test(...).only() +### t.only() Eltro supports exclusivity when running tests. When specified, only tests marked with only will be run. -You can do exclusivity on tests by adding `.only()` after or before the test like so: +You can do exclusivity on tests by adding `.only()` in front of describe, after or before the test like so: + +```node +t.only().describe('Only these will run', function() { + t.test('this one', function() { assert.strictEqual(true, true) }) + t.test('and this one', function() { assert.strictEqual(true, true) }) +}) +``` + +You can also put it on individual test like so ```node t.test('Only run this test', function() { @@ -175,9 +184,18 @@ t.only().test('Only run this test', function() { }) ``` -### t.test(...).skip() +### t.skip() -You can skip tests easily by adding `.skip()` before or after the test like so: +You can skip tests easily by adding `.skip()` before describe, before or after the test like so: + +```node +t.skip().describe('None of these will run', function() { + t.test('not this', function() { assert.strictEqual(true, true) }) + t.test('or this one', function() { assert.strictEqual(true, true) }) +}) +``` + +You can also do it on individual tests like so: ```node t.test('Skip due to something being broken', function() { @@ -191,9 +209,18 @@ or like so: t.skip().test('Skip this', function() { ... }) ``` -### t.test(...).timeout(dur) +### t.timeout(dur) -Tests can take a long time. By default, eltro will cancel a test if it takes longer than 2 seconds. You can however override this by calling the timeout function after or before the test with the specified duration in milliseconds like so: +Tests can take a long time. By default, eltro will cancel a test if it takes longer than 2 seconds. You can however override this by calling the timeout function after or before the test or before the describe with the specified duration in milliseconds like so: + +```node +t.timeout(5000).describe('These will all have same timeout', function() { + t.test('One slow function', async function() { ... }) + t.test('Another slow function', async function() { ... }) +}) +``` + +Or apply to individual test like so: ```node t.test('This is a really long test', async function() { diff --git a/lib/eltro.mjs b/lib/eltro.mjs index 53ba0a8..1c728e9 100644 --- a/lib/eltro.mjs +++ b/lib/eltro.mjs @@ -36,6 +36,7 @@ function Eltro() { this.Eltro = Eltro this.groups = new Map() this.groupsFlat = [] + this.activeGroup = null this.tests = [] this.failedTests = [] this.hasTests = false @@ -47,6 +48,11 @@ function Eltro() { skip: false, only: false } + this.describeTemporary = { + timeout: 0, + skip: false, + only: false + } } Eltro.prototype.begin = function() { @@ -246,27 +252,27 @@ Eltro.prototype.resetFilename = function() { Eltro.prototype.describe = function(name, func) { let before = this.prefix + + // Store and set the temporary test values for entire group + let beforeCurrent = this.describeTemporary + this.describeTemporary = { + timeout: this.temporary.timeout || beforeCurrent.timeout, + skip: this.temporary.skip || beforeCurrent.skip, + only: this.temporary.only || beforeCurrent.only, + } + this.temporary.timeout = 0 + this.temporary.skip = this.temporary.only = false + if (before) { this.prefix = before + ' ' + name } else { this.prefix = name } func() + this.describeTemporary = beforeCurrent this.prefix = before } -/*Test.prototype.timeout = function(time) { - this.customTimeout = time -} - -Test.prototype.skip = function() { - this.skipTest = true -} - -Test.prototype.only = function() { - this.e.hasExclusive = this.group.hasExclusive = this.isExclusive = true -}*/ - Eltro.prototype.timeout = function(time) { this.temporary.timeout = time return this @@ -301,16 +307,18 @@ Eltro.prototype.test = function(name, func) { let test = new Test(this, group, targetName, func) group.tests.push(test) - if (this.temporary.only) { + if ((this.temporary.only || this.describeTemporary.only) && !this.temporary.skip && !this.describeTemporary.skip) { test.only() this.temporary.only = false + } else if (this.temporary.only) { + this.temporary.only = false } - if (this.temporary.skip) { + if (this.temporary.skip || this.describeTemporary.skip) { test.skip() this.temporary.skip = false } - if (this.temporary.timeout) { - test.timeout(this.temporary.timeout) + if (this.temporary.timeout || this.describeTemporary.timeout) { + test.timeout(this.temporary.timeout || this.describeTemporary.timeout) this.temporary.timeout = 0 } return test diff --git a/package.json b/package.json index 246b4d3..c0b631d 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Eltro is a tiny no-dependancy test framework for node", "main": "index.mjs", "scripts": { - "test": "node cli.mjs test/**/*.test.mjs" + "test": "node cli.mjs test/**/*.test.mjs -r dot" }, "repository": { "type": "git", diff --git a/test/eltro.test.mjs b/test/eltro.test.mjs index 97d90fa..9067876 100644 --- a/test/eltro.test.mjs +++ b/test/eltro.test.mjs @@ -230,6 +230,165 @@ e.test('Eltro should support only tests in front of the test', async function() assert.strictEqual(assertIsTrue, true) }) +e.test('Eltro should support timed out describes', async function() { + testsWereRun = true + const t = CreateT() + t.begin() + t.timeout(10).describe('', function() { + t.test('', function(cb) { setTimeout(cb, 25) }) + t.test('', function(cb) { setTimeout(cb, 25) }) + }) + t.describe('', function() { + t.test('', function(cb) { setTimeout(cb, 25) }) + }) + t.test('', function(cb) { setTimeout(cb, 25) }) + await t.run() + assert.strictEqual(t.failedTests.length, 2) + assert.ok(t.failedTests[0].error) + assert.match(t.failedTests[0].error.message, /10ms/) + assert.ok(t.failedTests[1].error) + assert.match(t.failedTests[1].error.message, /10ms/) +}) + +e.test('Eltro should support skipped tests in describe', async function() { + testsWereRun = true + let assertRan = 0 + const t = CreateT() + t.begin() + t.skip().describe('', function() { + t.test('', function() { throw new Error('Should not be called') }) + t.test('', function() { throw new Error('Should not be called') }) + t.test('', function() { throw new Error('Should not be called') }) + }) + t.describe('', function() { + t.test('', function() { assertRan++ }) + }) + t.test('', function() { assertRan++ }) + await t.run() + assert.strictEqual(t.failedTests.length, 0) + assert.strictEqual(assertRan, 2) +}) + +e.test('Eltro should have skip at higher importance than only', async function() { + testsWereRun = true + let assertRan = 0 + const t = CreateT() + t.begin() + t.skip().describe('', function() { + t.only().test('', function() { throw new Error('Should not be called') }) + t.only().test('', function() { throw new Error('Should not be called') }) + t.only().test('', function() { throw new Error('Should not be called') }) + }) + t.describe('', function() { + t.test('', function() { assertRan++ }) + }) + t.test('', function() { assertRan++ }) + await t.run() + assert.strictEqual(t.failedTests.length, 0) + assert.strictEqual(assertRan, 2) +}) + +e.test('Eltro should support nested skip in describe commands', async function() { + testsWereRun = true + let assertRan = 0 + const t = CreateT() + t.begin() + t.skip().describe('', function() { + t.describe('', function() { + t.only().test('', function() { throw new Error('Should not be called') }) + t.only().test('', function() { throw new Error('Should not be called') }) + t.only().test('', function() { throw new Error('Should not be called') }) + }) + }) + t.describe('', function() { + t.test('', function() { assertRan++ }) + }) + t.test('', function() { assertRan++ }) + await t.run() + assert.strictEqual(t.failedTests.length, 0) + assert.strictEqual(assertRan, 2) +}) + +e.test('Eltro should support only tests in front of the test', async function() { + testsWereRun = true + let assertRan = 0 + const t = CreateT() + t.begin() + t.only().describe('', function() { + t.test('', function() { assertRan++ }) + t.test('', function() { assertRan++ }) + }) + t.describe('', function() { + t.test('a', function() { throw new Error('Should not be called') }) + }) + t.test('c', function() { throw new Error('Should not be called') }) + await t.run() + assert.strictEqual(t.failedTests.length, 0, 'failed tests should be 0 but was ' + t.failedTests.length) + assert.strictEqual(assertRan, 2) +}) + +e.test('Eltro should support nexted only tests in front of the test', async function() { + testsWereRun = true + let assertRan = 0 + const t = CreateT() + t.begin() + t.only().describe('', function() { + t.describe('', function() { + t.test('', function() { assertRan++ }) + t.test('', function() { assertRan++ }) + }) + }) + t.describe('', function() { + t.test('a', function() { throw new Error('Should not be called') }) + }) + t.test('c', function() { throw new Error('Should not be called') }) + await t.run() + assert.strictEqual(t.failedTests.length, 0, 'failed tests should be 0 but was ' + t.failedTests.length) + assert.strictEqual(assertRan, 2) +}) + +e.test('Eltro should support nested timed out describes', async function() { + testsWereRun = true + const t = CreateT() + t.begin() + t.timeout(10).describe('', function() { + t.describe('', function() { + t.test('', function(cb) { setTimeout(cb, 25) }) + t.test('', function(cb) { setTimeout(cb, 25) }) + }) + }) + t.describe('', function() { + t.test('', function(cb) { setTimeout(cb, 25) }) + }) + t.test('', function(cb) { setTimeout(cb, 25) }) + await t.run() + assert.strictEqual(t.failedTests.length, 2) + assert.ok(t.failedTests[0].error) + assert.match(t.failedTests[0].error.message, /10ms/) + assert.ok(t.failedTests[1].error) + assert.match(t.failedTests[1].error.message, /10ms/) +}) + +e.test('Eltro nested timeout should work as expected', async function() { + testsWereRun = true + const t = CreateT() + t.begin() + t.timeout(50).describe('', function() { + t.timeout(10).describe('', function() { + t.test('', function(cb) { setTimeout(cb, 25) }) + }) + t.test('', function(cb) { setTimeout(cb, 25) }) + }) + t.describe('', function() { + t.test('', function(cb) { setTimeout(cb, 25) }) + }) + t.test('', function(cb) { setTimeout(cb, 25) }) + await t.run() + assert.strictEqual(t.failedTests.length, 1) + assert.ok(t.failedTests[0].error) + assert.match(t.failedTests[0].error.message, /10ms/) +}) + // Extra testing to make sure tests were run at all process.on('exit', function(e) { try {