Mocha: ์˜ค๋ฅ˜ : ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ๊ณผ๋„ํ•˜๊ฒŒ ์ง€์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2016๋…„ 08์›” 02์ผ  ยท  84์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: mochajs/mocha

์ด:

before(done => {
    return Promise
        .all([])
        .then(() => Model.insert(...)) // Bookshelf model returning a Bluebird Promise
        .then(() => done())
        .catch(done)
})

Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both. ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์„œ ๋‚ด์šฉ :

Mocha v3.0.0 ์ด์ƒ์—์„œ Promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  done ()์„ ํ˜ธ์ถœํ•˜๋ฉด ์ผ๋ฐ˜์ ์œผ๋กœ ์‹ค์ˆ˜์ด๋ฏ€๋กœ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋ธ ํ˜ธ์ถœ์€ ์ƒˆ๋กœ ์‚ฝ์ž… ๋œ ํ•ญ๋ชฉ์˜ Promise.<Object> ๋กœ ํ•ด๊ฒฐ๋˜์ง€๋งŒ .then(() => done()) ๋ฅผ ์ƒ๋žตํ•˜๋ฉด ํ…Œ์ŠคํŠธ ์‹œ๊ฐ„์ด ์ดˆ๊ณผ๋ฉ๋‹ˆ๋‹ค.

confirmed-bug

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

async ์™€ ๊ธฐ๋Šฅ (๋ฐ”๋ฒจ) done ๋˜ํ•œ ํœด์‹.

๋ชจ๋“  84 ๋Œ“๊ธ€

async ์™€ ๊ธฐ๋Šฅ (๋ฐ”๋ฒจ) done ๋˜ํ•œ ํœด์‹.

์˜ค๋ฅ˜๊ฐ€ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด, arity๊ฐ€ 0๋ณด๋‹ค ํฐ ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•ด์„œ๋Š” ์•ˆ๋˜๋ฉฐ (์ฆ‰, done ์ฝœ๋ฐฑ์„ ์ˆ˜๋ฝ ํ•จ์„ ์˜๋ฏธ) _and_ Promise๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ return ๋ฅผ ์ƒ๋žตํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.ํ•˜์ง€๋งŒ promise๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€์‹  done ์ฝœ๋ฐฑ์„ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. :

before(() => Promise.all([]).then(() => Model.insert(...)));

๋‹ค์Œ์€ async (๋ณธ์งˆ์ ์œผ๋กœ ํ”„๋ผ ๋ฏธ์Šค)์™€ done ์˜ ๋‘ ๊ฐ€์ง€ ์˜ˆ์ž…๋‹ˆ๋‹ค.

it('fires change event when calling blah.doSomethingThatFiresChange', async function (done) {
  const blah = await getBlah()
  blah.on('change', () => done())
  blah.doSomethingThatFiresChange()
})

@elado ์ด๊ฒƒ์€ ํฅ๋ฏธ๋กœ์šด ์‚ฌ์šฉ ์‚ฌ๋ก€์ด์ง€๋งŒ mocha์˜ ๊ด€์ ์—์„œ ๋ณด๋ฉด ๋™์ผํ•œ ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค done ์ฝœ๋ฐฑ์„ ๋ฐ›๊ณ  promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์™„์ „ํžˆ ์•ฝ์† ๊ธฐ๋ฐ˜์œผ๋กœ ๋‹ค์‹œ ์ž‘์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

it('fires change event when calling blah.doSomethingThatFiresChange', async function () {
  const blah = await getBlah()
  return new Promise(resolve => {
    blah.on('change', resolve)
    blah.doSomethingThatFiresChange()
  })
})

...ํ•˜์ง€๋งŒ ๋‹น์‹ ์ด ์–ป๋Š” ๊ฒƒ์€์ด ์˜ˆ์ œ์—์„œ mocha๊ฐ€ ์•ฝ์†์ด ํ•ด๊ฒฐ๋˜๊ณ  ์ฝœ๋ฐฑ์ด ํ˜ธ์ถœ๋˜๊ธฐ๋ฅผ _both_ ๊ธฐ๋‹ค๋ฆฌ๋ฉด ๋” ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋ถˆํ–‰ํžˆ๋„ ํŠน์ • ์ฝค๋ณด๋Š” ํ…Œ์ŠคํŠธ์—์„œ ๊ฐ€์žฅ ์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š” ๋ฒ„๊ทธ์ด๋ฏ€๋กœ์ด ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์ฒ˜์Œ์— ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

... .then (() => done ())์„ ์ƒ๋žตํ•˜๋ฉด ํ…Œ์ŠคํŠธ ์‹œ๊ฐ„์ด ์ดˆ๊ณผ๋ฉ๋‹ˆ๋‹ค.

์–ด์จŒ๋“  ์ด๊ฒƒ์€ ๋ฒ„๊ทธ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

@ScottFreeCode ํ , ์˜ˆ, done ์ฝœ๋ฐฑ์œผ๋กœ ์ œ๊ณต๋˜๋Š” ํ•จ์ˆ˜์—์„œ "๊ณผ๋„ํ•˜๊ฒŒ ์ง€์ •๋จ"์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. https://github.com/mochajs/mocha/blob/4944e31ff60105815f4b314996a9861e73f6bfd2/lib/ runnable.js # L357 -L373

... ๋ฌผ๋ก  ์šฐ๋ฆฌ๋Š” ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ ๋˜ ์ž๋งˆ์ž ๊ทธ ์˜ค๋ฅ˜๋กœ ์ธํ•ด ์‹คํŒจํ•ด์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@ScottFreeCode ์—ฌ๊ธฐ์„œ ์ˆ˜์ • ์‚ฌํ•ญ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

"ํ•ด๊ฒฐ ๋˜๋Š” ๊ฑฐ๋ถ€ ์•ฝ์†์„ ๊ธฐ๋‹ค๋ฆฐ ๋‹ค์Œ '๊ณผ๋„ํ•˜๊ฒŒ ์ง€์ •๋จ'์˜ค๋ฅ˜๋กœ ๊ฑฐ๋ถ€"๋ผ๊ณ  ์ถ”์ธก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋™์ผํ•œ ํ…Œ์ŠคํŠธ์—์„œ done ์™€ promise๋ฅผ ์˜ค๋ฅ˜๋กœ ๊ฐ„์ฃผํ•œ๋‹ค๋ฉด done ๋ฅผ๋ฐ›์€ ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜๊ฐ€ ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ž๋งˆ์ž ์˜ค๋ฅ˜๋ฅผ ๊ฐ์ง€ํ•˜์ง€ ๋ชปํ•  ์ด์œ ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. @papandreou๊ฐ€ ์ œ์•ˆ done ํ•จ๊ป˜ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š” ํ•œ ์–ด๋–ค ๋‹ค๋ฅธ ํฌ์ธํŠธ๊ฐ€ ์˜ค๋ฅ˜๋ฅผ ์œ ๋ฐœํ•ด์•ผํ•˜๋Š”์ง€ ์•Œ์•„๋‚ด๋Š” ๊ฒƒ์€ ๋‚˜์—๊ฒŒ ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

@ScottFreeCode ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ทธ๊ฒƒ์€

  1. ๋ฌธ์ œ ๊ฐ์ง€; Error ์ธ์Šคํ„ด์Šคํ™”ํ•˜์ง€๋งŒ done() ๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.
  2. ์•ฝ์†์ด ์ดํ–‰ ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ์‹ญ์‹œ์˜ค.
  3. Error ๊ฑฐ๋ถ€

๋ณด๋„ˆ์Šค ์งˆ๋ฌธ : ์•ฝ์† ์ดํ–‰์˜ ๊ฒฐ๊ณผ๋กœ ๋ฌด์—‡์„ํ•ด์•ผํ•ฉ๋‹ˆ๊นŒ?

์•„, ์•Œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์˜ค๋ฅ˜๋ฅผ ๊ฐ์ง€ํ•˜๋”๋ผ๋„ ๋‹ค์Œ ํ…Œ์ŠคํŠธ์—์„œ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š๋„๋ก ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฅผ๋ณด๊ณ  ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์•ฝ์†์„ ํ•ด๊ฒฐํ•˜๊ฑฐ๋‚˜ ๊ฑฐ๋ถ€ํ•˜์ง€ ์•Š๊ณ  ํ…Œ์ŠคํŠธ์—์„œ done ๋ฅผ ํ˜ธ์ถœ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๊นŒ? ๊ทธ๋ ‡๋‹ค๋ฉด ์šฐ๋ฆฌ๊ฐ€ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๋˜ ๋‹ค๋ฅธ ์ตœ์ข… ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค.

๋‚ด ์„ฑํ–ฅ, re. ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋กœํ•ด์•ผ ํ•  ์ผ์€ ์‹œ๊ฐ„์ด ์ดˆ๊ณผ ๋œ ๊ฒฝ์šฐ ( done ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜ ์•ฝ์†์„ ํ•ด๊ฒฐ / ๊ฑฐ๋ถ€ํ•˜์ง€ ์•Š๊ณ ) ์‹œ๊ฐ„์ด ์ดˆ๊ณผ๋˜๋ฉด ์•ฝ์†๊ณผ ํ•จ๊ป˜ done ์‚ฌ์šฉ์„๋ณด๊ณ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. (์กฐํ•ฉ์— ๋Œ€ํ•œ ํ˜ผ๋™์ด ๋‘˜ ์ค‘ ํ•˜๋‚˜์— ๋„๋‹ฌํ•˜์ง€ ๋ชปํ•˜๊ณ  ๋Œ€์‹  ์‹œ๊ฐ„์ด ์ดˆ๊ณผ ๋œ ์ด์œ  ์ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—) ๊ทธ๋Ÿฌ๋‚˜ ๋‘ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์™„๋ฃŒ๋˜๋ฉด ์•„๋งˆ๋„ ๊ฒฐ๊ณผ๊ฐ€ ์œ ํšจํ•˜๊ฑฐ๋‚˜ (๋˜๋Š” โ€‹โ€‹์ ์–ด๋„ ์˜๋ฏธ์žˆ๋Š”)๋ณด๊ณ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. done ์˜ ์ž˜๋ชป๋œ ์‚ฌ์šฉ๊ณผ ํ•จ๊ป˜ ์•ฝ์†ํ•˜๊ณ  ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๊ฐ€ ์ ์–ด๋„ ์–ด๋Š ์ •๋„ ๋„์›€์ด๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์–ด์จŒ๋“  ๊ทธ๊ฒƒ์ด ๋‚ด๊ฐ€ ์ง€๊ธˆ ์ƒ๊ฐ ํ•ด๋‚ผ ์ˆ˜์žˆ๋Š” ์ตœ์„ ์˜ ๋ฐฉ๋ฒ•์ด์ง€๋งŒ,์ด ๋ฌธ์ œ๋ฅผ ํŒŒํ—ค์น  ์‹œ๊ฐ„์„ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋” ๋งŽ์€ ํ†ต์ฐฐ๋ ฅ์„ ๊ฐ€์งˆ ์ˆ˜์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์Œ, ์šฐ๋ฆฌ๋Š” ์ด๊ฒƒ์„ ๋‹จ๊ณ„์ ์œผ๋กœ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ๋Š” Promise๊ฐ€ ๋ฐ˜ํ™˜๋˜๊ณ  done ์ฝœ๋ฐฑ์ด ์ฃผ์–ด์ง€๋ฉด Mocha๊ฐ€ ์นœ๊ทผํ•œ ๋ฐฉ์‹์œผ๋กœ ์ค‘๋‹จ๋˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์€ _ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค _ (๋ธ”๋ฃจ ๋ฒ„๋“œ ์‚ฌ์šฉ) :

// to make this work, you need to omit `return`
it('should do something async for sure', function(done) {
  return somethingAsync()
    .then(makeAssertion)
    .asCallback(done);
});

ํ•˜์ง€๋งŒ ๊ทธ๊ฒƒ์€ ๋‹น์‹ ์ด ํ•  ์ˆ˜์žˆ๋Š” ์ผ์ž…๋‹ˆ๋‹ค. ์•„์ง ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๊ฒฐ์ •ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

๋‚ด ์ž์‹ ์„ ํ˜ผ๋ž€์Šค๋Ÿฝ๊ฒŒ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ๋ฒ„๊ทธ๊ฐ€ ์žˆ๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ "๋ถˆ๋Ÿ‰ํ•œ UI"์œ ํ˜•์˜ ๋ฌธ์ œ์— ๊ฐ€๊น์Šต๋‹ˆ๋‹ค.

๋ฐ˜ํ™˜ ๋œ promise๊ฐ€ ํ•ด๊ฒฐ / ๊ฑฐ๋ถ€ ๋˜๋”๋ผ๋„ done ๊ฐ€ ํ˜ธ์ถœ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์‹œ๊ฐ„์€ ์šฐ๋ฆฌ๊ฐ€ ์ฒซ ๋ฒˆ์งธ์—์„œ done ์™€ promise๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ธˆ์ง€ํ• ์ง€ ์—ฌ๋ถ€์— ๊ด€๊ณ„์—†์ด ํ™•์‹คํžˆ ๋ฒ„๊ทธ์ž…๋‹ˆ๋‹ค. ์žฅ์†Œ. promise์™€ done ๊ฐ€ ๊ฐ™์€ ํ…Œ์ŠคํŠธ์—์„œ ๋ชจ๋‘ ์‚ฌ์šฉ ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— promise ๋ฐ / ๋˜๋Š” ์˜ค๋ฅ˜์˜ ๊ฒฐ๊ณผ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•˜์ง€๋งŒ, ๋‹ค๋ฅธ ํ•˜๋‚˜๊ฐ€ ์™„๋ฃŒํ–ˆ์„ ๋•Œ ๋‘˜ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์™„๋ฃŒ๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ํ˜„์žฌํ•˜๋Š” ์ผ์ž…๋‹ˆ๋‹ค) :

it("should not time out", function(done) {
  return new Promise(function(resolve, reject) {
    setTimeout(resolve.bind(42), 50)
  })
})

1) ์‹œ๊ฐ„ ์ดˆ๊ณผ๋˜์ง€ ์•Š์•„์•ผํ•ฉ๋‹ˆ๋‹ค.
์˜ค๋ฅ˜ : ์‹œ๊ฐ„ ์ดˆ๊ณผ 2000ms๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ํ…Œ์ŠคํŠธ์—์„œ done () ์ฝœ๋ฐฑ์ด ํ˜ธ์ถœ๋˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

์–ด์จŒ๋“  PR์„ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค ...

๊ด€์‹ฌ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค์€ # 2413์„ ๋ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๋ฟก ๋นต๋€จ

๋ฒ„์ „ 3์—์„œ ์—ฌ๋Ÿฌ ๋น„๋™๊ธฐ beforeEach ํ›„ํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ผํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

  beforeEach((cb) => connection.db.collection('users').remove({}, cb));
  beforeEach((cb) => connection.db.collection('accounts').remove({}, cb));
  beforeEach((cb) => connection.db.collection('accounts').insertOne(account1, cb));

๊ทธ๋Ÿฐ ์‹์œผ๋กœ ์—ฌ์ „ํžˆ ๋น„๋™๊ธฐ ํ›„ํฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๊นŒ?

๋‚ด ๋ฌธ์ œ๋ฅผ ์•Œ์•„ ๋ƒˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ํ›„ํฌ ๋‚ด๋ถ€์˜ ๋ฉ”์„œ๋“œ๊ฐ€ promise ๋ฐ˜ํ™˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค (์ด ๊ฒฝ์šฐ์—๋Š” promise๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์•Œ ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค). ๋ถ„๋ช…ํžˆ cb ํ•จ์ˆ˜๋„ ์ „๋‹ฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. .

๋‚˜๋Š” ์ด๊ฒƒ์ด ์ข‹์€ ์ƒ๊ฐ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฝœ๋ฐฑ์„ ์š”์ฒญํ•˜๋ฉด ์˜๋„๋ฅผ ๋ถ„๋ช…ํžˆ ํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์˜ ์˜ค๋ฅ˜๋Š” ๋‹จ์ง€ ์„ฑ๊ฐ€์‹  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์„ ์ œ๊ฑฐํ•˜์‹ญ์‹œ์˜ค.

์ด๊ฒƒ์€ ์‹ค์ œ๋กœ ์˜๋„์˜ ๋ฌธ์ œ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. # 1320์˜ ์„ค๋ช…์—์„œ :

์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ๋ชจ๋‘ ์ง€์ •๋˜๊ณ  Promise ๊ฐ์ฒด๊ฐ€
๋ฐ˜ํ™˜๋˜๋ฉด Runnable์˜ ํ•ด๊ฒฐ ์กฐ๊ฑด์ด ๋ชจํ˜ธํ•ฉ๋‹ˆ๋‹ค.

๋ชจํ˜ธํ•˜์ง€ ์•Š๊ณ  ์ฝœ๋ฐฑ์ด ์š”์ฒญ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ๋ชจํ˜ธํ•ฉ๋‹ˆ๊นŒ?

๋‚˜๋Š” @RobertWHurst ์—ฌ๊ธฐ์— ๋ชจํ˜ธํ•œ ๊ฒƒ์ด ์—†๋‹ค๋Š” ๊ฒƒ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

๊ฒŒ๋‹ค๊ฐ€์ด ๋ฌธ์ œ๋Š” "์˜๊ฒฌ ๊ธฐ๋ฐ˜"์ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ฐœ๋ฐœ์ž๋Š” ๋‹ค๋ฅธ ๊ด€์ ์„ ๊ฐ€์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ํŒŒ๊ดด์ ์ธ ๋ณ€ํ™”๋ฅผ ์ผ์œผํ‚ค๊ณ  ์‚ฌ๋žŒ๋“ค์ด ๊ทธ๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๋„๋ก ๊ฐ•์š”ํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ๊ทน๋‹จ ์ฃผ์˜์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์•„๋ฌด์—๊ฒŒ๋„ _ ๊ฐ•์š” _ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ •์˜์— ๋”ฐ๋ผ ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด์žˆ๋Š” ๋ฉ”์ด์ €๋ฅผ ์ถœ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” semver๋ฅผ ๊นจ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ทธ๊ฐ€ ๋‹น์‹ ์ด semver๋ฅผ ๊นจ๋œจ๋ ธ๋‹ค๋Š” ์˜๋ฏธ๊ฐ€ ์•„๋‹ˆ๋ผ ๋‹น์‹ ์ด Mocha๋ฅผ ๊นจ๋œจ๋ ธ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ณ€๊ฒฝ์€ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ผ์„ ๋” ์‰ฝ๊ฒŒ ๋งŒ๋“ค์ง€ ์•Š๊ณ  ์˜๊ฒฌ์„ ๊ฐ•์š”ํ•ฉ๋‹ˆ๋‹ค.

beforeEach((cb) => connection.db.collection('users').remove({}, cb));
            ^^

^^ ๋ชจํ˜ธํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ €์ž๊ฐ€ ๊ธฐ๋Œ€ํ•˜๋Š” ๋ฐ”๋Š” ๋งค์šฐ ๋ถ„๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์ž‘์„ฑ์ž๊ฐ€ ์ฝœ๋ฐฑ์„ ์š”์ฒญํ–ˆ์Šต๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ์—ฌ๊ธฐ์—์„œ ์˜ˆ์™ธ๋ฅผ ์–ป๋Š” ์ด์œ ๋Š” ์˜๊ฒฌ์„ ๊ฐ•์š”ํ•˜๋Š” ๊ฒƒ์„ ์ตœ๋Œ€ํ•œ ํšŒํ”ผํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. Mocha๋Š” ๋ฐ˜ํ™˜ ๋œ promise ๋˜๋Š” ์ฝœ๋ฐฑ์ด ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ์˜๊ฒฌ์ด ์—†์Šต๋‹ˆ๋‹ค. ๋ชจํ˜ธํ•œ ๊ฒฐ๊ณผ๋กœ ์ด์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์— ๋™์‹œ์— ๋‘˜ ๋‹ค ๊ฐ€์งˆ ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„ ์›Œํฌ์˜ ๋ชจํ˜ธํ•œ ๊ฒฐ๊ณผ๋Š” ์˜ค๋ฅ˜๋กœ ๊ฐ„์ฃผ๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋Š”์ด๋ฅผ ์ธ์‹ํ•˜๊ณ  ๊ท€ํ•˜์˜ ์˜๊ฒฌ์— ๋งž๊ฒŒ ์„ ํƒํ•˜๊ณ  ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐ ๋„์›€์ด๋ฉ๋‹ˆ๋‹ค.

๋“œ๋ผ๋งˆ์˜ ์–‘์„ ์ค„์ด๋Š” ๊ฒƒ์ด ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. "๋‹น์‹ ์€ ๋ชจ์นด๋ฅผ ๊นผ์Šต๋‹ˆ๋‹ค"๋Š” ๋ˆ„๊ตฌ์—๊ฒŒ๋„ ๋„์›€์ด๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. semver ๋ฉ”์ด์ € ๋ฒ„์ „ ์ฆ๊ฐ€๋Š” ์ฝ”๋“œ ์กฐ์ •์ด ํ•„์š”ํ•  ์ˆ˜์žˆ๋Š” ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์œผ๋กœ ๋ช…์‹œ ์ ์œผ๋กœ ์ •์˜๋ฉ๋‹ˆ๋‹ค. 2.x๋ฅผ ์œ ์ง€ํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜์ •ํ•˜๊ธฐ ์œ„ํ•ด ๋ณ€๊ฒฝํ•  ์‹œ๊ฐ„์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํŒŒ์†์ด ์•„๋‹ˆ๋ผ ์ง„ํ™”์ž…๋‹ˆ๋‹ค.

@Munter ์ฝœ๋ฐฑ ์š”์ฒญ์ด ๋ชจํ˜ธํ•œ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์—ฌ์ „ํžˆ ์†์‹ค์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝœ๋ฐฑ์„ ์š”์ฒญํ•˜๋Š” ๊ฒฝ์šฐ์ด๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ์ž์˜ ๋ช…์‹œ์ ์ธ ์กฐ์น˜์ž…๋‹ˆ๋‹ค.

๋‹น์‹ ์ด ๋“œ๋ผ๋งˆ๋ฅผ ๋Š๋ผ๊ณ  ์žˆ๋‹ค๋ฉด, ๋‚˜๋Š” ์•„๋ฌด๊ฒƒ๋„ ์˜๋ฏธํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. "๋‹น์‹ ์ด ๋ชจ์นด๋ฅผ ๊นจ๋œจ๋ ธ๋‹ค"๋Š” ๊ฒƒ์€ ๊ณผ์žฅ๋œ ์˜๋ฏธ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์ด ๋ชจ๋“ˆ์˜ ๋””์ž์ธ์— ์–ด๊ธ‹๋‚˜๊ณ  ์›๋ž˜์˜ API ๊ณ„์•ฝ์„ ๊นจ๋œจ๋ฆฐ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

babel async / await ์ „์— ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด ์ƒˆ๋กœ์šด mocha @ 3 ์—์„œ๋Š” ์ž˜ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค

it('should fill userName and password', async function (done) {
    const userNameField = global.driver.wait(until.elementLocated({css: '#username'}));
    userNameField.sendKeys('admin');

    const passNameField = global.driver.findElement({css: '#password'});
    passNameField.sendKeys('*******');

    const userNameVal = await userNameField.getAttribute('value');
    const passwordVal = await passNameField.getAttribute('value');

    try {
      assert.equal(userNameVal, 'admin');
      assert.equal(passwordVal, 'changeme');
    } catch (error) {
      done(error);
      return;
    }

    done();
  });

์ด ์ฝ”๋“œ๋Š” mocha @ 2 ์—์„œ๋Š” ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ await ์—์„œ๋Š” promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ mocha @ 3 ์—์„œ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด PR์ด ์—ฌ๊ธฐ์— ๊ด€๋ จ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค => https://github.com/mochajs/mocha/pull/2413
์ด ์˜ค๋ฅ˜์˜ ๊ฐ€์žฅ์ž๋ฆฌ ์‚ฌ๋ก€๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค.

@artyomtrityak done ๊ฐ€ ๋ถˆํ•„์š”ํ•œ ์ข‹์€ ์˜ˆ์ž…๋‹ˆ๋‹ค.

๋น„๋ฐฉํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์€ ๊ทธ๋“ค์˜ ๋ง์„ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Mocha์˜ ๋ฉ”์ธํ…Œ์ด๋„ˆ๋“ค์€์ด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋˜ ๋Œ๋ฆฌ๋Š” ์ฃผ์žฅ์— ๋™์˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Eran Hammer๋Š” "๊ด€๋ฆฌ์ž๋กœ์„œ ํ•  ์ˆ˜์žˆ๋Š” ๊ฐ€์žฅ ์–ด๋ ค์šด ์ผ ์ค‘ ํ•˜๋‚˜๋Š” ์ž‘์—…์„ ์ž์‹ ์˜ ๋ฐฉํ–ฅ์œผ๋กœ ์˜ฎ๊ธฐ๊ณ  ์žํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์„ ์‹ค๋ง์‹œํ‚ค๋Š” ๊ฒƒ"์ด๋ผ๊ณ  ๋งํ–ˆ์Šต๋‹ˆ๋‹ค.

๋” ๋งŽ์€ ๋ฌธ์„œ (์˜ˆ :์ด ์˜ค๋ฅ˜์— ๋Œ€ํ•œ ๋” ๋งŽ์€ ์˜ˆ์ œ ๋ฐ ์ˆ˜์ • ๋ฐฉ๋ฒ•), ๋” ๋‚˜์€ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ๋“ฑ์˜ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ํ™˜์˜ํ•˜์ง€๋งŒ ๋“œ๋ผ๋งˆ, ๋ฌด๋ก€ ํ•จ ๋˜๋Š” ๋ถˆํ‰์—๋Š” ๊ด€์‹ฌ์ด ์—†์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋ฅผ Mocha์— ์ œ๊ณตํ•˜๋ฉด ๋ถ€์ •์ ์ธ ๊ฒƒ์„ ๊ธ์ •์ ์œผ๋กœ ๋ฐ”๊พธ๋Š” ๋ฐ ๋„์›€์ด๋ฉ๋‹ˆ๋‹ค.

์ด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๋งˆ์Œ์— ๋“ค์ง€ ์•Š๊ณ  ๋‹จ์ˆœํžˆ ๊ฑด์„ค์  ์ผ ์ˆ˜ ์—†๋‹ค๋ฉด OSS์ž…๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ๋ฅผ ๋ถ„๊ธฐํ•˜๊ณ  ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋˜๋Œ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@boneskull์€ promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. promise๊ฐ€ ์ถฉ์กฑ ๋  ๋•Œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋ฅผ ์™„๋ฃŒ ํ•  ํ•„์š”๋Š” ์—†์ง€๋งŒ ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž ์ง€์ • ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ๋งํ–ˆ๋“ฏ์ด์ด ์ฝ”๋“œ๋Š” mocha @ 2 ์—์„œ๋Š” ์™„๋ฒฝํ•˜๊ฒŒ ์ž‘๋™ํ•˜์ง€๋งŒ mocha @ 3 ์—์„œ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ €ํฌ ํŒ€ (~ 20ppl)์€์ด ๋•Œ๋ฌธ์— ์ตœ์‹  ๋ชจ์นด๋กœ ์ด๋™ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ mocha 2.x๋Š” ๋งŽ์€ ์œ ์—ฐ์„ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ณ€๊ฒฝ์— ๋Œ€ํ•œ ๊ธฐ์ˆ ์  ์ด์œ ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

@artyomtrityak ์ด๊ฒƒ์ด ๋ถˆํ•„์š”ํ•œ ๋ถ€๋ถ„์˜ ํ›Œ๋ฅญํ•œ ์˜ˆ์ž…๋‹ˆ๋‹ค.

babel async/await ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๊ณ  return new Promise ์—†์ด ์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ๋ณด์ด๋Š”์ง€ ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

@artyomtrityak ์•ฝ์†์„ ์™„์ „ํžˆ ์ˆ˜์šฉํ•˜๋Š”

it('should fill userName and password', async function () {
    const userNameField = global.driver.wait(until.elementLocated({css: '#username'}));
    userNameField.sendKeys('admin');

    const passNameField = global.driver.findElement({css: '#password'});
    passNameField.sendKeys('*******');

    const userNameVal = await userNameField.getAttribute('value');
    const passwordVal = await passNameField.getAttribute('value');

    assert.equal(userNameVal, 'admin');
    assert.equal(passwordVal, 'changeme');
  });

๊ฐœ์ธ์ ์œผ๋กœ ๊ณต๊ฒฉ์„ ๋ฐ›์•˜๋‹ค๊ณ  ๋Š๋‚€๋‹ค๋ฉด์ด ๋Œ€ํ™”์— ์–ผ๋งˆ๋‚˜ ๊ฐ์ •์ ์œผ๋กœ ํˆฌ์žํ–ˆ๋Š”์ง€ ์žฌ๊ณ ํ•ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ฐœ์ธ์ ์ธ ์˜๊ฒฌ์€ ์—†์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ๊ฐ์‚ฌํ•˜๊ณ  ์นญ์ฐฌ ํ• ๋งŒํ•œ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋ฐ ์‹œ๊ฐ„์„ ํˆฌ์ž ํ•œ ์ ์„ ๊ณ ๋ คํ•˜๋ฉด ๋ชจ๋‘ ํ›Œ๋ฅญํ•˜๋‹ค๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค.

๋Œ€๋ถ€๋ถ„ (ํ˜„์žฌ ํ™œ์„ฑ ์œ ์ง€ ๊ด€๋ฆฌ์ž)์€ 2014 ๋…„ ์ค‘๋ฐ˜์— Mocha ์ž‘์—…์„ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ชจ์นด๋Š” ์—ฌ๋Ÿฌ๋ถ„์ด ๊ธฐ์—ฌํ•˜๊ธฐ ์‹œ์ž‘ํ•œ ์‹œ์ ์— ์ด๋ฏธ ์„ค๋ฆฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ œ ์˜๊ฒฌ ์ผ ๋ฟ์ด์ง€ ๋งŒ ์ •๋‹นํ™”๋˜์ง€ ์•Š๋Š” ํ•œ ๊ธฐ์กด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ณ€๊ฒฝํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์ด ์ € ํ˜ผ์ž๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ๋ณ€๊ฒฝ์— ๋Œ€ํ•œ ์›๋ž˜์˜ ์ •๋‹น์„ฑ์„ ์ƒ์ƒํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋‹ค์Œ์„ ์ง€์ ํ•˜๋ฉด ์ž˜ ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฝœ๋ฐฑ์„ ์š”์ฒญํ•˜๋Š” ๊ฒƒ์€ ๋ช…ํ™•ํ•œ ์˜๋„๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. Promise๋Š” ์š”์ฒญ๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ช…ํ™•ํ•˜์ง€ ์•Š์œผ๋ฉฐ ๋ฐ˜ํ™˜๋˜๋ฉฐ ๊ฐ„์ ‘์  ๋ฐ ์šฐ๋ฐœ์ ์œผ๋กœ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์˜ˆ : ํƒ€์‚ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ๋ฐ˜ํ™˜ ๋จ). ์ด๋Ÿฌํ•œ ์ฐจ์ด๋กœ ์ธํ•ด ์–‘๋ณด์˜ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ๋™์ผํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋‘ ๊ฐ€์ง€๋ฅผ ๋ชจ๋‘ ์‚ฌ์šฉํ•˜๋ ค๋Š” ์‹œ๋„๋Š” ์‹ค์ œ๋กœ ๋ชจํ˜ธํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฝœ๋ฐฑ์€ ํ…Œ์ŠคํŠธ ์ธ์ˆ˜์— ์ž‘์„ฑ๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์•ฝ์†์œผ๋กœ๋Š” ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์ฝœ๋ฐฑ์„ ์š”์ฒญํ•จ์œผ๋กœ์จ ์˜๋„๋ฅผ ๋ช…์‹œ ์ ์œผ๋กœ ์ „๋‹ฌํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ท€ํ•˜์˜ ์ปค๋ฎค๋‹ˆํ‹ฐ๋Š” ์ด๋Ÿฌํ•œ ์šฐ๋ ค๋ฅผ ์ œ๊ธฐํ–ˆ์œผ๋ฉฐ ์‹ค์ˆ˜๋ฅผ ์ธ์ •ํ•˜๋Š” ๋Œ€์‹  ๋‘ ๋ฐฐ๋กœ ์ค„์–ด๋“ค๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์˜ค๋ฅ˜๊ฐ€ ์ผ๊ด€๋˜๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ํ…Œ์ŠคํŠธ๋ฅผ ๋น„ ๋™๊ธฐํ™”ํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜๊ณ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. => https://github.com/mochajs/mocha/pull/2413์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค. ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์‹ค์ˆ˜๋กœ๋ถ€ํ„ฐ ๋ณดํ˜ธํ•˜๋Š” ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€์— ๋Œ€ํ•œ ํฐ ๋ณ€ํ™”์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ๋ถ„์€ @tj ๊ฐ€ ๋– ๋‚œ ์ดํ›„

@RobertWHurst์™€ ์™„์ „ํžˆ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

done ์š”์ฒญ์€ ๋ฐ˜ํ™˜ ๋œ promise ๋™์ž‘์„ ์žฌ์ •์˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ done ๋ฅผ ์š”์ฒญํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋‚ฎ์œผ๋ฉฐ async ํ•จ์ˆ˜์—์„œ ์ƒ์„ฑ ๋œ ์ด๋ฒคํŠธ์˜ ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ์™„๋ฒฝํ•œ ์˜ˆ์ž…๋‹ˆ๋‹ค.

์œ„์˜ ๋‚ด ์˜๊ฒฌ์—์„œ :

it('fires change event when calling blah.doSomethingThatFiresChange', async function (done) {
  const blah = await getBlah()
  blah.on('change', () => done())
  blah.doSomethingThatFiresChange()
})

๋” ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ES6 / 7 + async / await ๋กœ ์ด๋™ํ•จ์— ๋”ฐ๋ผ Mocha๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์žฌ๊ณ ํ•˜์‹ญ์‹œ์˜ค.

@RobertWHurst done ์ฝœ๋ฐฑ์„ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ๋ช…์‹œ์ ์ธ ์˜๋„๋ผ๊ณ  ์ฃผ์žฅํ•ฉ๋‹ˆ๋‹ค. return ์ง„์ˆ ์€ ๋ช…์‹œ์ ์ธ ์˜๋„๊ฐ€ ์•„๋‹™๋‹ˆ๊นŒ? ๋‘˜ ๋‹ค ์ฝ”๋“œ์— ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ์˜ ํ•œ ๋ถ€๋ถ„์ด ์˜๋„์ ์ด๊ณ  ๋‹ค๋ฅธ ๋ถ€๋ถ„์ด ์•„๋‹Œ์ง€ ์–ด๋–ป๊ฒŒ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? () => foo ์ด์ „์˜ ์„ธ๊ณ„๋ฅผ ์ƒ์ƒํ•œ๋‹ค๋ฉด ๋ชจ๋“  return ๋ฌธ์€ ํ•ญ์ƒ ๋ช…์‹œ ์ ์ด์—ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹น์‹ ์ด ์ง€๊ธˆ ๋ชจ๋‘ ํŒ”์งฑ์„ ๋ผ๊ณ ์žˆ๋Š” ์œ ์ผํ•œ ์ด์œ ๋Š” ๋‹น์‹ ์ด ์•”์‹œ์ ์ธ return ๋ฌธ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ œ๊ฐ€ ์ƒ๊ฐํ•  ์ˆ˜์žˆ๋Š” ๊ฒƒ์€ ๋ฏธ์ ์ธ ์ด์œ  ์ผ๋ฟ์ž…๋‹ˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ Mocha ์‚ฌ์šฉ์€ ์ผ๋ฐ˜์ ์œผ๋กœ done ์ฝœ๋ฐฑ์„ ํฌํ•จ ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋งค์šฐ ๋†’์€ ์˜ˆ์ œ๋ฅผ ๋ณต์‚ฌ / ๋ถ™์—ฌ ๋„ฃ๊ธฐํ•˜๋Š” ์ดˆ๋ณด์ž์— ์˜ํ•ด ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค.์ด ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž๊ฐ€ ๋ช…์‹œ ์ ์œผ๋กœ promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€๋งŒ ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ• ๊นŒ์š”? ์ด๊ฒƒ์€ ๋‹น์‹ ์ด ํ™”๊ฐ€ ๋‚œ ๋ณ€ํ™”๊ฐ€ ๋˜๋Œ๋ฆด ๋•Œ์˜ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค.

ํ˜„์žฌ ๋™์ž‘์€ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ณด๋‹ค ๋ฌด์—‡์ด ์ž˜๋ชป๋˜์—ˆ๋Š”์ง€ ํ›จ์”ฌ ๋” ๋ช…ํ™•ํ•ฉ๋‹ˆ๋‹ค.

@Munter ๊ทธ๋ฆผ ์—์„œ async ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด await ์‚ฌ์šฉ ์—ฌ๋ถ€์— ๊ด€๊ณ„์—†์ด ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜๊ณ  ๋ฐ˜ํ™˜๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ˜ํ™˜ ๋œ promise ์ ์ˆ˜๊ฐ€ ๋ช…์‹œ ์„ฑ ์ฒ™๋„์—์„œ ๋” ๋‚ฎ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

it('should work with a async function that could have been sync', async function () {
  assert.ok(true);
});

it('should work with a legitimately async function', async function () {
  assert.equal(await getBlah(), 'blah');
});

it('should work with a fully spelled-out Promise-based test', function () {
  return getBlah().then(function (blah) {
    assert.equal(blah, 'blah');
  });
});

๊ทธ๋ฆฌ๊ณ  ๋…ผ๋ž€์˜ ์—ฌ์ง€๊ฐ€์žˆ๋Š” ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

it('should foo', async function (done) {
  assert.equal('foo', 'foo');
  done();
});

์•„์ฃผ ์ž‘์€ async ์šฐ์—ฐํžˆ ์ž ์ž…ํ•˜๊ธฐ ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์—

์—ฌ๊ธฐ์—์„œ ์•ฝ๊ฐ„์˜ ๋Œ€ํ™” => https://github.com/mochajs/mocha/pull/1320 ํ›„์— ๋ฌธ์ œ์— ๋Œ€ํ•œ ๋Œ€์ฒด ์†”๋ฃจ์…˜์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๊ฐ€ ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ๋ฆฌ๋ทฐ์˜ ์ฆ๊ฑฐ์›€์„ ์œ„ํ•ด PR์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค => https://github.com/mochajs/mocha/pull/2454

:๋งฅ์ฃผ:

done ์ฝœ๋ฐฑ์„ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ๋ช…์‹œ์ ์ธ ์˜๋„๋ผ๊ณ  ์ฃผ์žฅํ•ฉ๋‹ˆ๋‹ค. return ๋ฌธ์ด ๋ช…์‹œ์ ์ธ ์˜๋„๊ฐ€ ์•„๋‹™๋‹ˆ๊นŒ?

@Munter coffeescript์™€ es6 ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ํ‘œํ˜„์‹์ด _implicitly_๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

it 'should foo', (done) -> request('/foo').end (err, res, body) -> done()

์•ˆ์ „ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ์ด ๋ฌธ์ œ๋Š” ๋ฉ‹์ง„ ํ•œ ์ค„์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€ํ™˜ํ•ด์•ผ ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

it 'should foo', (done) ->
  request('/foo').end (err, res, body) -> done()
  return

์ด๊ฒƒ์€ ๊ฐ๊ฐ ๊ณผ mecano ์˜ ์ „์ฒด ์ฝ”๋“œ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ์šฐ๋ฆฌ์˜ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ์ด๊ฑธ ๊ณ ๋ คํ•˜์„ธ์š”:

it 'should foo', (done) ->
  obj =
    run: ->
      done()
      @
    then: -> "what the hell, i'm not a promise"
  obj.run()

์ด๊ฒƒ์€ coffeescript์—๋งŒ ๊ตญํ•œ๋œ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ์•”์‹œ ์  ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์ตœ์•…์˜ ์ƒํ™ฉ์ด๋ฉ๋‹ˆ๋‹ค. Mocha๋Š” ์œ ํšจํ•œ promise ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ์ง€ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์˜ต์…˜์œผ๋กœ์ด ๊ธฐ๋Šฅ์„ ๋น„ํ™œ์„ฑํ™” ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋‘ ์•ˆ๋…•,
๋‹ค์Œ ์ฝ”๋“œ๋กœ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

describe('Page', ->
  describe('/GET home', ->
    it('it SHOULD return the homepage', (done) ->
      chai.request(app).get('/').end((err, res) ->
        res.should.have.status(200)
        res.text.should.be.a('string')
        done()
      )
    )
  )
)

์•ฝ์† ์ฒด์ธ์„ ์กด์ค‘ํ•˜๊ณ  ์ฝœ๋ฐฑ done() ์ƒ๋žตํ•˜์—ฌ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

describe('Page', ->
  describe('/GET home', ->
    it('it SHOULD return the homepage', ->
      chai.request(app).get('/').then((res) ->
        res.should.have.status(200)
        res.text.should.be.a('string')
      )
    )
  )
)

๋‚˜๋Š” ์ด๊ฒƒ์ด ๋น„์Šทํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ๋„์›€์ด๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

PS : ํ•˜ํŠธ : ๋ชจ์นด btw : +1 :

ํŽธ์ง‘ @Munter ์˜ ์˜๊ฒฌ์— ๋”ฐ๋ผ catch() ์ œ๊ฑฐ.

@karlbateman ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ๋งˆ์ง€๋ง‰ .catch ๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฑฐ๋ถ€ ๋œ ์•ฝ์†์€ Mocha์— ์˜ํ•ด ์˜ค๋ฅ˜๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค.

@Munter , ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค : ์Šค๋งˆ์ผ :

์กฐ๊ธˆ ๋” ์ƒ๊ฐ ํ•ด๋ณด๋‹ˆ ํ”„๋ผ ๋ฏธ์Šค์™€ ์ฝœ๋ฐฑ์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์ž‘์ด ์ •๋ง ๋งˆ์Œ์— ๋“ญ๋‹ˆ๋‹ค. ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์ง„์ „์ด ์žˆ์—ˆ์Šต๋‹ˆ๊นŒ?

@ light24bulbs ํ”ผ๋“œ๋ฐฑ ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ์•„๋‹ˆ, ์•„ํŒŒ ์ต ๋‚ด๊ฐ€ ๋ฐ˜์‘์„๋ณด๊ธฐ ์œ„ํ•ด ๊ฑฐ๊ธฐ์— ๋˜์ง„ ์•„์ด๋””์–ด์ด๊ธฐ ๋•Œ๋ฌธ์— ์•„๋ฌด๋„ ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ์ž‘์—…์„ ์‹œ์ž‘ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋ฐฉ๊ธˆ ์•„์ด๋””์–ด์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ํ”ผ๋“œ๋ฐฑ์ด ์žˆ๋Š”์ง€, ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฐ”๋ฒจ์„ ์‚ฌ์šฉํ•  ๋•Œ ์ด์— ๋Œ€ํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๋ฐ”๋ฒจ์„ ์‚ฌ์šฉํ•  ๋•Œ ์ด์— ๋Œ€ํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๋‘ ๋ฒˆ ํฌ์žฅํ•ฉ๋‹ˆ๋‹ค.

it("should work", done => {
  (async () => {
    await something;
    done();
  })();
});

@SaschaNaz ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค, ์ด๊ฒƒ์€ v3.2.0์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค :)

6 ๊ฐœ์›” ํ›„, ์ด๊ฒƒ์€ ์—ฌ์ „ํžˆ โ€‹โ€‹๋ชจ๋“  ์ตœ์‹  js ํ…Œ์ŠคํŠธ๋ฅผ ์ œ๋™ํ•˜๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.
๋ถ€๋„๋Ÿฌ์›€

@benfavre ์ž์› ๋ด‰์‚ฌ์ž๋“ค์ด ์•„์ด๋“ค๊ณผ ๋†€๊ธฐ๋ณด๋‹ค ์ž์œ  ์‹œ๊ฐ„์— ์ง€์ •ํ•˜์ง€ ์•Š์€ ์†”๋ฃจ์…˜์„ ๊ตฌํ˜„ํ•  ์ฑ…์ž„์„์ง€๊ฒŒ ํ•  ๊ฐ€์žฅ ํ™•์‹คํ•œ ๋™๊ธฐ๋ฅผ ๋ถ€์—ฌํ•˜๋Š” ๊ฒฉ๋ ค์˜ ๋ง์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

@Munter mochajs ์˜ ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž๋กœ์„œ ์ง๋ฉด ํ•œ ํŠน์ • ๋ฌธ์ œ๋ฅผ ์‹๋ณ„ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค„ ์ˆ˜์žˆ์–ด ๊ฑฑ์ •ํ• 
@SaschaNaz ๋Š” ๋‘ ๋ฒˆ ํฌ์žฅํ•˜๋Š” ์†”๋ฃจ์…˜์„ ์ œ์•ˆํ–ˆ์ง€๋งŒ ๋„์›€์ด๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

=> ์•ฝ์† ๋งŒ ์‚ฌ์šฉํ•˜๋ฉด ์ œ๋Œ€๋กœ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ๋ฒˆ์—๋Š” ๋ฐ”๋ณด์ฒ˜๋Ÿผ "+1"๋งŒํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™์•„ ๊ณต์งœ๋กœ ๋ชจ์š•์„ ๋‹นํ•˜์ง€ ์•Š๋„๋ก.
๋‚ด ๋ฉ”์‹œ์ง€์—๋Š” ๋ชจ์š•์  ์ธ ๋‚ด์šฉ์ด ์—†์—ˆ์œผ๋ฉฐ ๋” ๋‚˜์•„๊ฐ€ ๋‚ด ์ง„์ˆ ์€ ์‚ฌ์‹ค๋กœ ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์€ ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„ ์›Œํฌ๋ฅผ ์„ ํƒํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ๋กœ์„œ๋Š” async / await๋กœ ๋‹จ์ˆœํ•˜๊ฒŒ ๊นจ์กŒ๊ณ , ๋ฉ”์ธ ์‚ฌ์ดํŠธ์— ๋ช…ํ™•ํ•œ ํ‘œ์‹œ๊ฐ€์—†๊ณ  cli์— ๋ช…ํ™•ํ•œ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์ƒˆํ•ด ๋ณต ๋งŽ์ด ๋ฐ›์œผ์‹œ๊ณ  ์•„์ด๋“ค๊ณผ ์ฆ๊ฑฐ์šด ์‹œ๊ฐ„์„ ๋ณด๋‚ด์‹ญ์‹œ์˜ค.

๋ƒ‰๊ธฐ...

ํ† ๋ก ์€ done ์ฝœ๋ฐฑ๊ณผ ๋ฐ˜ํ™˜ ๋œ Promise ๋ชจ๋‘์— "์ฃผ์˜๋ฅผ ๊ธฐ์šธ์ด๋Š”"๊ฒƒ์œผ๋กœ ๋ฐœ์ „ํ–ˆ์Šต๋‹ˆ๋‹ค. : https://github.com/mochajs/mocha/issues/2509

ํ์‡„. # 2509 ์ฐธ์กฐ

์•„์ง ๋ชธ์ด ํž˜๋“ค๋‹ค๋ฉด ...

๋ฐ”๋ฒจ์„ ์‚ฌ์šฉํ•  ๋•Œ ์ด์— ๋Œ€ํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ด์ œ # 2509์—์„œ ์–ธ๊ธ‰ ํ•œ ์•ฝ์† ์ฒ˜๋ฆฌ๊ธฐ๊ฐ€ ๋‚ด์žฅ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด wrapping twice hack ๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

it("should work", done => {
  (async () => {
    await something;
    done();
  })();
});

๋Œ€์‹  ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ„๋‹จํžˆ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

it("should work", async () => {
  await something;
});

์ž์„ธํ•œ ๋‚ด์šฉ์€์ด ๊ฒŒ์‹œ๋ฌผ ์„ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.

@ lo-tp
1.)์ด ์ฝ”๋“œ๋Š” babel๋กœ ์ปดํŒŒ์ผ ํ•  ๋•Œ ์ž‘๋™ํ•ฉ๋‹ˆ๊นŒ?

it("should work", async () => {
  await something;
});

์•ˆ๋…•ํ•˜์„ธ์š”.

  • ์˜ˆ, ์ง€๊ธˆ async/await ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด babel์˜ ๋„์›€์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ๋ญ”๊ฐ€๋ฅผ ๋†“์น˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์ง€๋งŒ ์•ฝ์†๊ณผ ํ•จ๊ป˜ return ๋ฌธ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  done ()์— ์˜์กด ํ•˜์—ฌ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋ฅผ ์œ„ํ•ด ์ผํ•˜๋Š” ์˜ˆ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  describe('STRIPE CHARGES: Get Charges', () => {
    it('should list customer charges', async () => {
      const charges = await Stripe.getChargesList(customerObj);
      charges.data[0].should.have.property('id');
      charges.data[0].amount.should.have.property('id');
    });
  });

๋‚˜๋Š” chai.assert์™€ ํ•จ๊ป˜ mocha 4๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ฒ˜์Œ์—๋Š” done () ์ฝœ๋ฐฑ์„ ์‚ฌ์šฉํ•˜๋ ค๊ณ ํ–ˆ์Šต๋‹ˆ๋‹ค.

it('should throw an error', async function(done) {
  try {
    result = await something('value that causes something() to throw an Error');
    done('failed');
  } catch (e) {
    done();
  }
});

๊ทธ๊ฒƒ์€ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค

Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both."

๊ทธ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋ฅผ์ด ํŽ˜์ด์ง€๋กœ ์ด๋Œ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋‹ค์†Œ ๊ธด ์Šค๋ ˆ๋“œ๋ฅผ ํ†ต๊ณผํ•˜๋ฉด์„œ (๊ทธ๋ฆฌ๊ณ  ๋ชจ๋“  ๋ถ„์Ÿ์„ ์™„์ „ํžˆ ์ดํ•ดํ•˜์ง€ ๋ชปํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ์ธ์ •ํ•ฉ๋‹ˆ๋‹ค) ์•ฝ์† ๊ธฐ๋ฐ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ๋น„๋™๊ธฐ ํ˜ธ์ถœ๊ณผ ํ•จ๊ป˜ done ()์„ ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค๋Š” ๊ฒƒ์„ ์ดํ•ดํ•ด์•ผํ•ฉ๋‹ˆ๊นŒ?

๊ทธ๋ ‡๋‹ค๋ฉด await something () ํ˜ธ์ถœ์ด ์˜ค๋ฅ˜๋ฅผ ๋˜์งˆ ๋•Œ ๋‹ค์Œ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒํ•ด์•ผํ•ฉ๋‹ˆ๊นŒ?

it('should throw an error', async function() {
  try {
    result = await something('value that causes something() to throw an Error');
  } catch (e) {
    // how to indicate that this should happen, if I can't call done() to tell mocha?
  }
});

๋ˆ„๊ตฐ๊ฐ€์ด ํŠน์ • ์‚ฌ๋ก€๋ฅผ ์ดํ•ดํ•˜๋„๋ก ๋„์™€ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์–ด์„ค ์…˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๊นŒ, ์•„๋‹ˆ๋ฉด ์œ„์˜ ์ฝ”๋“œ์— ์ถ”๊ฐ€ํ•ด์•ผํ•˜๋Š” ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์‰ฌ์šด ๋‚ฎ์€ ์ˆ˜์ค€์˜ ์†”๋ฃจ์…˜ :

it('should throw an error', async function() {
  try {
    result = await something('value that causes something() to throw an Error');
    throw new Error('Promise unexpectedly fulfilled');
  } catch (e) {
    // Optionally assert something about e...
  }
});

๋‚˜๋Š” ์ฃผ์ค‘ ์–ธ์ œ๋“ ์ง€ ์–ด์„ค ์…˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

const expect = require('unexpected');
it('should throw an error', async function () {
    await expect(something(), 'to be rejected with', 'the error message');
});

๋˜๋Š” chai + chai-as-promised :

const chai = require('chai');
chai.use(require('chai-as-promised'));
const expect = chai.expect;

it('should throw an error', async function () {
    await expect(something()).to.be.rejectedWith('argh');
});

์•ˆ๋…•ํ•˜์„ธ์š”, ์ด๊ฒƒ์€ asyncawait์—์„œ ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค ( 'done ()'์ƒ๋žต)

describe('New order from landing', function() {
    describe('check new client function', function () {
        it("must check db and return that random client is new", async function () {
            var result = await handler.checkClient(reqNewClient.body)
                expect(result).to.have.property('newclient').equal(true)
            })
    })
})

๊ฒฐ๊ณผ:

์ฐฉ๋ฅ™์—์„œ ์ƒˆ๋กœ์šด ์ฃผ๋ฌธ
์ƒˆ ํด๋ผ์ด์–ธํŠธ ๊ธฐ๋Šฅ ํ™•์ธ
โˆš db๋ฅผ ํ™•์ธํ•˜๊ณ  ์ž„์˜์˜ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ƒˆ๋กœ์šด ๊ฒƒ์„ ๋ฐ˜ํ™˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
1 ํšŒ ํ†ต๊ณผ (9ms)

@kolykhalov ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ๊ทธ๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ผํ–ˆ์Šต๋‹ˆ๋‹ค

์ œ ๊ฒฝ์šฐ์—๋Š” ๋น„๋™๊ธฐ ๋ธ”๋ก์„ try / catch๋กœ ๋ž˜ํ•‘ํ–ˆ์Šต๋‹ˆ๋‹ค.

it('It should activate a user.', async() => {
        return new Promise((resolve, reject) => {
            try {
                // Get the last activation token from the DB
                let sql = 'select * from activation_tokens order by created_at desc limit 1';
                let res = await DB.query(sql);
                let {token} = res[0];

                server
                    .post('/auth/activate')
                    .send({token})
                    .set('Content-Type', 'application/x-www-form-urlencoded')
                    .expect('Content-Type', /json/)
                    .expect(200)
                    .end((err, res) => {
                        res.body.data.should.contain.keys('message');
                        res.body.data.message.should.equal("Activated");
                        resolve();
                    });
            } catch (e) {
                console.error(e);
            }
        });
    });

์ทจ์•ฝ์„ฑ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์—…๊ทธ๋ ˆ์ด๋“œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ 99 ๊ฐœ์˜ ํ…Œ์ŠคํŠธ๋ฅผ ๋‹ค์‹œ ์ž‘์„ฑํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. FML

๋”ฐ๋ผ์„œ ๋ฌธ์ œ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ๋ช…ํ™•ํžˆํ•˜๊ธฐ ์œ„ํ•ด ์ผ๋ถ€ ์‚ฌ๋žŒ๋“ค์€ done ๋ฐ async ๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๊ณ  ๋งํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ๋‘˜ ๋‹ค ์‚ฌ์šฉํ•˜๋ ค๋Š” ์˜ˆ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

it('should error on fn', async function(done) {
  try {
    await fn();
  } catch (e) {
    // assert some things here
    done()
  }
});

done ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์œผ๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผ๋ฉ๋‹ˆ๋‹ค. ์ผ๋ถ€๋Š” expect(await fn).to.throw('blah') ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋„๋ก ์ œ์•ˆํ–ˆ์ง€๋งŒ ๋•Œ๋กœ๋Š” ํ•œ ์ค„์— ๋“ค์–ด๊ฐˆ ์ˆ˜์žˆ๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ๋งŽ์€ ์†์„ฑ์„ ํ™•์ธํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์ง€๋งŒ ์‹ค์ˆ˜๋กœ ์•ฝ์†์„ ๋ฐ˜ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค (์Šˆํผ ํ…Œ์ŠคํŠธ).

it('Should do something', (done) => {
       return supertest(server)
           .get(`/api/endpoint`)
           .set('somekey', 'somevalue')
           .expect(200)
           .then(() => { done(); })
           .catch(done);
});

'๋ฐ˜ํ’ˆ'์ ˆ์„ ์ œ๊ฑฐํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์— ์—ด๊ด‘ํ•œ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์—๊ฒŒ๋Š” ...

์ด๊ฒƒ์€ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค :

it("should work", async () => {
  await something;
});

์ด๊ฒƒ์€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค :

it("should work", async (done) => {
  await something;
});

done ๋ฅผ ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ์ œ๊ฑฐํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

@tamoyal , ์˜ˆ -elado๊ฐ€ 2016 ๋…„ 8 ์›” 3 ์ผ์—

async / await๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•”์‹œ ์  Promise ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. done ์ฝœ๋ฐฑ ์‚ฌ์šฉ์€
์—ฌ๊ธฐ์— ํ‘œ์‹œ๋œ๋Œ€๋กœ CPS ๊ธฐ๋ฐ˜ ๋น„๋™๊ธฐ. Mocha๋Š” ๋‘˜ ๋‹ค ์ง€์›ํ•˜์ง€๋งŒ ๋™์‹œ์—๋Š” ์•„๋‹™๋‹ˆ๋‹ค.
์ด๊ฒƒ์€ ๋ฌธ์„œํ™” ๋˜์–ด ์žˆ์œผ๋ฉฐ Mocha-3.0 ๋ฆด๋ฆฌ์Šค ์ดํ›„ ํ‘œ์ค€ ๋™์ž‘์ด์—ˆ์Šต๋‹ˆ๋‹ค.

์ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์ง€๋งŒ ์‹ค์ˆ˜๋กœ ์•ฝ์†์„ ๋ฐ˜ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค (์Šˆํผ ํ…Œ์ŠคํŠธ).

it('should do something', (done) => {
       return supertest(server)
           .get(`/api/endpoint`)
           .set('somekey', 'somevalue')
           .expect(200)
           .then(() => { done(); })
           .catch(done);
});

'๋ฐ˜ํ’ˆ'์ ˆ์„ ์ œ๊ฑฐํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

@victorsferreira , ์ด๊ฒƒ์ด ํ•ด๊ฒฐ์ฑ…์ด์—ˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค ...

it('should do something', () => {
  return supertest(server)
    .get(`/api/endpoint`)
    .set('somekey', 'somevalue')
    .expect(200);
});

@tamoyal ๋„ค ๊ทธ๊ฒŒ ๋‚˜๋ฅผ ๋„˜์–ด

@mienaikoe ,์ด ์ •ํ™•ํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” ๋ช…์‹œ ์ ์œผ๋กœ ๋ฌธ์„œํ™” ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

@plroebuck ๋‘ ๊ฐ€์ง€ :

1) ๋ฌด์–ธ๊ฐ€๋ฅผ ๋ฌธ์„œํ™”ํ•˜๋Š” ๊ฒƒ๊ณผ ํ•จ์ˆ˜์˜ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์กฐ์‚ฌํ•˜๋Š” npm์˜ ๋ช‡ ์•ˆ๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ํ•˜๋‚˜๊ฐ€๋˜๋Š” ๊ฒƒ์—๋Š” ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์นœ๊ตฌ๋“ค์„ ์ฒ˜์Œ ๋งŒ๋‚ฌ์„ ๋•Œ ๋ชจ๋“  ์นœ๊ตฌ๋“ค์˜ ๋ฐฐ๊ฒฝ ์กฐ์‚ฌ๋ฅผ ๋ฐ›๋Š”๋‹ค๋Š” ๊ฒƒ์„ ๋ฌธ์„œํ™” ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์—ฌ์ „ํžˆ ์ด์ƒํ•˜๊ณ  ์‚ฌ๋žŒ๋“ค์€ ๋‚ด๊ฐ€ ์ด์œ ๊ฐ€์—†๊ณ  ๋ช…์‹œ ์ ์œผ๋กœ ์ด์œ ๋ฅผ ๋งํ•˜์ง€ ์•Š๋Š” ํ•œ ๋ถˆํ‰ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

2) ๋ฌธ์„œ์— ๊ฒฐํ•จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

Mocha v3.0.0 ์ด์ƒ์—์„œ Promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  done ()์„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

done์„ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์‚ฌ์šฉ ์—ฌ๋ถ€์— ๊ด€๊ณ„์—†์ด _ done ๋ฅผ ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ์ง€์ • _ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ฟก ๋นต๋€จ

  1. Mocha๋Š” it ์˜ ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ํ™•์ธํ•˜์—ฌ ํ•จ์ˆ˜๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ  (์žˆ๋Š” ๊ฒฝ์šฐ) ์‚ฌ์šฉ์ž๊ฐ€ ์ฝœ๋ฐฑ์„ ์ถ”๊ฐ€ํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ธํŠธ๋กœ ์ŠคํŽ™ ์…˜์œผ๋กœ ๊ฑฐ์˜ ์ ํ•ฉํ•˜์ง€ ์•Š์œผ๋ฉฐ JavaScript์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  2. ๋ฌธ์„œ๊ฐ€ ๋„ˆ๋ฌด ๋ชจํ˜ธํ•˜๋‹ค๊ณ  ์ƒ๊ฐ๋˜๋ฉด PR์„ ๋ณด๋‚ด ๋ฌธ์„œ๋ฅผ ์ˆ˜์ •ํ•˜์‹ญ์‹œ์˜ค.

param์œผ๋กœ ์ œ๊ฑฐํ•˜๋ฉด ๋‚˜๋ฅผ ์œ„ํ•ด ์ผํ–ˆ์Šต๋‹ˆ๋‹ค!

์ „์—:

image

ํ›„ (์ž‘๋™!)

image

@QauseenMZ , "์ด์ „"๊ณผ "์ดํ›„"์ฝ”๋“œ๊ฐ„์— ์ฐจ์ด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋‹น์‹ ์€ ๋˜ํ•œ ๋‹น์‹ ์˜ ์•ฝ์†์„ ๋Œ๋ ค์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๋น„์Šทํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

  it('should receive successful RPC response', async () => {
    return await getResponse(unitData)
      .then((res) => {
        expect(res).to.have.status(200);
      });
  });

์ถ”์‹ . ๋…ธ๋“œ ์ฝœ๋ฐฑ ์ธ์ˆ˜ ์ˆœ์„œ๊ฐ€ ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค ... error _always_๊ฐ€ ๋จผ์ € ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.

@plroebuck ์–ธ๊ธ‰

getResponse ํ•จ์ˆ˜๊ฐ€ ์ฝœ๋ฐฑ์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์•ฝ์†์„ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ๋‚ด๊ฐ€ ์ž‘๋™ํ•˜๊ฒŒ ํ•œ ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์ด์—ˆ์Šต๋‹ˆ๋‹ค. getResponse ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

image

์—ฌ๊ธฐ์„œ ์˜ค๋ฅ˜๋Š” ์ฝœ๋ฐฑ getResponse ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์— ๋Œ€ํ•œ ๋‹น์‹ ์˜ ์ƒ๊ฐ์„ ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค. ๊ฐ์‚ฌ!

์ผ๋ถ€ ๋ถ€๋ถ„์€ ๋น„๋…ผ๋ฆฌ์ ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค. ๋ช…ํ™•์„ฑ์„ ์œ„ํ•ด ์–ด๋–ค request ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?
options ๊ฐ์ฒด ( unitData ๋ผ๋Š” ์ด๋ฆ„)๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

  • obj ์ถœ์ฒ˜๋Š” ์–ด๋””์ž…๋‹ˆ๊นŒ?
  • ์™œ ๊ฒƒ res.body.error A๋ฅผ res.statusCode === 200 ?

์ถ”์‹ . ์ฝ”๋“œ ์ด๋ฏธ์ง€๊ฐ€ ์•„๋‹Œ ์ฝ”๋“œ ์ž์ฒด๋ฅผ ๋ถ™์—ฌ ๋„ฃ์œผ์„ธ์š”.

์ด๊ฒƒ์— ์—ด๊ด‘ํ•œ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์—๊ฒŒ๋Š” ...

์ด๊ฒƒ์€ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค :

it("should work", async () => {
  await something;
});

์ด๊ฒƒ์€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค :

it("should work", async (done) => {
  await something;
});

done ๋ฅผ ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ์ œ๊ฑฐํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

@tamoyal ๋‹น์‹ ์€ ๋‚ด ์ธ์ƒ์„ ๊ตฌํ–ˆ์Šต๋‹ˆ๋‹ค <3

์ด๋กœ ์ธํ•ด ๋™์ผํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

it('Location Querying Works', async () => {
    await WeatherComponent.pullLocationData();
    Vue.nextTick(()=>{
      expect(WeatherComponent.$el.textContent).contain("Spain")
    })
  })

๋‹น์‹ ์ด์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ๋น ๋ฅธ ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด, ์•ฝ์†์˜ ์ „์ฒด ํ…Œ์ŠคํŠธ๋ฅผ ํฌ์žฅํ•˜๊ณ , ์‚ฌ์šฉ resolve ๋‹น์‹ ์ดํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ done .

์ด๊ฒƒ์„ ๋Œ๋ ค :

it.only("Works with the database", async (done) => {
    let browser = await puppeteer.launch();
    let query = db.collection('lists').where('ownerId', '==', 'UJIXXwynaCj8oeuWfYa8');
    let ct = 0;
    query.onSnapshot(async querySnapshot => {
        if (ct === 0) {
            await addAPurpose(browser, session, sessionSig); // A function with a bunch of Puppeteer code.
            ct++
        } else {
            expect(querySnapshot.size).to.equal(1);
            expect(querySnapshot.docs[0].get().title).to.equal("Understand Mocha");
            done();
        }
        console.log(`Received query snapshot of size ${querySnapshot.size}`);
    }, err => {
        console.log(`Encountered error: ${err}`);
    });
});

์ด๊ฒƒ์œผ๋กœ :

it.only("Works with the database", async () => {
    const onSnap = new Promise(async (res, rej) => {
        let browser = await puppeteer.launch();
        let query = db.collection('lists').where('ownerId', '==', 'UJIo1gGMueoubgfWfYa8');
        let ct = 0;
        let unsubscribe = query.onSnapshot(async querySnapshot => {
            if (ct === 0) {
                await addAPurpose(browser, session, sessionSig);
                ct++
            } else {
                expect(querySnapshot.size).to.equal(1);
                expect(querySnapshot.docs[0].data().title).to.equal("Evolution");
                // done(); 
                unsubscribe();
                res();
            }
            console.log(`Received query snapshot of size ${querySnapshot.size}`);
        }, err => {
            console.log(`Encountered error: ${err}`);
            rej()
        });
    });
    return onSnap;
});

๊ทธ๋ฆฌ๊ณ  ์›ํ•˜๋Š”๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

done์„ ํ˜ธ์ถœ ํ•  ๋•Œ๊นŒ์ง€ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰ ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— done ๋ฅผ ์ œ๊ฑฐํ•ด์•ผํ•˜๋Š” ํ•„์š”์„ฑ์— ๋†€๋ž์Šต๋‹ˆ๋‹ค. done์„ async์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค๋Š” ๊ฒƒ์„ ๋” ๋ช…ํ™•ํžˆํ•˜๊ธฐ ์œ„ํ•ด done์ด ์ „๋‹ฌ๋˜๋ฉด ๋น„๋™๊ธฐ ํ•จ์ˆ˜๊ฐ€ _ ์ฆ‰์‹œ _ ์‹คํŒจํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. Mocha๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ…Œ์ŠคํŠธ๋ฅผ ์‹œ์ž‘ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

  1. ํ•จ์ˆ˜๊ฐ€ ๋น„๋™๊ธฐ์ธ์ง€ ํ™•์ธํ•˜๊ณ 
  2. done ์ธ์ˆ˜๋ฅผ ๊ฐ์ง€ํ•ฉ๋‹ˆ๋‹ค.

๋‘˜ ๋‹ค ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ done ๊ฐ€ ํ˜ธ์ถœ ๋  ๋•Œ๊นŒ์ง€ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ ํ•œ ๋‹ค์Œ ๋‚˜๋ฅผ ๋ธ”๋ฃจ ๋ณผ๋งํ•˜๋Š” ๋Œ€์‹  ๋˜์ ธ์•ผํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์˜ค๋ฅ˜๋Š” ์ฝ”๋“œ๋ฅผ ๋‹ค๋ฅธ promise๋กœ ๋ž˜ํ•‘ํ•˜๊ณ  done ์ฒ˜๋Ÿผ resolve๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

function.prototype.name === "AsyncFunction" ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ

if (function.prototype.name === "AsyncFunction && arg1.name === "done") {
  throw new Error("Can't use done with an async function")
}

์ด๊ฒƒ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด.

๋‚˜๋Š” ์ด๊ฒƒ์— ๊ฑฐ์˜ SOL ์ด์—ˆ๋‹ค. ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด์•ผํ•˜๊ณ  ์ฝ”๋“œ ์‹คํ–‰์ด ์™„๋ฃŒ๋˜์ง€ ์•Š์„ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋˜๋ฏ€๋กœ done์„ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์„ฑ๊ฐ€์‹  ํ•ดํ‚น ๋ฐฉ๋ฒ•์€ ๋น„๋™๊ธฐ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž์ฒด ํ˜ธ์ถœ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋กœ ๋ž˜ํ•‘ํ•˜๋Š” ๊ฒƒ์ด์—ˆ์ง€๋งŒ it func๋Š” ๋™๊ธฐํ™” ํ•จ์ˆ˜๋กœ ๋‚จ๊ฒจ ๋‘์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ์ฑ…:

it("It shouldn't be like this", function (done) {
    ( async function(){
        var life = require('InfiniteLife');
        var asyncRes = await life.someCoolstuff();
        assert(asyncRes);
        setTimeout( function(){
            done();
        },letsCallItQuitsNow);
    })();
});

์ค‘๋‹จ์ด ์™„๋ฃŒ๋œ ๋น„๋™๊ธฐ ํ•จ์ˆ˜์˜ ์˜ˆ์ž…๋‹ˆ๋‹ค.

it('If the credentials exists in the system it should return the token generated against it.', async (done) => {
        let aObj = await admin.createAdmin();
        chai.request(server)
        .post("/authenticate")
        .set("Content-Type", "application/x-www-form-urlencoded")
        .send({username: aObj.login,password:aObj.password})
        .end((err, res) => {
            res.should.have.status(200);
            res.body.should.be.a("string");
            done();
        });
    });

์„ฑ๊ณต ์‚ฌ๋ก€

it('If the credentials exists in the system it should return the token generated against it.', async () => {
        let adminObj = await admin.createAdmin();
        chai.request(server)
        .post("/auth/login")
        .set("Content-Type", "application/x-www-form-urlencoded")
        .send({username: adminObj.login,password:adminObj.password})
        .end((err, res) => {
            res.should.have.status(200);
            res.body.should.be.a("string");
            // done();
        });
    });

ํ—‰ํ—‰

ํ…Œ์ŠคํŠธ์—์„œ done ๋„ async ๋„ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Chai http๋Š” ์•ฝ์†์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. Promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด Mocha์˜ ํ…Œ์ŠคํŠธ๋Š” ๋น„๋™๊ธฐ ์ฝ”๋“œ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

it('If the credentials exists in the system it should return the token generated against it.', () => {
  let adminObj = await admin.createAdmin();
  return chai.request(server)
    .post("/auth/login")
    .set("Content-Type", "application/x-www-form-urlencoded")
    .send({username: adminObj.login,password:adminObj.password})
    .end((err, res) => {
      res.should.have.status(200);
      res.body.should.be.a("string");
    });
});

๋ฟก ๋นต๋€จ

๊ฒŒ์‹œ ๋œ ์†”๋ฃจ์…˜์€ ์‹œ๊ฐ„์ด ๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ๊ฒฝ์šฐ ํ…Œ์ŠคํŠธ ์‹œ๊ฐ„์„ ์ดˆ๊ณผํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Mocha ์—๋Š” ์ด๋ฏธ์ด ๊ธฐ๋Šฅ์ด ๋‚ด์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

it("It should be liek this", async function () {
  this.timeout(letsCallItQuitsNow);

  var life = require('InfiniteLife');
  var asyncRes = await life.someCoolstuff();
  assert(asyncRes);
});

๊ท€ํ•˜์˜ ์˜ˆ์ œ๋Š” ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ์ดˆ๊ณผ๋˜๋ฉด ํ…Œ์ŠคํŠธ์— ์‹คํŒจํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์œผ๋ฏ€๋กœ ์ •ํ™•์„ฑ์— ๋”ฐ๋ผ ์กฐ์‹ฌํ•˜์‹ญ์‹œ์˜ค.

`express / js ๋ฐ firebase ํด๋ผ์šฐ๋“œ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ api ์˜ค๋ฅ˜ ์‘๋‹ต์„ ํ™•์ธํ•œ ๋‹ค์Œ ํ† ํฐ์„ ๋ฐ›๊ณ  ๋‹ค์‹œ ์‹œ๋„ํ•˜์„ธ์š”. express๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด .send๊ฐ€ ์•„๋‹Œ .json์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  mocha์™€ ํ•จ๊ป˜ ๋กœ๊ฑฐ ๋ฒ„๊ทธ๋ฅผ ์ž‘๋™ํ•˜๋ฏ€๋กœ ์ผ๋ฐ˜ console.log๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.
๋น„๋™๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์™„์ „ํžˆ ์™„๋ฃŒ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.

  process.env.NODE_ENV='TESTING';
  const { FIREBASE_UID } = require('dotenv').config()?.parsed;
  const { red, green, white } = require('chalk');
  const chai = require('chai');
  const chaiHttp = require('chai-http');
  const server = require('../lib/api').API;
  const should = chai.should();
  const expect = chai.expect;
  chai.use(chaiHttp);
  const test = chai.request(server).keepOpen();

  const shouldPrint = (details, status) => {
      return white(`details: ${details}, status: ${status}`);
  };

describe('Authorization Middleware Error Check for bad token', () => {

    it(shouldPrint('Bad Request', red(400)), async () => {
        try {
            const res = await test.get('/').send()
            res.should.have.status(400);
            res.should.have.json
            const { details, status } = JSON.parse(res.text)
            expect(details).to.equal('Bad request')
            expect(status).to.equal(400)
        } catch (error) { 
            throw error 
        }
    })


    it(shouldPrint('Unauthorized', red(401)), async () => {
        try {
            const res = await test.get('/').set('Authorization', 'Bearer bad123token').send()
            res.should.exist
            res.should.have.status(401);
            res.should.have.json
            const { details, status } = JSON.parse(res.text)
            expect(details).to.equal('Unauthorized')
            expect(status).to.equal(401) 
        } catch (error) {
            throw error
        }
    })

})

 describe('Get token and ping', () => {
    let adminToken

    it(shouldPrint( 'Create custom jwt for testing', green(200)), async () => {
        try {
            const res = await test.get(`/createToken/${FIREBASE_UID}`).send()
            res.should.exist
            res.should.have.status(200);
            res.should.have.json
            adminToken = (JSON.parse(res.text)).token
        } catch (error) {
            throw error
        }
    })

    it(shouldPrint('PING', green(200)), async () => {
        try {
            const res = await test.get('/')
                .set('x-tenorders-testing', 'true')
                .set('Authorization', `Bearer ${adminToken}`).send()

            res.should.exist
            res.should.have.status(200);
            res.should.have.json
            const { details, status } = JSON.parse(res.text)
            expect(details).to.equal('PING')
            expect(status).to.equal(200)
        } catch (error) {
            throw error
        }   
    })

})
`

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰