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

'there can only be one only test' conflicts with 'before' test #463

Open
ghost opened this issue Mar 10, 2019 · 9 comments
Open

'there can only be one only test' conflicts with 'before' test #463

ghost opened this issue Mar 10, 2019 · 9 comments

Comments

@ghost
Copy link

ghost commented Mar 10, 2019

I'm looking for a solution to a problem I'm having. Sometimes I need to isolate a test for a short period of time, but almost all my tests have setups like below. Commenting out all the other tests is really annoying, plus it stills runs the tests in my other files, so I need to comment all AND use a different glob pattern AND relaunch nodemon.

I'd be open to pretty much any solution, even if it involves modifying my tape node_modules since I only need this while i'm coding to improve productivity, it doesn't need to stay in the code permanently.

test('setup', async t => {
  await app.launch()
  await browser.open()
  t.end()
})

test('route: hello world', async t => {
  await browser.goTo(APP.URL)
  const pageContent = await browser.getPageContent()
  t.equal(pageContent, 'hello world')
  t.end()
})
@ljharb
Copy link
Collaborator

ljharb commented Mar 10, 2019

Instead of using test as a hacked-together before, make a setup function, and call it inside each test that needs the setup. eg:

const setup = async () => {
  await app.launch();
  await browser.open();
});

test('route: hello world', async t => {
  await setup();
  await browser.goTo(APP.URL);
  const pageContent = await browser.getPageContent();
  t.equal(pageContent, 'hello world');
  t.end();
})

@ghost
Copy link
Author

ghost commented Mar 11, 2019

yes that would work but I don't like it for 2 reasons.

  1. it's a before all setup, so calling it every time would be too slow, and checking if it was already called once doesn't seem right. What if some tests down the page need a re-setup? What if I need a slightly different set up. I'd rather avoid confusion created by that.

  2. I'm trying to keep each individual test as small and clean as possible. I already extract setups and asserts relevant to specific tests inside reusable functions. I'd rather keep my before all setup before all tests, because then the code is self explanatory.

@ljharb
Copy link
Collaborator

ljharb commented Mar 11, 2019

Considering that there's not an official "before" feature in tape, I'm not sure how to handle it.

Certainly, though, you could make the setup function memoized - so that it's safe to call it multiple times.

@ghost
Copy link
Author

ghost commented Mar 11, 2019

I've actually solved my problem using this

const test = require('tape')

const tests = []

const group = (description, test) => {
  tests.push({description, test})
  return group
}

group.run = (...args) => {
  if (args.length) {
    group(...args)
  }

  test.only('grouped tests', async t => {
    const endTest = t.end
    t.end = () => {}

    for (const _test of tests) {
      t.comment(_test.description)
      await _test.test(t)
    }

    endTest()
  })
}

test.group = group

then in your test file

const test = require('tape')
require('test/group')

test.group('some test', t => {})
test('some test', t => {})
test.group('some test', t => {})
test('some test', t => {})
test.group.run('some test', t => {})
test('some test', t => {})
test('some test', t => {})

It's not pretty but it's already saving me some time. Would be cool if there was a way to not have to call "run" on the last test

@ljharb
Copy link
Collaborator

ljharb commented Mar 11, 2019

I suppose you could do something gnarly like listen for the process exiting, and start the tests then.

@ghost
Copy link
Author

ghost commented Mar 11, 2019

I suppose you could do something gnarly like listen for the process exiting, and start the tests then.

Do you know how? I tried this but it doesn't register the test.only in group.run before the other tests already ran

const test = require('tape')

const tests = []
let ran

const group = (description, test) => {
  tests.push({description, test})
  return group
}

group.run = (...args) => {
  if (ran) {
    return
  }
  ran = true
  if (args.length) {
    group(...args)
  }

  test.only('grouped tests', async t => {
    const endTest = t.end
    t.end = () => {}

    for (const _test of tests) {
      t.comment(_test.description)
      await _test.test(t)
    }

    endTest()
  })
}
test.group = group

const run = () => {
  group.run()
}

process.on('beforeExit', run)

test('test one', t => {
  t.pass()
  t.end()
})

test.group('test two', t => {
  t.pass()
  t.end()
})

test('test three', t => {
  t.pass()
  t.end()
})

@ljharb
Copy link
Collaborator

ljharb commented Mar 11, 2019

I'm not really sure as I haven't thought this through.

Personally, even in test frameworks that have a beforeAll feature, I never ever use it - i'd prefer to set up and destroy my database for every single test, no matter how slow that made the suite, rather than risk a single test falsely passing based on data pollution from a previous test.

@ghost
Copy link
Author

ghost commented Mar 11, 2019

I'm not really sure as I haven't thought this through.

Personally, even in test frameworks that have a beforeAll feature, I never ever use it - i'd prefer to set up and destroy my database for every single test, no matter how slow that made the suite, rather than risk a single test falsely passing based on data pollution from a previous test.

I do the same for databases because they open pretty quick and you need a clean slate. But right now I'm testing an express app and need to open the browser, which takes too long, and need to launch the express app, which even if it's quick, it's tons of useless code repetition. My tests are small and I have many of them. it would make 5-10% of the entire file useless code repetition.

@markanderstam

This comment has been minimized.

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

No branches or pull requests

2 participants