Jest: ๋งˆ์ง€๋ง‰ ํ…Œ์ŠคํŠธ๊ฐ€ ์™„๋ฃŒ๋œ ํ›„ Jest ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋˜์ง€ ์•Š์Œ

์— ๋งŒ๋“  2016๋…„ 08์›” 18์ผ  ยท  60์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: facebook/jest

๋งˆ์ง€๋ง‰ ํ…Œ์ŠคํŠธ๊ฐ€ ์™„๋ฃŒ๋œ ํ›„ Jest ํ”„๋กœ์„ธ์Šค๊ฐ€ ์™„๋ฃŒ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ctrl-c๋กœ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฐ•์ œ ์ข…๋ฃŒํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ์ด๋ก ์€ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ์ž๊ฐ€ ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ์ •๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ์ด์ƒ์ ์œผ๋กœ Jest๋Š” ์–ด์จŒ๋“  ์ข…๋ฃŒํ•ด์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํŠนํžˆ firebase-server Firebase๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ๋ชจ๋“  ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•ด ํ•˜๋‚˜ ์ด์ƒ์˜ ์„œ๋ฒ„๋ฅผ ๊ฐ€๋™ํ•ฉ๋‹ˆ๋‹ค. afterEach ์ž‘์—…์—์„œ ๋งˆ์ง€๋ง‰ ํ…Œ์ŠคํŠธ์—์„œ ์ƒ์„ฑ ๋œ ๋ชจ๋“  ์„œ๋ฒ„์— ๋Œ€ํ•ด close ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์ง€๋งŒ์ด ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ Jest ํ”„๋กœ์„ธ์Šค๋Š” ์—ฌ์ „ํžˆ ์ข…๋ฃŒ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด (ํ†ต๊ณผ ๋˜๋Š” ์‹คํŒจ) Jest ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฐ•์ œ๋กœ ์ข…๋ฃŒํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚จ์€ ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๋ฅผ ์ •๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด afterAll ํ›„ํฌ๋ฅผ ์–ป์„ ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ? Jest ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋˜์ง€ ์•Š๋„๋ก ์ •ํ™•ํžˆ ๋””๋ฒ„๊น…ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๊ฐ์‚ฌ.

Enhancement Help Wanted good first issue

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

์ฝ๋Š” ์‚ฌ๋žŒ์ด๋ผ๋ฉด --forceExit ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ์ด ๊ธฐ๋Šฅ์— ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐ŸŽ‰

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

์ง€๊ธˆ ๋‹น์žฅ์€ ๊ทธ๋ ‡๊ฒŒ ํ•  ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค. ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€ ์•Œ์•„ ๋‚ด๊ธฐ ์œ„ํ•ด ๋””๋ฒ„๊ฑฐ (Chrome Inspector)์— ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด ์ž ์žฌ์ ์œผ๋กœ ์›์ˆญ์ด ํŒจ์น˜๋ฅผ ์ ์šฉํ•˜๊ณ  ์ถ”์  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์˜ˆ : Promise.prototype.then ์ฃผ์œ„์— ๋ฌด์–ธ๊ฐ€๋ฅผ ๋ฐฐ์น˜).

๋ชจ๋“  afterEach / after ํ›„ํฌ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์„ ๋•Œ ๋น„๋™๊ธฐ ์ž‘์—…์„ ๊ฐ•์ œ ์ข…๋ฃŒ ํ•  ์ˆ˜์—†๋Š” ์ด์œ ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

ํ•ธ๋“ค์ด ์—†๋‹ค๋ฉด ๊ธฐ์กด ๋น„๋™๊ธฐ ํ”„๋กœ์„ธ์Šค๋ฅผ ์–ด๋–ป๊ฒŒ ์ฃฝ์ผ ์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

ava ์—์„œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ–ˆ๋Š”๋ฐ ๋ฌธ์ œ๊ฐ€๋˜์ง€ ์•Š์•˜๋Š”๋ฐ ๋‹ต์ด ์žˆ์„๊นŒ์š”? Node.js์—์„œ๋Š” process.exit .

์šฐ๋ฆฌ๋Š” ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ์‚ฌ๋žŒ๋“ค์ดํ•ด์•ผ ํ•  ๋•Œ ๋งค๋‹ฌ๋ฆฌ์ง€ ์•Š๊ณ  ์ž์›์„ ์ œ๋Œ€๋กœ ์ข…๋ฃŒํ•˜์ง€ ์•Š์„๊นŒ ๊ฑฑ์ •๋ฉ๋‹ˆ๋‹ค.

cc @dmitriiabramov ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์„ธ์š”?

ํ•œ ๊ฐ€์ง€ ์˜ˆ : ์‹ค์ œ๋กœ Jest ์ž์ฒด๋ฅผ ์ข…๋ฃŒํ•˜์ง€ ์•Š๋Š” ์žฅ๊ธฐ ์‹คํ–‰ ๊ฐ์‹œ์ž ํ”„๋กœ์„ธ์Šค๊ฐ€์žˆ๋Š” Jest์™€ ํ•จ๊ป˜์ด ๋ฌธ์ œ๋ฅผ ๊ฒช์—ˆ์Šต๋‹ˆ๋‹ค. Jest๊ฐ€ ํ…Œ์ŠคํŠธ ์‹คํ–‰ ์ค‘์— ์ž์‚ดํ–ˆ๋‹ค๋ฉด (heh!) ๋‚˜๋Š” ๋ฌธ์ œ๋ฅผ ์•Œ์•„ ์ฑ„์ง€ ๋ชปํ–ˆ์„ ๊ฒƒ์ด๊ณ  ์‚ฌ๋žŒ๋“ค์ด ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋ฉˆ์ถ”๋Š” ๋ฒ„์ „์„ ์ถœํ•˜ํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฐ•์ œ ์ข…๋ฃŒํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•œ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋™์‹œ์— ์‚ฌ๋žŒ๋“ค์ด ํ…Œ์ŠคํŠธ๊ฐ€ ์™„๋ฃŒ๋œ ํ›„ ๋น„๋™๊ธฐ ์‚ฌํ›„ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•˜๊ธฐ ์ „์— ์™„๋ฃŒ ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋Š” after all ํ›„ํฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ๋ฌธ์ œ๋Š” ์ธ์‡„๊ฐ€ ๋๋‚˜๊ธฐ ์ „์— ์ถœ๋ ฅ ์ŠคํŠธ๋ฆผ์„ ์ž๋ฅด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋˜๊ธฐ ์ „์— ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ธ์‡„ ํ•  ์‹œ๊ฐ„์ด ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์„ ๋•Œ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ๋Š” Jest๊ฐ€ "์ผ๋ถ€ ํ…Œ์ŠคํŠธ๊ฐ€ ์ž์ฒด์ ์œผ๋กœ ์ •๋ฆฌ๋˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€"๋ผ๊ณ  ๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค.

after all ํ›„ํฌ๊ฐ€ ์—ฌ๊ธฐ์—์„œ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์ง€๋งŒ ๋ฌธ์„œ์—์„œ ๊ทธ๋Ÿฐ ๊ฒƒ์„ ๋ณด์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค ( afterEach ). ๋ˆ„๋ฝ ๋œ ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์˜ฌ๋ฐ”๋ฅธ ์ •๋ฆฌ ํ…Œ์ŠคํŠธ์™€ ๊ด€๋ จํ•˜์—ฌ _files_๊ฐ€ ์ œ ์‹œ๊ฐ„์— ์™„๋ฃŒ๋˜์—ˆ๋Š”์ง€ ํ…Œ์ŠคํŠธ ํ•  ์ˆ˜ ์žˆ๊ณ  ๋ฌธ์ œ๋ฅผ ๊ฒฉ๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด bisect ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”์ง€ ํ…Œ์ŠคํŠธ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€ (์˜ˆ : rspec).

์ข‹์•„, ๋” ๋งŽ์€ ์กฐ์‚ฌ๋ฅผ ํ•œ ํ›„์— ์ด๊ฒƒ์€ Firebase ์ž์ฒด์— ๋ฌธ์ œ๊ฐ€์žˆ๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ด๋ฉฐ process.exit ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ ์™ธ์—๋Š” ์ •๋ฆฌํ•  ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค.

์ž์›:

๋ชจ๋“  ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์—๋Š” process.exit ์ˆ˜๋™์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. Jest ์ปจํ…์ŠคํŠธ์—์„œ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๋‘๋ ต์Šต๋‹ˆ๋‹ค. ์–ด๋””๋กœ ์ „ํ™”๋ฅผ ๊ฑธ์ง€์— ๋Œ€ํ•œ ๊ถŒ์žฅ ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚ด ์ฒซ ์ƒ๊ฐ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์•˜์Šต๋‹ˆ๋‹ค.

afterAll(() => setTimeout(() => process.exit(), 1000))

โ€ฆ Jest๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ชจ๋“  ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰ ๋œ ํ›„ 1 ์ดˆ๋ฅผ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์ด ์‹œ๊ณ„ ๋ชจ๋“œ์— ์–ด๋–ค ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ๋งž๋‹ค๋ฉด Jest๋Š” ์˜ˆ์ƒ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š์„ ์ˆ˜์žˆ๋Š” ๋ฉ‹์ง„ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” Jest์—์„œ ์ˆ˜์ •ํ•ด์•ผ ํ•  ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ์ด๊ฒƒ์ด ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ํ’‹๊ฑด์ฒ˜๋Ÿผ ๋ณด์ธ๋‹ค๋ฉด Jest์— ๋„ฃ๋Š” ๊ฒƒ์€ ์–ด๋–จ๊นŒ์š”? ๋˜๋Š” ์ตœ์†Œํ•œ "๊ฒฝ๊ณ "๋ชจ๋“œ์™€ "์ข…๋ฃŒ"๋ชจ๋“œ ์‚ฌ์ด๋ฅผ ์ „ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” mocha์™€ ์œ ์‚ฌํ•˜๊ฒŒ ํ…Œ์ŠคํŠธ๊ฐ€ ์™„๋ฃŒ ๋  ๋•Œ ์ž๋™์œผ๋กœ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋‹ซ๋Š” --exit ํ”Œ๋ž˜๊ทธ ๋˜๋Š” ๋ฌด์–ธ๊ฐ€ (ํŒŒ์ผ ๋ณ„ ์ฃผ์„ ๋˜๋Š” ๋ฌด์–ธ๊ฐ€๊ฐ€ ๋  ์ˆ˜ ์žˆ์Œ)๋ฅผ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ํ…Œ์ŠคํŠธ ํŒŒ์ผ์—์„œ ๋ชจ๋“  ์—ฐ๊ฒฐ์„ ์ˆ˜๋™์œผ๋กœ ๋‹ซ๋Š” ๊ฒƒ์€ ์•ฝ๊ฐ„ ์„ฑ๊ฐ€์‹  ์ผ์ž…๋‹ˆ๋‹ค.

Codeship์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ drone.io ์—์„œ๋„
ํ•˜์ง€๋งŒ ๋กœ์ปฌ์—์„œ๋Š” ์ œ๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

ํŽธ์ง‘ํ•˜๋‹ค:

  • Jest ๋ฒ„์ „ : 15.1.1
  • ์ง€์—ญ :

    • ๋…ธ๋“œ : 6.2.2

    • npm : 3.9.5

  • CodeShip :

    • ๋…ธ๋“œ : 6.5.0

    • npm : 3.10.3

  • Drone.io

    • ๋…ธ๋“œ : 0.10.26

    • npm : 1.4.3

Firebase๋ฅผ ๊ณ ์ณ์•ผ ํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

--forceExitAfterTestRun ๋ผ๋Š” ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ์˜ˆ์•ฝ์ด ์—†์œผ๋ฉฐ ์‰ฝ๊ฒŒ ์ถ”๊ฐ€ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—์„œ ์ข…๋ฃŒํ•˜๋ ค๋ฉด ๋ณ€๊ฒฝํ•ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. https://github.com/facebook/jest/blob/master/packages/jest-cli/src/cli/index.js#L41 ๊ฒฐ๊ณผ.

์ผ์ข…์˜ ๊ฒฝ์Ÿ ์กฐ๊ฑด ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋•Œ๋กœ๋Š” ๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ๋กœ์ปฌ์—์„œ ์‹คํ–‰ ํ•œ ํ›„ ์ข…๋ฃŒ๋˜๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ์˜ ๋Œ€์‹  ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” API ์‚ฌ์–‘์— Jest๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ•œ ํ›„์—๋„์ด ์ž‘์—…์„ ์‹คํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค (๋ฏธ์•ˆํ•˜์ง€๋งŒ ์Šค๋ƒ… ์ƒท์€์ด ์ž‘์—…์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค). ๋‚˜๋Š” ์—ฐ๊ฒฐ์„ ์ •๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด afterAll ํ›„ํฌ๋ฅผ ์ถ”๊ฐ€ ํ•œ ํ›„์—๋„ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ๋Š”๋ฐ, ์ด๋Š” ๋””๋ฒ„๊น…ํ•˜๊ธฐ ๊ฐ€์žฅ ์‰ฌ์šด ๊ฒƒ์ด ์•„๋‹ˆ๋ผ setupFiles ์˜ ๋‚ด ์กฐ๋ช…๊ธฐ ์ธ๊ตฌ์™€ ๊ด€๋ จ์ด ์žˆ๋‹ค๊ณ  ๋ฏฟ๊ฒŒํ•ฉ๋‹ˆ๋‹ค.

Jasmine์—๋Š” --forceexit ์˜ต์…˜์ด์žˆ๋Š” ๊ฒƒ ๊ฐ™์•„์„œ ๋น„์Šทํ•œ ๊ฒƒ์ด Jest์— ์ฐฉ๋ฅ™ํ•˜๋”๋ผ๋„ ๋ถˆํ‰ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค .๐Ÿ™

๋˜ ๋‹ค๋ฅธ ๋ฌธ์ œ-ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•˜๋ฉด afterAll() ๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์•„๋ฌด๊ฒƒ๋„ ์ •๋ฆฌ๋˜์ง€ ์•Š๊ณ  ์•„๋ฌด๊ฒƒ๋„ ๋‹ซํžˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. --bail ์ด (๊ฐ€)์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ์•„์ง ์‹œ๋„ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

๋ˆ„๊ตฌ๋“ ์ง€ PR์„ ๋ณด๋‚ด๊ณ  ์‹ถ๋‹ค๋ฉด ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ ๋„์›€์„ ์ค„ ์ˆ˜์žˆ๋Š” ๊ฒƒ์ด๋ฉฐ ์ด์ „ ์˜๊ฒฌ์— ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ์„ค๋ช…ํ–ˆ์Šต๋‹ˆ๋‹ค. :)

์ฃผ๋ง์— ์‹œ๊ฐ„์ด ์žˆ์œผ๋ฉด ํ•œ ๋ฒˆํ•ด๋ณผ ๊ฒŒ์š”. ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๊ทธ ์ „์— ๊ทธ๊ฒƒ์„ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๊ทธ๊ฒƒ์€ ๋ฉ‹์ง€๋‹ค : ๋ฏธ์†Œ :

๋ฐฉ๊ธˆ ์—ด๋ฆฐ PR์— ์ฐฌ์„ฑํ•˜์—ฌ ๋งˆ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋…ผ์˜๋ฅผ ๊ณ„์†ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฝ๋Š” ์‚ฌ๋žŒ์ด๋ผ๋ฉด --forceExit ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ์ด ๊ธฐ๋Šฅ์— ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐ŸŽ‰

Google ์ง์›์˜ ๊ฒฝ์šฐ : Jest๋Š” Jenkins CI์—์„œ ์ข…๋ฃŒ๋˜์ง€ ์•Š์ง€๋งŒ ๋กœ์ปฌ์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. --forceExit ์‹ค์ œ๋กœ ์ €๋ฅผ ์œ„ํ•ด ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋ฅผ ์œ„ํ•ด ๊ทธ๊ฒƒ์€ .then (() => {})์™€์˜ ์•ฝ์† ์ฒ˜๋ฆฌ๋ฅผ ์žŠ์—ˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์•„์ง๋„ ์ด๊ฒƒ์œผ๋กœ ๊ณ ๊ตฐ๋ถ„ํˆฌํ•˜๊ณ ์žˆ๋‹ค. async ๋ฐ await API๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ต์Šคํ”„๋ ˆ์Šค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์—ฐ๊ฒฐํ•˜๊ณ  ์—”๋“œ ํฌ์ธํŠธ๋ฅผ pingํ–ˆ์ง€๋งŒ ํ…Œ์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. mongodb์™€ ์„œ๋ฒ„์— ๋Œ€ํ•œ ์—ฐ๊ฒฐ์„ ๋‹ซ์œผ๋ ค๊ณ ํ–ˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ์—ด๋ ค ์žˆ์Šต๋‹ˆ๋‹ค. ๋นˆ json ๋งŒ ๋‹ค์‹œ ๋ณด๋‚ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ œ ๊ฒฝ์šฐ์—๋Š” ์ด๊ฒƒ์ด Firebase ๋ฌธ์ œ๋กœ ๋๋‚ฌ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ

afterAll(() => {
  firebaseApp.database().goOffline();
  firebaseApp.delete();
});

ํŠธ๋ฆญ์„ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‘ ์ค„์ด ์‹ค์ œ๋กœ ํ•„์š”ํ•˜๋ฉฐ ์›๋ž˜ .initializeApp() ์—์„œ ์–ป์€ ๊ฒƒ๊ณผ ๋™์ผํ•œ firebaseApp ์„ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

forceExit์—†์ด์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

Jest 23์—๋Š” Jest๊ฐ€ ์ข…๋ฃŒ ํ•  ์ˆ˜์—†๋Š” ์ด์œ ์˜ ์†Œ์Šค๋ฅผ ๊ฐ€๋ฆฌ์ผœ ์•ผํ•˜๋Š” --detectOpenHandles ๋ผ๋Š” ํ”Œ๋ž˜๊ทธ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

--detectOpenHandles๋Š” mongoose.connect ๋ฐ mongoose.model์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. afterAll์—์„œ mongoose.disconnect๋ฅผ ์‹œ๋„ํ•˜๋ฉด mongo ์˜ค๋ฅ˜ ํ† ํด๋กœ์ง€๊ฐ€ ํŒŒ๊ดด๋ฉ๋‹ˆ๋‹ค.

screenshot 2018-06-08 11 14 51
screenshot 2018-06-08 11 14 29

@elkhan ์ด ๋ชฝ๊ตฌ์Šค ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„ ๋ƒˆ์Šต๋‹ˆ๊นŒ?

--detectOpenHandles ์ถ”๊ฐ€ํ•˜๋ฉด Jest๊ฐ€ ๋‚ด ํ…Œ์ŠคํŠธ๋ฅผ ์™„๋ฃŒ ํ• ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์‹ค์ œ๋กœ Jest๋ฅผ ์ฐจ๋‹จํ•˜๋Š” ์ด์ƒํ•œ ๊ฒƒ์„ ํ‘œ์‹œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฒ„๊ทธ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

๋‚˜๋ฅผ ์œ„ํ•ด --forceExit ๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋™์‹œ์— --detectOpenHandles ํ•˜์ง€๋งŒ ์•„๋ฌด๊ฒƒ๋„ ๊ฐ์ง€ํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค (๋กœ์ปฌ ๋ฐ CircleCI ๋ชจ๋‘). ๋‚˜๋Š” ๋˜ํ•œ --runInBand ์‹คํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค.

๋‚˜๋ฅผ ์œ„ํ•ด --runInBand ์ œ๊ฑฐํ•˜๋ฉด ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

--forceExit ๋Š” shippable์„ ์‚ฌ์šฉํ•  ๋•Œ๋„ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค ... --detectOpenHandles ์‹œ๋„ํ–ˆ์ง€๋งŒ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค์ง€ ์•Š์•˜๊ณ  ๋นŒ๋“œ๊ฐ€ ์ค‘๋‹จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

--detectOpenHandles ์ถ”๊ฐ€ํ•˜๋ฉด ๊ธฐ์ด ํ•œ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

๋…ธ๋“œ : v8.12.0
Jest : v23.6.0

--detectOpenHandles ๋˜๋Š” --forceExit ํ•ด๋„ Codeship์—์„œ ์‹คํ–‰ํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

jest --ci --verbose --forceExit --detectOpenHandle

๋…ธ๋“œ : v8.12.0
Jest : v23.6.0

@sibelius ์ด ๋ฌธ์ œ๋ฅผ ํ”ผํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋ชจ๋ธ์˜ init ํ•จ์ˆ˜๋ฅผ ์Œ์†Œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

const mongoose = require('mongoose');

mongoose.Model.init = () => {};

์ธ๋ฑ์Šค๊ฐ€ ์ƒ์„ฑ๋˜์ง€๋Š” ์•Š์ง€๋งŒ Jest๊ฐ€ ๋ชจ๋ธ์— ๋Œ€ํ•ด ๋ถˆํ‰ํ•˜๋Š” ๊ฒƒ์„ ๋ง‰์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

db.collection("test-collection").add({
    title: 'post title',
    content: 'This is the test post content.',
    date: new Date(),
})
    .then(docRef => {
        console.log('Document written with ID: ', docRef);
    })
    .catch(error => {
        console.error('Error adding document: ', error);
    });

jest --forceExit --detectOpenHandle ํ…Œ์ŠคํŠธ๋Š” ํ†ต๊ณผํ–ˆ์ง€๋งŒ .then ๋˜๋Š” .catch ๋Š” ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค !!
์–ด๋–ค ์•„์ด๋””์–ด?

@alexpchin ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    beforeAll(async (done) => {
        dbConnection = await mongoose.connect(...)
        done()
    })

    afterAll(async (done) => {
        await dbConnection.close()
        dbConnection.on('disconnected', done)
    })

NestJ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ

afterAll(() => {
  app.close();
});

์ด ๋ฌธ์ œ๋Š” ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋ถ€์กฑํ•œ jest ํ”„๋กœ์„ธ์Šค๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค. --maxWorkers=10 ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š”์ด ์›์ธ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์žˆ๋Š”๋ฐ ์•„๋งˆ๋„์ด ๋ฌธ์ œ์— ๋Œ€ํ•ด ๊ถ๊ธˆํ•ดํ•˜๋Š” ์‚ฌ๋žŒ์ด ๋‚ด๊ฐ€ ๊ฐ€์ง„ ์ด์œ ๋ฅผ ๊ฐ€์ง€๊ณ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋‚˜๋Š” Travis ๋‚ด์—์„œ Jest๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ NodeJS ์•ฑ์„ ํ…Œ์ŠคํŠธํ•˜๊ณ  ์žˆ์—ˆ๊ณ  travis๋Š” Jest ์งํ›„ ์‹œ๊ฐ„ ์ดˆ๊ณผ๊นŒ์ง€ ๊ณ„์† ์ค‘๋‹จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. Jest๊ฐ€ ๋‹ซํžˆ์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
๋งŽ์€ ์‹œ๋„ ๋์— JSDom๊ณผ ํ•จ๊ป˜ ๋†๋‹ด์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค.
jest.config.js ํŒŒ์ผ์— ๋‹ค์Œ ์ค„์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  'testURL': 'http://localhost/',

์ด๋กœ ์ธํ•ด JSDom์ด๋กœ๋“œ๋˜๊ณ  ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋‹ซํžˆ์ง€ ์•Š๊ณ  Jest๊ฐ€ ์œ ์ง€๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ค„์„ ์ œ๊ฑฐํ•˜์—ฌ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Jest๋Š” ๋‹ค์Œ ์˜ค๋ฅ˜๋กœ ์‹คํŒจ ํ•ฉ๋‹ˆ๋‹ค .

SecurityError: localStorage is not available for opaque origins

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด jest.config.js ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

  'testEnvironment': 'node',

๋ˆ„๊ตฌ์—๊ฒŒ๋‚˜ ๋„์›€์ด๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ๋‚˜๋Š”์ด ์›์ธ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.์ด ๋ฌธ์ œ์— ๋Œ€ํ•ด ๊ถ๊ธˆํ•ดํ•˜๋Š” ์‚ฌ๋žŒ์ด ๋‚ด๊ฐ€ ๊ฐ€์ง„ ์ด์œ ๋ฅผ ๊ฐ€์ง€๊ณ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋‚˜๋Š” Travis ๋‚ด์—์„œ Jest๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ NodeJS ์•ฑ์„ ํ…Œ์ŠคํŠธํ•˜๊ณ  ์žˆ์—ˆ๊ณ  travis๋Š” Jest ์งํ›„ ์‹œ๊ฐ„ ์ดˆ๊ณผ๊นŒ์ง€ ๊ณ„์† ์ค‘๋‹จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. Jest๊ฐ€ ๋‹ซํžˆ์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
๋งŽ์€ ์‹œ๋„ ๋์— JSDom๊ณผ ํ•จ๊ป˜ ๋†๋‹ด์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค.
jest.config.js ํŒŒ์ผ์— ๋‹ค์Œ ์ค„์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  'testURL': 'http://localhost/',

์ด๋กœ ์ธํ•ด JSDom์ด๋กœ๋“œ๋˜๊ณ  ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋‹ซํžˆ์ง€ ์•Š๊ณ  Jest๊ฐ€ ์œ ์ง€๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ค„์„ ์ œ๊ฑฐํ•˜์—ฌ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Jest๋Š” ๋‹ค์Œ ์˜ค๋ฅ˜๋กœ ์‹คํŒจ ํ•ฉ๋‹ˆ๋‹ค .

SecurityError: localStorage is not available for opaque origins

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด jest.config.js ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

  'testEnvironment': 'node',

๋ˆ„๊ตฌ์—๊ฒŒ๋‚˜ ๋„์›€์ด๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

--forceExit --detectOpenHandles --maxWorkers = 10

์šฐ๋ฆฌ๋ฅผ ์œ„ํ•ด ํ•ด๋ƒˆ์–ด

๋…ธ๋“œ : 8.11.3
๋†๋‹ด 23.6.0

NestJ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ

afterAll(() => {
  app.close();
});

NestJS ์‚ฌ์šฉ์ž๋ฅผ ์œ„ํ•ด ์—ฌ๊ธฐ์— ๋‚จ๊ฒจ ๋‘์‹ญ์‹œ์˜ค.
NestJS๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์œ„์˜ ๋‹ต๋ณ€์ด ํšจ๊ณผ๊ฐ€ ์žˆ์Œ์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค.
์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

afterAll(async () => {
        await app.close()
    })

๋‚˜๋ฅผ ์œ„ํ•ด ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์€ --forceExit --maxWorkers=10 ์ž…๋‹ˆ๋‹ค (์ €๋Š” [email protected]์„ ์‚ฌ์šฉํ•˜๋Š” Ubuntu 18.04์— ์žˆ์Šต๋‹ˆ๋‹ค)

์ œ ๊ฒฝ์šฐ์—๋Š” NodeJS 10 ๋˜๋Š” 11์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์ง€๋งŒ Node 6 ou Node 8์—๋Š” ์—ฌ์ „ํžˆ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. --detectOpenHandles ์˜ต์…˜์„ ์‚ฌ์šฉํ•  ๋•Œ ์•„๋ฌด๊ฒƒ๋„ ํ‘œ์‹œ๋˜์ง€ ์•Š๊ณ  --forceExit ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์— 1 ๋ช… ๋” (์˜ˆ : @motss ๋ฐ @seanlindo ) _ "Jest๊ฐ€ ํ…Œ์ŠคํŠธ ์‹คํ–‰์ด ์™„๋ฃŒ๋œ ํ›„ 1 ์ดˆ ํ›„์— ์ข…๋ฃŒ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค."_๋Š” --detectOpenHandles ๊ฐ€ ์‚ฌ์šฉ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์—๋งŒ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

[email protected]

ํ…Œ์ŠคํŠธ๋Š” --detectOpenHandles ์—†์ด ์ผ๊ด€๋˜๊ฒŒ ์‹คํŒจํ•˜์ง€๋งŒ --detectOpenHandles ์‹คํ–‰ํ•  ๋•Œ ํ†ต๊ณผํ•˜๊ณ  ์—ด๋ฆฐ ํ•ธ๋“ค์„ ํ‘œ์‹œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋จธ์‹  / ์ปจํ…Œ์ด๋„ˆ์—๋Š” 2 ๊ฐœ์˜ ์ฝ”์–ด๊ฐ€ ์žˆ์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ…Œ์ŠคํŠธ๋Š” maxWorkers=1 ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ถ”๊ฐ€ํ•˜๋ฉด --detectOpenHandles ๋Š” config์—์„œ ํ”Œ๋ž˜๊ทธ์™€ ๋ด / globalConfig๊ฐ€ ์‚ฌ์šฉ --debug ํ”Œ๋ž˜๊ทธ๋Š” detectOpenHandles ๊ฐ’์€ _only_ ์ฐจ์ด์ž…๋‹ˆ๋‹ค ...

with --runInBand --detectOpenHandles ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ด๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ "... did not exit ..."์˜ค๋ฅ˜๋ฅผ ํ‘œ์‹œํ•˜์ง€ ์•Š๊ณ  ํ…Œ์ŠคํŠธ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • jest --maxWorkers=2
  • jest --detectOpenHandles
  • jest --forceExit

์ง€๊ธˆ์€ maxWorkers=2 ๋กœ ์ž‘์—…ํ•˜๊ณ  ์žˆ์ง€๋งŒ ์ด๋Š” ๋ฏธ๋ž˜์— ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ์„์œ„ํ•œ ๋‚ด ๊ด€์ฐฐ์ž…๋‹ˆ๋‹ค.

_Edit : ์ถ”๊ฐ€ ์„ธ๋ถ€ ์ •๋ณด : ์ด๊ฒƒ์€ ๋…ธ๋“œ v8.9.3์„ ์‹คํ–‰ํ•˜๋Š” alpine : 3.7 ์—์„œ ๋„์ปค ์ปจํ…Œ์ด๋„ˆ ์ธ ๋‚ด CI ํ™˜๊ฒฝ์—๋งŒ ์˜ํ–ฅ์„์ค๋‹ˆ๋‹ค. ๋‚ด dev ์ปดํ“จํ„ฐ์—์„œ --maxWorkers=1 ์žฌํ˜„ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค _

์ง€๊ธˆ์ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. --maxWorkers=10 ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ .... ๋‚˜๋Š” ์ด๊ฒƒ๊ณผ ๊ฝค ์˜ค๋žซ๋™์•ˆ ์‹ธ์šฐ๊ณ  ์žˆ์—ˆ๋‹ค (ํŠธ๋ž˜๋น„์Šค CI, ์ž‘์—…๋ณต, ํƒ€์ดํ”„ ์Šคํฌ๋ฆฝํŠธ ์‚ฌ์šฉ).
๊ฒฐ๊ตญ ์ค‘๋‹จ๋˜๊ณ  ์‹คํŒจํ•œ ๋นŒ๋“œ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค (Travis CI์—์„œ๋งŒ).

๋งŽ์€ ์‹œํ–‰ ์ฐฉ์˜ค ๋์—์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ ํ•œ ๊ฒƒ์€ ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•œ ๋ช…์‹œ์ ์ธ ๊ฒฝ๋กœ๋ฅผ ์ถ”๊ฐ€ ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

npm ์Šคํฌ๋ฆฝํŠธ๋กœ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.

   "test": "jest",
    "test:coverage": "npm run test -- --collectCoverage && cat ./src/coverage/lcov.info | coveralls",

๊ทธ๋ฆฌ๊ณ  (travis ci์—์„œ) ๋‹ค์Œ๊ณผ ํ•จ๊ป˜ ์ „๋‹ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

   "test": "jest .*\.test\.ts",
    "test:coverage": "npm run test -- --collectCoverage && cat ./src/coverage/lcov.info | coveralls",

๋‹น์‹ ์€ ๋ ˆ๋“œํ–‡ UBI ์ด๋ฏธ์ง€๋กœ ๊ณ ์ • ํ‘œ์‹œ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ ์žˆ๋Š” ๊ฒฝ์šฐ create-react-app ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค ๋‹น์‹ ์€ ์„ค์ • CI=true ์‹คํ–‰ํ•˜๊ธฐ ์ „์— npm test

2019 ๋…„ 12 ์›”. Travis์—์„œ๋งŒ์ด ๋ฌธ์ œ๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๋Š” ๋กœ์ปฌ์—์„œ ํ†ต๊ณผํ•ฉ๋‹ˆ๋‹ค. @qopqopqop ์˜ ์ˆ˜์ •์ด ๋‚˜๋ฅผ ์œ„ํ•ด ์ผํ–ˆ์Šต๋‹ˆ๋‹ค. Jest ๋ฒ„์ „ 24.9.0 ์‚ฌ์šฉ

ํ”„๋กœ์ ํŠธ์—์„œ ํ›„ํฌ ๋ฐ ํ…Œ์ŠคํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ƒˆ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ์‹œ์ž‘ํ•  ๋•Œ๋งŒ์ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. Jest, testing-library ๋ฐ React hooks๋Š” ๋ชจ๋‘ ์ƒˆ๋กœ์šด ๊ธฐ์ˆ ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋งˆ์ฐฐ์ด์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ”„๋กœ์ ํŠธ๋Š” ์—ฌ์ „ํžˆ ์„œ๋กœ ์ž˜ ์–ด์šธ๋ฆฌ๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šฐ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜๋Š” ํ›„ํฌ๋ฅผ ๋ถ€์ ์ ˆํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๋ฒ„๊ทธ๊ฐ€ ๋งŽ์€ ๊ธฐ๋Šฅ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. :-)

์—ฌ์ „ํžˆ์ด ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๋ฅผ ์ข…๋ฃŒ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ๋ชจ๋“  ์•ฑ์—์„œ npm test ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค. ์–ด๋–ค ๋‹จ์„œ?

@koooge ๊ท€ํ•˜์—๊ฒŒ ์ ํ•ฉํ•˜์ง€ ์•Š์€ ์˜ˆ๋ฅผ ๊ฒŒ์‹œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผ ํ•œ ํ›„ 0์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์ข…๋ฃŒํ•˜๋ ค๋ฉด --watchAll = false๋ฅผ ์ „๋‹ฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
npm ์‹คํ–‰ ํ…Œ์ŠคํŠธ---watchAll = false

์ด๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ผํ–ˆ๋‹ค

Firebase์—์„œ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

afterAll(() => {
    firebase.app().delete();
});

์˜ต์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

--forceExit

https://jestjs.io/docs/en/cli# --forceexit

๊ทธ๋ž˜์„œ์ด ๋ฌธ์ œ๋„ ๋งŒ๋‚ฌ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  async ํ˜ธ์ถœ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜์„ ๋•Œ A worker process has failed to exit gracefully and has been force exited... ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋Š” ๊ฒƒ์€ ์„ฑ๊ฐ€์‹  ์ผ์ด์—ˆ์Šต๋‹ˆ๋‹ค. --detectOpenHandles ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ–ˆ์ง€๋งŒ ์•„๋ฌด๊ฒƒ๋„ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋ช‡ ๊ฐ€์ง€ ์กฐ์‚ฌ ๋์— ๋‚ด ๋ฒ”์ธ์ด Promise.race ๋ผ๋Š” ๊ฒƒ์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค.

๋„ค์ดํ‹ฐ๋ธŒ promise ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ (https://github.com/blend/promise-utils)๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ผ๋ถ€ ์™ธ๋ถ€ API ํ˜ธ์ถœ์„ timeout ์œ ํ‹ธ๋ฆฌํ‹ฐ์— ๋ž˜ํ•‘ํ•ฉ๋‹ˆ๋‹ค. ์ด ์œ ํ‹ธ๋ฆฌํ‹ฐ๋Š” ์ฐจ๋ก€๋กœ ๊ธฐ๋ณธ Promise.race ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ทธ ์ฝ”๋“œ๋ฅผ ๊บผ๋‚ด ๋‚ด ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

it('promise.race', async() => {
  await Promise.race([
    new Promise((res) => setTimeout(res, 10000)),
    Promise.resolve('true')
  ])
})

ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ œํ•œ ์‹œ๊ฐ„ ์„ค์ •์ด ๊ธฐ๋ณธ๊ฐ’์ด๋ผ๊ณ  ๊ฐ€์ •ํ•˜๋ฉด ์œ„์˜ ํ…Œ์ŠคํŠธ๋Š” ํ•ญ์ƒ ๊ฒฝ๊ณ ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

jest ์ด ํ›„๋“œ ์•„๋ž˜์—์„œ ์—ด๋ฆฐ ํ•ธ๋“ค์„ ๊ฐ์ง€ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋ฌด์—‡์ด๋“ ๊ฐ„์—, Promise.race ์˜ํ•ด ์˜๋„์ ์œผ๋กœ ์—ด๋ฆฐ ํ•ธ๋“ค์„ ๊ณ ๋ คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ํ™•์‹คํžˆ ์˜ค ํƒ์ง€ ๋ฒ”์ฃผ์— ์†ํ•ฉ๋‹ˆ๋‹ค. ์ด ์˜ค ํƒ์ง€๊ฐ€ ๊ณ ์น  ์ˆ˜ ์žˆ๋Š”์ง€๋Š” ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ ์•„๋งˆ๋„ ๊ฐœ๋ฐœ์ž ์ค‘ ํ•œ ๋ช…์ด ์ด์— ๋Œ€ํ•œ ๋…์ฐฝ์  ์ธ ํ•ด๊ฒฐ์ฑ…์„ ๊ฐ€์ง€๊ณ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ง€๊ธˆ์€ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์ฒ˜๋Ÿผ --forceExit ๊ณ ์ˆ˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ํŽธ์ง‘ํ•˜๋‹ค:
๋ฐฉ๊ธˆ ์ด๊ฒƒ์„ ๋ฐœ๊ฒฌํ–ˆ๋Š”๋ฐ ์‹ค์ œ๋กœ ๋” ๊นŠ์€ nodejs / v8 ๋ฌธ์ œ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค https://github.com/nodejs/node/issues/24321

Firestore ํ…Œ์ŠคํŠธ์—์„œ ์—ฌ๊ธฐ๋กœ ์˜ค๋Š” ๋‹ค๋ฅธ ์‚ฌ๋žŒ์—๊ฒŒ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

afterAll(async () => {
  // Shut down Firestore, otherwise jest doesn't exit cleanly
  await firestoreInstance.terminate()
});

Apollo & Jest๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—ฌ์ „ํžˆ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์•ˆํƒ€๊น๊ฒŒ๋„ --detectOpenHandles ์˜ต์…˜์ด ๊ฒฐ๊ตญ ์ข…๋ฃŒ ๋˜๋”๋ผ๋„ ํ”„๋กœ์„ธ์Šค๋Š” ๊ณ„์†ํ•ด์„œ ๋ช‡ ์ดˆ ๋™์•ˆ ๋ณด๋ฅ˜๋ฉ๋‹ˆ๋‹ค (์ด๋ฆ„๊ณผ ๋ชจ์ˆœ๋จ : ์•„์ง ์—ด๋ ค์žˆ๋Š” ํ•ธ๋“ค์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค!).

--forceExit ํ•˜๋ฉด ์ž‘์—…์ด ์ˆ˜ํ–‰๋˜์ง€๋งŒ ์งœ์ฆ์Šค๋Ÿฝ๊ฒŒ ์ธ์‡„๋ฉ๋‹ˆ๋‹ค.

Jest ๊ฐ•์ œ ์ข…๋ฃŒ :> ๋ชจ๋“  ํ…Œ์ŠคํŠธ๊ฐ€ ์™„๋ฃŒ๋œ ํ›„์—๋„ ๊ณ„์† ์‹คํ–‰๋˜๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์„ ๊ฐ์ง€ํ•˜๊ธฐ ์œ„ํ•ด --detectOpenHandles ์‚ฌ์šฉ์„ ๊ณ ๋ คํ•ด ๋ณด์…จ์Šต๋‹ˆ๊นŒ?

๋‚ด๊ฐ€ ์ฐพ์€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ teardown ๋ฅผ jest.config.js์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

globalTeardown: '<rootDir>/__tests__/teardown.js',

teardown.js์—์„œ๋Š” process.exit๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

module.exports = async function () {
    console.log('done!');
    process.exit(0);
}

๋‚˜๋Š” ๋˜ํ•œ์ด ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ ๊ณ ์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? forceExit: true . --forceExit --detectOpenHandles --maxWorkers=10 ์€ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

https://github.com/atom-ide-community/atom-ide-base/pull/33

ํŽธ์ง‘ : ๋‹ค๋ฅธ ๊ณณ์—์„œ ๋ฌธ์ œ. ๋‚ด๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ํ…Œ์ŠคํŠธ ๋Ÿฌ๋„ˆ์— ์žˆ์Šต๋‹ˆ๋‹ค ...

@ ์•Œ๋ฃจ์‹œ ์ฝ”๋“œ
์ด๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ž‘๋™ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค npm test --watchAll=false
๊ทธ๋Ÿฌ๋‚˜ package.json ํŒŒ์ผ์— --watchAll=false ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ‘

์ฒ˜๋Ÿผ

"test": "react-scripts test a jest --ci --reporters=default --reporters=jest-junit --watchAll=false"

๊ณต์‹ ๋ฌธ์„œ : https://jestjs.io/docs/en/cli.html# --watchall

firebase๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์ง€๋งŒ ์›Œํฌ ํ”Œ๋กœ ์Šคํฌ๋ฆฝํŠธ์—์„œ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋งค๊ฐœ ๋ณ€์ˆ˜์—†์ด jest ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ผ๋ถ€ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ข…๋ฃŒ๋˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ --runInBand --detectOpenHandles ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ํ•˜๋‚˜๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  ํ…Œ์ŠคํŠธ์˜ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค (btw --detectOpenHandles ๋ฌธ์ œ๊ฐ€์žˆ๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ์ง€ ์•Š์Œ).
๊ทธ๋ž˜์„œ ๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๋‚˜์”ฉ ํ™•์ธํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‘ ํ…Œ์ŠคํŠธ์—์„œ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ ํ•  ๋•Œ await ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์žŠ์—ˆ์Šต๋‹ˆ๋‹ค.
๊ธฐ๋‹ค๋ฆผ ์ถ”๊ฐ€ ํ›„ ์ˆ˜์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค. --detectOpenHandles ๊ฐ€ ๋ฌธ์ œ๋ฅผ ์ธ์‡„ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ •์ƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€๋Š” ์•Š์ง€๋งŒ.

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