์ด:
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())
๋ฅผ ์๋ตํ๋ฉด ํ
์คํธ ์๊ฐ์ด ์ด๊ณผ๋ฉ๋๋ค.
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 ๋์ํฉ๋๋ค. ๊ทธ๋์ ๊ทธ๊ฒ์
Error
์ธ์คํด์คํํ์ง๋ง done()
๋ฅผ ํธ์ถํ์ง ๋ง์ญ์์ค.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
๋ฅผ ๋งค๊ฐ ๋ณ์๋ก ์ง์ _ํ๋ ๊ฒ์
๋๋ค.
๋ฟก ๋นต๋จ
it
์ ๋ ๋ฒ์งธ ๋งค๊ฐ ๋ณ์๋ฅผ ํ์ธํ์ฌ ํจ์๊ฐ ์กด์ฌํ๋์ง ํ์ธํ๊ณ (์๋ ๊ฒฝ์ฐ) ์ฌ์ฉ์๊ฐ ์ฝ๋ฐฑ์ ์ถ๊ฐํ๋์ง ์ฌ๋ถ๋ฅผ ํ์ธํฉ๋๋ค. ์ด๊ฒ์ ์ธํธ๋ก ์คํ ์
์ผ๋ก ๊ฑฐ์ ์ ํฉํ์ง ์์ผ๋ฉฐ JavaScript์์ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.param์ผ๋ก ์ ๊ฑฐํ๋ฉด ๋๋ฅผ ์ํด ์ผํ์ต๋๋ค!
์ ์:
ํ (์๋!)
@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 ํจ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ฌ๊ธฐ์ ์ค๋ฅ๋ ์ฝ๋ฐฑ 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๋ ๋ค์๊ณผ ๊ฐ์ด ํ
์คํธ๋ฅผ ์์ํด์ผํฉ๋๋ค.
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
}
})
})
`
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
async
์ ๊ธฐ๋ฅ (๋ฐ๋ฒจ)done
๋ํ ํด์.