Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

before/beforeEach/after/afterEach #59

Closed
thom4parisot opened this issue Jan 20, 2014 · 15 comments
Closed

before/beforeEach/after/afterEach #59

thom4parisot opened this issue Jan 20, 2014 · 15 comments

Comments

@thom4parisot
Copy link

Hello :-)

I'm considering using tape for a project requiring IE8 testing, in order to replace chai/mocha.

Is there any way to achieve doing before/beforeEach/after/afterEach to setup fixtures and stubs before running assertions?

Thanks very much :-)

@Raynos
Copy link
Collaborator

Raynos commented Jan 20, 2014

var test = require("tape")

var before = test
var after = test

var test = beforeEach(test, function before(assert) {
    // called before each thing

    // when done call
    assert.end()
})
test = afterEach(test, function after(assert) {
    // called after each thing

    // when done call
    assert.end()
})

before("before all tests", function (assert) {
    // before logic

    // when done call
    assert.end()
})

test("name of test", function (assert) {
    // before logic & beforeEach has run

    // when done with test call
    assert.end()
    // afterEach logic will run
})

after("after all tests", function (assert) {
    // after logic

    // when done call
    assert.end()
})

function beforeEach(test, handler) {
    return function tapish(name, listener) {
        test(name, function (assert) {
            var _end = assert.end
            assert.end = function () {
                assert.end = _end
                listener(assert)
            }

            handler(assert)
        })
    }
}
function afterEach(test, handler) {
    return function tapish(name, listener) {
        test(name, function (assert) {
            var _end = assert.end
            assert.end = function () {
                assert.end = _end
                handler(assert)
            }

            listener(assert)
        })
    }
}

We should put afterEach and beforeEach in a module like tape-before-after

@ghost
Copy link

ghost commented Jan 21, 2014

For before()/after() you can just use ordinary tests to do setup and teardown:

var test = require('tape');

test('setup', function (t) {
    // setup goes here, call t.end() when finished
});

// your other tests go here...

test('teardown', function (t) {
    // teardown goes here, call t.end() when finished
});

to perform some setup around each test, you can just write a function inline that takes a callback.

@ghost ghost closed this as completed Jan 21, 2014
@thom4parisot
Copy link
Author

Thanks guys for this very quick follow up. I'll give a try this way.

🍰

@nstepien
Copy link

@substack
What do you mean exactly by "write a function inline that takes a callback"?

I'm having trouble setting up asynchronous beforeEach/afterEach.

edit: nvm figured it out

@soundyogi
Copy link

@MayhemYDG
could you post your solution? thx

@knownasilya
Copy link

For others that are interested, there is a package called redtape that extends tape to give you beforeEach and afterEach functionality.

@braddunbar
Copy link
Contributor

For before()/after() you can just use ordinary tests to do setup and teardown:

So simple… :heart:

@shri3k
Copy link

shri3k commented Aug 12, 2015

@Raynos I just wanna say that, that is some clever piece of code there. My mind was figuratively blown when I finally understood what was going on. 👏

@tomek-he-him
Copy link

@oncletom @Raynos @sinkingshriek you can also listen to the end event on assert. Benefit: it also works with assert.plan.

@kuraga
Copy link
Contributor

kuraga commented Dec 24, 2015

Any ideas about merging this functionality? From tapes, for instance...

@alathon
Copy link

alathon commented Oct 11, 2016

Also ran into this. Thanks for the excellent idea @Raynos. I'm still not 100% satisfied with this, as it prevents accessing the Test object to set eg. tape.onFinished(), so that has to be done before you ever call beforeEach (afaik?), f.ex.

I ended up re-implementing it slightly, so that the beforeEach/afterEach methods can take either a function, or an array of functions, as follows (beware, ES6):

export const beforeEach = (_test, handlers) => {
  if (typeof handlers === 'function') return _beforeEach(_test, handlers)

  return handlers.reduce((prev, cur, curIdx, arr) => {
    if (curIdx === 0) return prev
    return _beforeEach(prev, cur)
  }, _beforeEach(_test, handlers[0]))
}

export const afterEach = (_test, handlers) => {
  if (typeof handlers === 'function') return _afterEach(_test, handlers)

  return handlers.reduce((prev, cur, curIdx, arr) => {
    if (curIdx === 0) return prev
    return _afterEach(prev, cur)
  }, _afterEach(_test, handlers[0]))
}

const _beforeEach = (_test, handler) => {
  return function tapish (name, listener) {
    _test(name, function (assert) {
      let _end = assert.end

      assert.end = function () {
        assert.end = _end
        listener(assert)
      }

      handler(assert)
    })
  }
}

const _afterEach = (_test, handler) => {
  return function tapish (name, listener) {
    _test(name, function (assert) {
      let _end = assert.end

      assert.end = function () {
        assert.end = _end
        handler(assert)
      }

      listener(assert)
    })
  }
}

Use is f.ex:

import tapeLib from 'tape'
import { beforeEach, someMethodA, someMethodB, someMethodC } from './helpers/hooks'

let tape = beforeEach(tapeLib, dropTables) // dropTables will run before each test.
tape = beforeEach(tape, [someMethodB, someMethodC]) // dropTables -> someMethodB -> someMethodC will run before each test

This allows you to separate the functionality into smaller methods that each do a certain thing, such as resetting your DB, or whatever else you need to do before tests.

@Raynos
Copy link
Collaborator

Raynos commented Oct 11, 2016

@alathon I've since written tape-cluster ( https://github.com/Raynos/tape-cluster ).

This allows you to build a generic class for your test suite, useful if your testing an app and want to setup & teardown the app before every test.

Bonus feature is that MyTest.test.only(); and MyTest.test.skip() work.
Bonus feature, you can pass options into your test class so that you can different configurations before every test.

@ChopperLee2011
Copy link

@substack your code is clear, but not fit with only case, if one test case is describe with test.only, then all the setup and teardown are skiped

@JasinYip
Copy link

The above solutions looks can only be used for the whole testing. It couldn't set beforeEach/afterEach or before/after for every single file because these solutions would modify the test object which is a single instance.

@JasinYip
Copy link

JasinYip commented Jan 21, 2020

Set alias from test function for implementing before and after might work around for calling order, but it would make side effects like we will see it on the result list. That might make the report looks not the same with the test case writers' expection.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests