๊ธฐ๋ฅ ์ ์์ฒญํ๊ฑฐ๋ ๋ฒ๊ทธ๋ฅผ๋ณด๊ณ ํ์๊ฒ ์ต๋๊น? ๊ณค์ถฉ
ํ์ฌ ํ๋์ ๋ฌด์์ ๋๊น?
์ฃผ์ด์ง ํ์ผ ํธ๋ฆฌ :
src/app/modules
โโโ module1
โย ย โโโ index.js
โย ย โโโ __tests__/
โโโ module2
โย ย โโโ index.js
โย ย โโโ __tests__/
modules
๋๋ ํ ๋ฆฌ ์ธ๋ถ์ ๋ชจ๋์ ๋๋ ํ ๋ฆฌ ์ด๋ฆ์ผ๋ก ๊ฐ์ ธ ์์ ์ฌ์ฉํฉ๋๋ค.
import Module1 from '../modules/module1';
import Module2 from '../modules/module2';
module1
๋ฐ module2
๋ฅผ ์กฐ๋กฑ ํ ์ ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ๊ทธ๋ฌ๋, ๋๋ ์์ฑํ๋ ๊ฒฝ์ฐ src/app/modules/module1/__mocks__/index.js
๋ฐ src/app/modules/module2/__mocks__/index.js
, ๋๋ ์ฃผ์ด์ง์์ด duplicate manual mock found
์์ ์ค๋ฅ๋ฅผ jest-haste-map
.
๊ทธ๋ฌ๋ src/app/modules/__mocks__/{module1.js,module2.js}
๋ฅผ ๋ง๋ค๋ ค๊ณ ํ๋ฉด ๋ชจ์ ํ์ผ์ด ์ฌ์ฉ๋์ง ์์ต๋๋ค.
ํ์ฌ ๋์์ด ๋ฒ๊ทธ ์ธ ๊ฒฝ์ฐ ์ฌํ ๋จ๊ณ๋ฅผ ์ ๊ณตํ๊ณ ๊ฐ๋ฅํ๋ฉด npm install
๋ฐ npm test
ํ ์์๋ GitHub์ ์ต์ ์ ์ฅ์๋ฅผ ์ ๊ณตํ์ธ์.
์์ ๋์์ ์ฐธ์กฐํ์ญ์์ค.
์์๋๋ ๋์์ ๋ฌด์์ ๋๊น?
์ฒซ ๋ฒ์งธ ๊ฒฝ์ฐ๋ ๋ค๋ฅธ ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ๊ณ ๋ ๋ฒ์งธ ๊ฒฝ์ฐ๋ ๋ชจ๋์ ๊ฒฝ๋ก ์ด๋ฆ์ ์ฌ์ฉํ๋ค๋ ์ ์ ๊ฐ์ํ ๋ ๋ ๋ฐฉ๋ฒ ๋ชจ๋ ์๋ ํ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค.
--debug
Jest๋ฅผ ๋ค์ ์คํํ๊ณ ์ธ์๋๋ ์ ์ฒด ๊ตฌ์ฑ์ ์ ๊ณตํฉ๋๋ค.
๋
ธ๋ v6.2.0
npm v3.8.9
OS X 10.11.6
> NODE_ENV=test jest --env jsdom "--debug" "src/app/redux/modules/devices"
jest version = 17.0.0
test framework = jasmine2
config = {
"moduleFileExtensions": [
"js",
"json"
],
"moduleDirectories": [
"node_modules"
],
"moduleNameMapper": [
[
"^.+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$",
"/Users/paul/dev/tools/jest/mock-assets.js"
],
[
"^.+\\.css$",
"identity-obj-proxy"
]
],
"name": "dev",
"setupTestFrameworkScriptFile": "/Users/paul/dev/tools/jest/setup-framework.js",
"testPathDirs": [
"/Users/paul/dev/src"
],
"testRegex": "/__tests__/.*\\.test\\.js$",
"timers": "fake",
"rootDir": "/Users/paul/dev",
"setupFiles": [],
"testRunner": "/Users/paul/dev/node_modules/jest-jasmine2/build/index.js",
"testEnvironment": "/Users/paul/dev/node_modules/jest-environment-jsdom/build/index.js",
"transform": [
[
"^.+\\.jsx?$",
"/Users/paul/dev/node_modules/babel-jest/build/index.js"
]
],
"usesBabelJest": true,
"automock": false,
"bail": false,
"browser": false,
"cacheDirectory": "/var/folders/dm/vt920lmd6tzdq_709zkykwx40000gn/T/jest",
"coveragePathIgnorePatterns": [
"/node_modules/"
],
"coverageReporters": [
"json",
"text",
"lcov",
"clover"
],
"expand": false,
"globals": {},
"haste": {
"providesModuleNodeModules": []
},
"mocksPattern": "__mocks__",
"modulePathIgnorePatterns": [],
"noStackTrace": false,
"notify": false,
"preset": null,
"resetMocks": false,
"resetModules": false,
"snapshotSerializers": [],
"testPathIgnorePatterns": [
"/node_modules/"
],
"testURL": "about:blank",
"transformIgnorePatterns": [
"/node_modules/"
],
"useStderr": false,
"verbose": null,
"watch": false,
"cache": true,
"watchman": true,
"testcheckOptions": {
"times": 100,
"maxSize": 200
}
}
jest-haste-map: duplicate manual mock found:
Module name: index
Duplicate Mock path: /Users/paul/dev/src/app/modules/push-notification-manager/__mocks__/index.js
This warning is caused by two manual mock files with the same file name.
Jest will use the mock file found in:
/Users/paul/dev/src/app/modules/push-notification-manager/__mocks__/index.js
Please delete one of the following two files:
/Users/paul/dev/src/app/modules/image-file/__mocks__/index.js
/Users/paul/dev/src/app/modules/push-notification-manager/__mocks__/index.js
No tests found
1 file checked.
testPathDirs: /Users/paul/dev/src - 1 match
testRegex: /__tests__/.*\.test\.js$ - 0 matches
testPathIgnorePatterns: /node_modules/ - 1 match
+1
์ ๊ฒฝ์ฐ์๋ cacheDirectory
/ var / folders / dm / vt920lmd6tzdq_709zkykwx40000gn / T / jest๋ฅผ ์ง์ฐ๊ณ npm ์ข
์์ฑ์ ๋ค์ ์ค์นํ๋ฉด ์ด๋ฌํ ๋ฉ์์ง๊ฐ ์ฌ๋ผ์ก์ต๋๋ค.
๋ค์์ ๋ฌธ์ ๊ฐ๋๋ ์ฝ๋์ ๋๋ค.
๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ํ์ธํ๋ ํ ์คํธ๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋์์ด ๋ช ์ ์ ์ผ๋ก ์ํ ์ ์์ต๋๋ค.
์ถ๊ฐ ๋ ํญ๋ชฉ :
https://github.com/facebook/jest/commit/cfade282fbbe2737b6dd2cee1cf3da3ee8624512
์ ์ฒด ๊ฒฝ๋ก๊ฐ ์๋ basename
ํค๋ก ์ฌ์ฉํ๋ ์ด์ ๊ฐ ๊ถ๊ธํฉ๋๋ค.
/ cc @flarnie
์ฆ, ์๋ ๋ชจ์๋ฅผ ์ฌ์ฉํ ๋ ๋ชจ๋์ ๋ํ basename
๋ ํ๋ก์ ํธ์์ ์ ์ญ ์ ์ผ๋ก ๊ณ ์ ํด์ผํฉ๋๋ค. ๋ด ์ฌ์ฉ ์ฌ๋ก์ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ ์์
์ ํ ์ ์์์ ์๋ฏธํฉ๋๋ค.
import { MyWhatever } from 'models/MyWhatever/schema';
import { MyOtherWhatever } from 'models/MyOtherWhatever/schema';
๋์์ ์๋ ๋ชจ์๋ฅผ ์ฌ์ฉํฉ๋๋ค. Jest๋ ํ์ฌ ๋ ๋ค schema
๋ฅผ ์กฐ๋กฑํ๊ณ ๋ถํํ๋ ๊ฒ์ผ๋ก๋ณด๊ณ ์์ต๋๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ฌ์ํ ๊ฒ (s / schema / MyWhateverSchema /)์ด์ง๋ง ํ ์คํธ๊ฐ ์๋ ์ฝ๋์ ์ด๋ฆ์ ๋ฐ๊พธ๊ณ ์ฌ๊ตฌ์ฑํ์ฌ ๋๋ด์ ์ฆ๊ฒ๊ฒํ๋ ๋ฒ๊ทธ์ฒ๋ผ ๋๊ปด์ง๋๋ค .๐.
์, ์ด๊ฒ์ ์ ๋ง ์ง์ฆ๋ฉ๋๋ค. ์๋ ์กฐ๋กฑ ์์คํ ์ ์ ๋ง ์ข์ง ์์ผ๋ฉฐ ์ํฉ์ ๊ฐ์ ํ ์์๋ PR์ ๋ฐ์ ๋ค์ฌ์ ๊ธฐ์ฉ๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋ชจ๋ FB๋ฅผ ๊นจ์ง ์๋๋ก ํ ์ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
๋ฉ์๋. ๋ด์ผ ํจ์น๋ฅผ ์๋ฆฌ ํ ์๊ฐ์ด ์์์ง ๋ชจ๋ฅด์ง๋ง ์ฝ์์ ์์ง๋ง ๐
@cpojer ์ด ๋์์ ๋ํ ํน๋ณํ ์ด์ ๊ฐ ์์ต๋๊น?
fb๊ฐ ๋ชจ๋์ ๊ณ ์ ํ ํ์ผ ์ด๋ฆ์ ์ฌ์ฉํ๋ค๋ ์ฌ์ค๊ณผ ๊ด๋ จ์ด ์์ต๋๊น? ๊ฐ์ ์ด๋ฆ์ ๊ฐ์ง ๋ ๊ฐ์ ๋ชจ์๋ฅผ ํ์ฉํ์ง ์๋ ๊ฒ์ด ์ด๋ป๊ฒ ๋ง์ด๋๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
์, mock๋ "๊ธ๋ก๋ฒ"์ ๋๋ค. ์ด๊ฒ์ ๋ถํํ๋ ์ฐ๋ฆฌ๊ฐ ํจ๊ป ์ด์์ผํ๋ ๋์ฐํ ๋์์ธ์ ๋๋ค. FB์๋ ์๋ชป๋ ์์น์ 4000 ๊ฐ ์ด์์ ๋ชจ์ ํ์ผ์ด ์์ต๋๋ค (๊ทธ๋ฆฌ๊ณ ์ข ์ข ์ ์ ํ ์์น๋ ์์ต๋๋ค). ๋ด๋ ์ด๋ฐ์์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๊ฐ๋ฅ์ฑ์ด ๋์ผ๋ฏ๋ก Jest์์ ๊ฐ์ ๋ ๊ฒ์ ๋๋ค. ์คํ ์์ค ์ฉ Jest์ ๋์์ ๊ฐ์ ํ๋ PR์ ์ง์ํ๊ฒ๋์ด ๊ธฐ์ฉ๋๋ค. ํ์ฌ FB์์ Jest์ ์ด์ ๋์์ ์ ์งํ ์ ์๋ค๋ฉด ๊ธฐ์ฉ๋๋ค.
@cpojer ๊น๋ฐ์ ์ด๋? ํ๋๊ทธ๋ก ์ด๊ฒ์ ํ์ฑํ / ๋นํ์ฑํํ๋ ํ๋ณด๋ฅผ ์๋ฝ ํ์๊ฒ ์ต๋๊น?
์, ๊ตฌ์ฑ ์ต์ ์ด์ด์ผํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ ๋ ๊ฒฝ๊ณ ์ ๋ํด์๋ง ๋งํ๋ ๊ฒ์ด ์๋๋ผ ์ผ๋ฐ์ ์ธ ๊ธฐ๋ฅ์ ๋ํด์๋ ์ด์ผ๊ธฐํ๊ณ ์์ต๋๋ค.
@cpojer ์ค๋ฅธ์ชฝ-๋๋ด์ ์ด๋ ๋ถ๋ถ์ด์ด ๋ถ๋ถ์ ๋ง์ง๋์?
ํด๊ฒฐ ์ฝ๋๋ jest-runtime : https://github.com/facebook/jest/blob/master/packages/jest-runtime/src/index.js ์์ ํธ์ถ๋๋ฉฐ jest-resolve ๋ฐ jest-resolve-dependencies ์ด๋๊ฐ์ ์์ต๋๋ค. .
@cpojer ํฌ์ธํฐ ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค : +1 :
@cpojer ์ด ๋์์ ์ ํํ๊ธฐ ์ํด JEST_USE_BASENAME_FOR_CACHING
์ ๊ฐ์ ์ ์ญ ์ฌ์ ์๋ ์ด๋ป์ต๋๊น?
์ ์ด๋ ์ฐ๋ฆฌ๋ ๊ณ ์ ํ์ง ์์ ํ์ผ ์ด๋ฆ์ ์ฆ๊ธธ ์ ์์ผ๋ฉฐ FB์์ ์ด๋ค ๊ฒ๋ ๊นจ์ง์ง ์์ต๋๋ค.
๋ฌผ๋ก ์ผ์์ ์ธ ํด๊ฒฐ์ฑ ์ ๋๋ค.
๋ด ๋ง์, ์ด๊ฒ์ /etc/profile
๋๋ ~/.bashrc
export JEST_USE_BASENAME_FOR_CACHING="true"
(๋๋ env๊ฐ์๋ ์ผ๋ถ ํ์ผ)
๊ทธ๋ฆฌ๊ณ
$ jest
๋๋ ์ด๊ฒ์ env ํ์ผ ์์ ์์ด :
$ JEST_USE_BASENAME_FOR_CACHING="true" jest
์ด๋ป๊ฒ ์๊ฐํ์ธ์? ์ผ์ข ์ ํดํน์ ๋๊น, ์๋๋ฉด ๊ด์ฐฎ์ต๋๊น? :๋์ง:
๋ ๊ฐ์ง ๋ฒ์ ์ jest ( ^15.0.0
๋ฐ ^17.0.0
)๋ฅผ ์ฌ์ฉํ์ฌ ์ repo ๋ฅผ ์ฌ์ฉํด ๋ณด์์ต๋๋ค. ํ์๋ ๊ฒฝ๊ณ ๋ฅผ ํ์ํ์ง๋ง ํ
์คํธ๋ ์์๋๋ก ์๋ํฉ๋๋ค.
@ColCh ์ฌ๊ธฐ์ ๋ฌธ์ ๊ฐ ์บ์์ ์๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ์๋ง๋ ๋ ์ ํฉํ ์ด๋ฆ์ JEST_USE_BASENAME_FOR_MOCKING
์์ต๋๋ค.
FB ์ฝ๋์ ์ด๋ฆ์ ๊ณ ์ ์ฑ์ ๋ํ ์ ํ์ด์๋ ๊ฒฝ์ฐ @cpojer , ์ ์ฒด ๊ฒฝ๋ก๋ฅผ ๋ชจ์ ๋งต์ ํค๋ก ์ฌ์ฉํ๋ฉด ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์์ต๋๋ค.
๋ด๊ฐ ๋ง์ต๋๊น, ์๋๋ฉด ๋ณด์ด์ง ์๋ ๊ฒ์ด ์์ต๋๊น?
๋ด๊ฐ ๋ณด๋ ๋ ๊ฐ์ง ์๋ฃจ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
getMockName
์์ @cpojer ๋ต๋ณ์ ๋ณด๋ ๊ฒ์ด ์ข์ ๊ฒ์ ๋๋ค.
์๋ ํ์ธ์ ์ฌ๋ฌ๋ถ, ์ง์ฐ๋์ด ์ฃ์กํฉ๋๋ค. ์ ๋ ์ง๊ธ ๋ง์ ์๋ฃ๋ฅผ ๋ฐฑ์ ํ๊ณ ์์ต๋๋ค.
์ด ์์คํ
์ ๊ฐ์ ํ๋ ๋ฐ ํ์ํ Jest์ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ ๋ฌด์์ด๋ ํ๊ธฐ๋ก ๊ฒฐ์ ํด๋ ๊ด์ฐฎ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์๋ ์กฐ๋กฑ์ ์ ๋ง ์๋ง์ด๊ณ ์ ์๋ํ์ง ์์ต๋๋ค. ์ฐ๋ฆฌ๊ฐํ๊ณ ์ถ์ ํ ๊ฐ์ง๋ "haste_modules": ['path/a', 'path/b']"
์ ๊ฐ์ ๊ตฌ์ฑ ์ต์
์ ์ฌ์ฉํ์ฌ "haste modules"(๋ด๋ถ FB ๋ชจ๋ ์์คํ
)์ ๋ฒ์๋ฅผ ์ ํ ํ ๋ค์์ด ์ด์ํ ์กฐ๋กฑ์ ํฌํจํ์ฌ ํด๋น ํด๋์์๋ haste ๋ชจ๋ ๋ง ์ดํด ๋ณด๋ ๊ฒ์
๋๋ค. ํ๋. ๋๊ตฌ๋ ์ง์ด ๋ณํ๋ฅผ ๋ง๋ค๊ณ ์ถ๋ค๋ฉด ๊ทธ๊ฒ์ ๋๋์ต๋๋ค.
์์ ๋ด์ผ ํ ํ ๊ฐ์ง๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. __mocks__/a.js
๊ฐ a.js
๋งคํ๋๋ ๊ฒ์ฒ๋ผ ๋ชจ๋ ์๋ ๋ชจ์๊ฐ ๋ก์ปฌ์ด๋ฉด node_module ๋ชจ์๋ก ๋ฌด์์ํ ๊น์? ์ด๋ฅผ ์ํด ๋ช ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
__node_modules_mocks__
ํด๋๋ฅผ ์๊ฐํฉ๋๋ค.rootDir
(ํ๋ก์ ํธ ๋ฃจํธ)์์ ํ์๋๋ ์ต์์ __mocks__
ํด๋๋ ์ ์ญ ํด๋ ์ญํ ์ ํ ์ ์์ต๋๋ค.์์ฝํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
["<rootDir>"]
์ฒ๋ผ ๋ณด์ผ ๊ฒ์
๋๋ค).์ด๋ป๊ฒ ์๊ฐํด?
์์๋๋ก :
๋ง์ธ : ๋ฏธ์ :: ๋ฐ๋ค :
์๋๋ฌ ์๊ตฌ ์ฌํญ์ ์ดํดํ๊ณ ์๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๋น์ ์ด ์๋ฏธํ๋ ๊ฒ์ "์ด ๋ชจ๋์ ์๋๋ฌ ๋ชจ๋์ด๋ค"๋ผ๊ณ ๋งํ ์์๋ ๊ฐ๋ฅ์ฑ์์ฃผ๋ ๊ฒ์
๋๊น?
4 ๊ฐ์ ๋ชจ๋ : /path_1/a
, /path_1/b
, /path_2/a
, /path_2/c
์ด๊ณ ์ค์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
"haste_modules:" ["/path_1/a", "/path_2/c"]
/path_1/a
๋ฐ /path_1/b
๋ง /path_1
์๋ง ์กด์ฌํ๋๋ก ์ ํ๋๋ฏ๋ก /path_2/c
๋ ์ ํจํ๋ฉฐ /path_2/a
๋ ์ค๋ฅ / ๊ฒฝ๊ณ ๋ฅผ ๋ฐ์์ํต๋๋ค.
ํ๊ฒ์ ์ฑ๊ธ / ๋๋ธ *
ํ๋๋ผ๋ ํน์ ํ์ผ๊ณผ ์ ์ฒด ๋๋ ํ ๋ฆฌ๊ฐ ๋ ์ ์์ต๋๋ค.
๋๋ ํ์ฌ์ ํ๋์ ์ ์งํ ๊ฒ์ ๋๋ค.
๋ชจ์ํ๋ ๋ชจ๋์ด ๋ ธ๋ ๋ชจ๋ (์ : fs) ์ธ ๊ฒฝ์ฐ ๋ชจ์๋ node_modules ํด๋์ ๋์ผํ ์์ ๋๋ ํ ๋ฆฌ์ ์์ด์ผํฉ๋๋ค.
๋ด ์๊ฐ:
haste_modules
์ด ์ข๋ค๊ณ ์๊ฐํฉ๋๋ค. collectCoverageFrom
๋ฐ ๊ธฐํ ์ต์
: glob ๋ฐฐ์ด ๊ณผ ๋๊ฐ์ด ์ ํฉํฉ๋๋ค.
๋ชจ๋ src
๋ฅผ _haste_ ๋ชจ๋๋ก ๊ฐ์ง๊ณ ์๊ณ ํ๋์ ๋๋ ํ ๋ฆฌ ๋ง ๋น ํค์ด์คํธ ์ธ ๊ฒฝ์ฐ :
haste_modules: [
"src",
"!src/foo"
]
@EnoahNetzach ๋๊ตฐ๊ฐ๊ฐ
์๋๋ฅด์ง ์๊ณ ์๋ํ๋ ค๋ฉด ... ์, ๋ค์๊ณผ ๊ฐ์ด ์ค๋ช ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
์ฃผ์ด์ง ๋ ธ๋ ๋ชจ๋
project/node_modules/react
, mock์project/__node_modules_mocks__/react.js
project/react.js
ํ์ผ์ด์๋ ๊ฒฝ์ฐproject/__mocks__/react.js
(๋ฌผ๋ก react.js
๊ฐ ์์
๋๋ค. ์ฌ๊ธฐ์๋ ๋ชจ๋ ๋ชจ๋ ์ค ์ด๋ค ํ์ผ ์ด๋ฆ๋ ๊ฐ๋ฅํ๋ฉฐ npm ์์ ์ค์นํ ์ ์์ต๋๋ค)
์ ๋ง๋ก, node_modules ๋ชจ๋์ ์กฐ๋กฑํ๋ node_modules ์กฐ๋กฑ์ ๊ฒฝ์ฐ _ugliness_๋ฅผ ๋ณด์ ํ ์ ์์ต๋๊น?
node_modules ๋ด๋ถ์ ๋ชจ๋์ ์์ฃผ ์กฐ๋กฑํ๋ ์ฌ๋์ด ์์ต๋๊น?
๋ด๊ฐ ์ ๋ค์ํผ ๋ฐ์ ๋ค์ดํฐ๋ธ ํ๋ก์ ํธ์ ๊ฒฝ์ฐ application modules
๋ฅผ ๋ชจ์ ์ฒ๋ฆฌํ๊ณ node_modules์ ๋ชจ๋์ lodash
).
์ด๊ฒ์ ๋ค์์ ์๋ฏธํฉ๋๋ค.
jest.mock
ํธ์ถ์ ๊ธด ๋ชฉ๋ก__ ๋ด๊ฐ ๋งํ๊ณ ์ถ์ ๊ฒ __ : ์ผ๋ถ ๊ฒฝ๋ก์์ ๋ชจ๋์ _auto mock_ํ๋ ๊ธฐ๋ฅ์ด ์์ผ๋ฉด ๋งค์ฐ ์ข์ ๊ฒ์ ๋๋ค.
config์์ ์ ์๋ ค์ง ๋ฐ์ดํฐ ๊ตฌ์กฐ array-of-jest-globs ๋ฅผ ์ค์ฌ์ผ๋ก ๊ตฌํํ ์ ์์ผ๋ฉฐ ๋ชจ๋์ ํํฐ๋ง ํ ์ ์์ต๋๋ค.
๋จ๊ณ๋ณ๋ก ์ค๋ช ํ๊ฒ ์ต๋๋ค.
์ด ๊ตฌ์ฑ ํญ๋ชฉ์ด ์ฃผ์ด์ง๋ฉด
"autoMockingPaths": [
"src/components/dumb/**/*.js",
]
์ด ์ฝ๋๋ src/screens/app.js
.
import _ from 'lodash';
import Button from '../../components/dumb/button.js';
// blah blah AppScreen implementation skipped
src/screens/__tests__/app-test.js
ํ๋ฉด์ ๋ํ์ด ํ
์คํธ ์ฝ๋ :
import AppScreen from '../app.js';
describe('AppScreen', () => /* testing app screen */);
์ฐ๋ฆฌ๋ app-test.js
๋งฅ๋ฝ์์์ด ์ํฉ์ ๋๋ฌํ์ต๋๋ค.
AppScreen
์ (๋) ์กฐ๋กฑ๋์ง ์์์ต๋๋ค.lodash
์ (๋) ์กฐ๋กฑ๋์ง ์์์ต๋๋ค.Button
์ ํ์ํ, AppScreen
, ์กฐ๋กฑ๋๊ณ ... automock
๊ตฌ์ฑ ํญ๋ชฉ์ผ๋ก ์ด๋ป๊ฒ ์ฌ์๋๋์ง ๋๋ต ํ ์ ์์ต๋๋ค.
๊ฐ๋จํ ๋งํ๋ฉด automock: true
๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
"autoMockingPaths": [
"<rootDir>"
]
automock
๋ํ ํน๋ณํ ๊ฐ์น๋ฅผ ์๊ฐ ํ ์ ์์ต๋๊น? ์ ์ด๋ ์ฌ๋๋ค์ ๊ตฌ์ฑ์ ๊นจ์ง ์์ ๊ฒ์
๋๋ค.
์๋ฅผ ๋ค์ด ๋ค์ ๊ตฌ์ฑ ํญ๋ชฉ์ ์ฌ์ฉํฉ๋๋ค.
automock: "app"
jest๋ ๋ชจ๋ ์ ํ๋ฆฌ์ผ์ด์
๋ชจ๋์ ์๋์ผ๋ก ๋ชจ์ํ๊ณ node_modules
๋ถํฐ ๋ชจ๋์ ์ค์ ๋ฒ์ ์ ๋จ๊น๋๋ค.
์ฑ ๋ ๋ฒจ ๋ชจ๋ automocking, @cpojer ์ ๋ํด ์ด๋ป๊ฒ ์๊ฐ
"haste_modules"
์ ์ ์ผ๋ก ๋์ํฉ๋๋ค.
์ฐ๋ฆฌ๋ ๊ฐ์ธ์ ์ผ๋ก automocking์ ๋ง์ด ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ฌด์์ด ๋ ์ข์์ง ๋งํ ์ ์์ต๋๋ค. ๋ด ์ถ์ธก์ "autoMockingPaths"
var๊ฐ ์ ์ฉํ๊ณ ํ๋ ฅ์ ์ผ ์ ์๋ค๋ ๊ฒ์
๋๋ค.
๋ฐ๋๋ก ๋ด๊ฐ ์ฐพ์ ์ "automock": "app"
๋๋ฌด ๋ปฃ๋ปฃํ (๊ธฐ๋ณธ์ ์ผ๋ก ๋๋ด ์ด๋ฏธ ์ฅ์ ์ธ automocking์).
__node_modules_mocks__
๋ ์ต์
์ด ๋ ์ ์์ต๋๋ค. ์ ๋ ํฌ์ ํจ์ด ์ถ์
ํจ์ ๋ณด์ํ๋ค๋ ๋ฐ ๋์ํฉ๋๋ค (์ ์ ํน๋ณํ ๊ฒฝ์ฐ์๋ ๊ฑฐ์ node_modules
์กฐ๋กฑํ๋ ์ผ์ด ๊ฑฐ์ ์์ผ๋ฉฐ,ํด์ผ ํ ๋ jest.mock(...)
).
์ ์ผํ์ฃผ์ ์ฌํญ์ ์ค์ฒฉ ๋ node_modules
ํด๋ (์ : src/node_modules
)๊ฐ์์ ๋ ๋ฐ์ํ๋ ์ผ์ด๋ฉฐ, ์ค์ฒฉ ๋ ๋ฒ์ ์ธ ์ ์ญ __node_modules_mocks__
์์ ๋ชจ๋์ ๋ชจ์ํด์ผํฉ๋๊น? ๋๋ ์ผ๋ฐ์ ์ผ๋ก __mocks__
ํจ๊ป ๋ฐฐ์น๋ฉ๋๊น?
๋๊ตฐ๊ฐ node_modules
์ app modules
๊ฐ์ ๋ชจ๋ ์ด๋ฆ์ ๊ฐ์ง๊ณ ์๋ค๋ฉด ๊ทธ๋ฅ ๋์ง ์ ์์ต๋๋ค.
์
app/express.js
๋ฅผ ์ฑ ๋ชจ๋๋ก ์ฌ์ฉ (๋ด๊ฐ ๊ธฐ์ฐจ ๊ฒ์์ํ๊ณ ์์ ์ ์์)
npm์์ ์น ์๋ฒ๋กapp/node_modules/express
throw new Error("can't mock express.js file - it duplicates one from node_modules")
์ด ๊ฒฝ์ฐ __mocks__
๋ฅผ node_modules
์ ์ฌ์ฉํ ์ ์์ง๋ง ๊ฐ๋ฐ์๋ ์ด๋ฌํ ์ถฉ๋์ ๋ํด ์์ฒด ๋ชจ๋์ ์ด๋ฆ์ ๋ณ๊ฒฝํด์ผํฉ๋๋ค.
์๋ ... ์ด๊ฑด __node_modules_mocks__
๋ณด๋ค ๋ ๋ชป ์๊ฒผ์ง?
๋ด๊ฐ ์๋ฏธํ๋ ๋ฐ๋ : npm install
ed ๋ชจ๋ x
์ด์์ด์๋ ๊ฒฝ์ฐ ์ฝ๋๋ฒ ์ด์ค์ ๋ ๊น์ ๊ณณ์์ ์ค์ฒฉ ๋ node_modules
ํด๋์ x
๋ชจ๋์ ์ ์ํฉ๋๋ค. ?
๋ช ๋ช ์ถฉ๋์ ์ผ๋ฐ์ ์ผ๋ก ๊ฐ์ฅ ๊ฐ๊น์ด ๋ ธ๋๋ฅผ ์ ํธํ์ฌ ๋ ธ๋์์ ์ฒ๋ฆฌ๋์ง๋ง ์ด๊ฒ์ด ์ด๋ป๊ฒ ์๋๋ฌ ์๋ํ๋์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
Create React App ๊ณผ ๊ฐ์ ํ๋ก์ ํธ์์ ์ฌ์ฉ ์ค์ด๊ฑฐ๋ ๊ฐ๊น์ด ์ฅ๋์ ํ ์์ ์ด๊ธฐ ๋๋ฌธ์์ด ๋ฌธ์ ๋ฅผ ์ ๊ธฐํ์ต๋๋ค.
์ฐธ๊ณ ๋ก @cpojer ๋์ด ๋ฌธ์ ์ ๊ด๋ จ์ด ์์ต๋๊น?
์๋๋ฌ ์๋ ๋ฐฉ์์ ๋ณ๊ฒฝํ๋ ๋ฐ ์ค์ ์ ๋๋๋กํ๊ฒ ์ต๋๋ค (๊ธฐ๋ณธ ์ค์ ์ด ์๋ ํ์ดํธ๋ฆฌ์คํธ / ๋ธ๋๋ฆฌ์คํธ). ๋๋ <rootDir>/__mocks__
์ด ๋
ธ๋ ๋ชจ๋ ๋ชจ์ ๊ธฐ๋ณธ๊ฐ์ด์ด์ผํ๋ค๊ณ ์ ์งํ๊ณ ์ถ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ด๋ฅผ ๊ตฌ์ฑ ์ต์
์ผ๋ก ๋ง๋ค ์๋ ์์ต๋๋ค : "globalMocks"๊ธฐ๋ณธ๊ฐ์ <rootDir>/__mocks__
์
๋๋ค. ๋๊ตฌ๋ ์ง ์ด๊ฒ์ ๋ํด ๊ธฐ๊บผ์ด ๋
ธ๋ ฅํฉ๋๊น?
๋ค์ ์ฃผ๋ง๋ณด๋ค ๋นจ๋ฆฌ์ด ์์ ์ ์ํ ํ ์์์ ๊ฒ์ ๋๋ค.
๋๋ ์ด๋ฒ ์ผ์์ผ์ PR ์์ ์ ํ ์์์ด, ๋๋ ์ข ์์ ๋กญ๋ค
์์ฝํ๊ธฐ ์ํด @cpojer- <rootDir>/__mocks__
๊ธฐ๋ณธ๊ฐ์ผ๋ก globalMocks
๊ตฌ์ฑ ํญ๋ชฉ์ ๋ง๋ญ๋๋ค. ์ด ์ต์
์ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ์ฌ jest ๋ด์์ node-haste
์ฌ์ฉ์ ๊ท์ ํฉ๋๋ค. ์๋๋ฉด ๊ฒฝ๋ก์ ๋ฐฐ์ด์ผ๊น์?
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ์ํ ๋ ํฐ ๋ณํ๋ผ๊ณ ์๊ฐํ์ง๋ง, ๋จ์ globalMocks ์ต์ (๋ฌธ์์ด ๋๋ ๋ฌธ์์ด ๋ฐฐ์ด ์ผ ์ ์์)๊ณผ haste ๋ชจ๋ ๊ฒฝ๋ก ๋ฐฐ์ด ์ธ hasteModules ์ต์ ์ด ๋ชจ๋ ํ์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ด ์ฝ๋์ ๋๋ถ๋ถ์ jest-haste-map ๋ฐ jest-resolve์ ์์ต๋๋ค. ์ฌ๋ฐ๋ฅธ ์๋ฃจ์ ์ด ์์ง ์ด๋ค ๋ชจ์ต ์ผ์ง 100 % ํ์ ํ์ง ๋ชปํฉ๋๋ค.
๋ณด๋ธ ์ฌ๋ : Max Sysoev [email protected]
์ ์ก : 2016 ๋
12 ์ 9 ์ผ ๊ธ์์ผ ์ค์ 8:18:44
๋ฐ๋ ์ฌ๋ : facebook / jest
์ฐธ์กฐ : Christoph Pojer; ์ธ๊ธํ๋ค
์ ๋ชฉ : Re : [facebook / jest] [bug] ์ค๋ณต ๋ ์๋ ๋ชจ์๊ฐ ๋ณ๋์ ๋๋ ํ ๋ฆฌ์ ์์ (# 2070)
๋๋ ์ด๋ฒ ์ผ์์ผ์ PR ์์ ์ ํ ์์์ด, ๋๋ ์ข ์์ ๋กญ๋ค
@cpojer https://github.com/cpojer ์์ฝํ๊ธฐ-๊ธฐ๋ณธ๊ฐ์ผ๋ก globalMocks ๊ตฌ์ฑ ํญ๋ชฉ ๋ง๋ค๊ธฐ
-
๋น์ ์ด ์ธ๊ธ ๋์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ฐ๊ณ ์์ต๋๋ค.
์ด ์ด๋ฉ์ผ์ ์ง์ ๋ต์ฅํ๊ฑฐ๋ GitHub https://github.com/facebook/jest/issues/2070#issuecomment-265958606 ์์ ๋ณด๊ฑฐ๋ https://github.com/notifications/unsubscribe-auth/AAA0KAMFc34iKqBDLHZzgaGHqyc3WkAzks5rGQ7kgaJpZM4Kt2DW .
์ฃ์กํฉ๋๋ค. ์ ์ํฌ ์คํ ์ด์ ์ด ๊ณ ์ฅ ๋ฌ๊ณ ๋ช ๋ฌ (1 ~ 2 ๊ฐ์) ์์ ์๋ ํ ๋ฐฉ๋ฒ์ด์๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ด PR์ ๋ํ ํ๋ก์ ํธ๋ ์์ด ๋ฒ๋ ธ์ต๋๋ค.
getMockName
์ ๋์์ ๋ณ๊ฒฝํ๋ ๊ตฌ์ฑ ์ต์
๋๋ด์ ๋ด๋ถ์ ๋๋ฌด ์ต์ํ์ง๋ ์์ง๋ง FB์ ๋ํ ๋๋ด์ ๊นจ์ง ์๊ณ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ฐ์ฅ ๊ฐ๋จํ ํด๊ฒฐ์ฑ
์ธ ๊ฒ ๊ฐ์ต๋๋ค.
์ด๊ฒ์ ์๋ ์๊ฐํ๋ ๊ฒ๋ณด๋ค ๋ ๋ณต์ก ํ ๊ฒ์ ๋๋ค. ๋์๊ฒ ์๋ ๋ชจ์๋ ๊ฐ์ฅ ๊ฐ๊น์ด ํ์ผ์ ๋์ฒดํด์ผํฉ๋๋ค. ์ด ๊ฐ์:
{ 'aws-sdk': '/Users/project/__mocks__/aws-sdk.js',
'slack': '/Users/project/__mocks__/slack.js',
'/Users/project/db/index': '/Users/project/db/__mocks__/index.js',
'/Users/project/slack/index': '/Users/projects/slack/__mocks__/index.js' }
require('aws-sdk')
๋ฐ๋ ํด๊ฒฐํด์ผ /Users/project/__mocks__/aws-sdk.js
์ด๊ฐ์ ๋ํ ๋ชจ์์
๋๋ค node_module
.
require('./db')
(๋๋ db
๋ํ ๋ชจ๋ ๊ฒฝ๋ก)๋ /Users/project/db/__mocks__/index.js
ํฉ๋๋ค.
jest ์๋ ๋ชจ์๋ฅผ ์ค์ ํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋์ ์ดํด๋ (์์ ๊ฐ์ ๊ฒ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์๋ง๋ ๋ ๋ง์ ๋ฌธ์๊ฐ์์ ๊ฒ์
๋๋ค) __mocks__
๋๋ ํ ๋ฆฌ ๋ด์์ ๊ฐ๋ฅํ ํ ๋ชจ์๋๋ ํ์ผ์ ๊ฐ๊น์ ์ผํ๋ค๋ ๊ฒ์
๋๋ค.
์๋ ๋ชจ์๋ ๋ชจ๋ ๋ฐ๋ก ์์์๋ __mocks __ / ํ์ ๋๋ ํ ๋ฆฌ์ ๋ชจ๋์ ์์ฑํ์ฌ ์ ์๋ฉ๋๋ค. (https://facebook.github.io/jest/docs/manual-mocks.html)
์ด๋ฅผ ๊ฐ์ํ ๋ ์์ ํ๋์ด ๊ฐ์ฅ ์๋ฏธ๊ฐ ์์ต๋๋ค.
์๊ฐ?
์ด๊ฒ์ ์์ ๊ฐ์ ๊ฒ์ ๊ตฌํํ๋ ์ด๊ธฐ ๋จ๊ณ์ ๋๋ค : https://github.com/facebook/jest/compare/master...mhahn : issue-2070-new-mock-resolution
๋ ์ด์ ๋ค์๊ณผ ๊ฐ์ ์์ํ "์ด๋ฆ์ด ์ง์ ๋"๋ชจ์๋ฅผ ํ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ถ๋ถ์ jest ๋จ์ ํ ์คํธ๋ฅผ ์ค๋จํฉ๋๋ค. https://github.com/facebook/jest/blob/master/packages/jest-runtime/src/__mocks__/ createRuntime.js
createRuntime
์ ๊ฐ์ IMO๋ ํ
์คํธ ์ ํธ๋ฆฌํฐ ํด๋์ ์์ด์ผํ๋ฉฐ ํ์ํ ํ
์คํธ์์ ๊ฐ์ ธ์์ผํ๋ ํ
์คํธ ์ ํธ๋ฆฌํฐ์
๋๋ค. ์๋ ๋ชจ์๋ก ๊ตฌํ๋๋ ๋ฐฉ์์ ๋ณด์กด๋์ด์ผํ๋ ๊ฒ์ผ๋ก ์ ์๊ฒ ์ดํด๊ฐ๋์ง ์์ต๋๋ค.
ํ ๊ฐ์ง ์ต์ ์ ๊ธฐ์กด ๋์๊ณผ ์์ ๋ณ๊ฒฝ ์ฌํญ์ ์ ๋ฆฌ ํ ๋ฒ์ ์ฌ์ด๋ฅผ ์ ํํ๋ ๊ตฌ์ฑ ๋ณ์๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ๋๋ค. ๋๋ ๊ทธ๊ฒ์ด ๋ฌด์์ ๋ถ๋ฌ์ผํ๋์ง ์ ๋ง๋ก ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
์ฐ๋ฆฌ๋ Facebook์์ ๊ทน๋๋ก ์์กดํ๊ณ ์๊ธฐ ๋๋ฌธ์ ํ์ฌ์ ํ๋์ ๊นจ๋จ๋ฆด ์ ์์ต๋๋ค.
@cpojer ๋์ํฉ๋๋ค. https://github.com/facebook/jest/issues/2070#issuecomment -265027510 ์ฝ๋๋ฅผ ์ฝ์ ํ์ด ์ฃผ์์ ์ค์ ๋ก ์ดํดํ์ง ๋ชปํ์ต๋๋ค. ํ์ฌ ๋์์ ํด๊ฒฐํ ๋๋ ํ ๋ฆฌ ๋ชฉ๋ก์ ํ์ฉ ๋ชฉ๋ก์ ์ถ๊ฐ ํ ์ ์์ต๋๊น?
๋ ๊ฐ์ง ์๋ก์ด ๊ตฌ์ฑ ์ต์ ์ ์ด๋ป์ต๋๊น?
fullPathMockResolution
(๊ธฐ์กด ๋์์ ์ ์งํ๊ธฐ ์ํด ๊ธฐ๋ณธ๊ฐ์ false
)namedMockDirectories
: fullPathMockResolution
๊ฐ ํ์ฑํ๋๋ฉด ํด๋น ๋ฐฐ์ด ๋ด์ ๋ชจ๋ ๋๋ ํฐ๋ฆฌ๊ฐ ๊ธฐ์กด ๋์์ผ๋ก ํ์ธ๋ฉ๋๋ค. FB ์ฌ์ฉ ์ฌ๋ก์ ๊ฒฝ์ฐ ์์์ ์ธ๊ธ ํ ๊ฒ์ฒ๋ผ [<rootDir>]
๋ฉ๋๋ค.์ด๋ฅผ ํตํด ๊ฐ๋ฐ์๋ ์ ์ฒด ๊ฒฝ๋ก ํ์ธ์ ์ ํํ ์ ์์ผ๋ฏ๋ก ๊ธฐ์กด jest ์ค์น์ ์ํ ๋ณ๊ฒฝ์ด ํ์ํ์ง ์์ผ๋ฉฐ ์ํ๋ ๊ฒฝ์ฐ ํน์ ๋๋ ํ ๋ฆฌ์ ๋ํ ๊ธฐ์กด ๋์์ ํ์ฑํ ํ ์๋ ์์ต๋๋ค.
cc @voideanvalue ์ด๊ฒ์ ๋น์ ์ด ์๊ฐํด์ผ ํ ๊ฒ์ ๋๋ค (์๋ก์ด ์๋๋ฌ ๊ตฌํ์ ์ผ๋ถ๋ก ๋ค์ ์คํ์ด์ค ๋งค๋ด์ผ ๋ชจ์).
+1,์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
+1
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์ ๋ฐ์ดํธ๊ฐ ์์ต๋๊น? ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฅด๋ฉด ์ ๋ง ๊ณ ํต ์ค๋ฝ์ต๋๋ค.
project/
โโโ models
โ โโโ index.js
โ โโโ __mocks__/
โ โ โโโ index.js/
โโโ challenges
โ โโโ index.js
โ โโโ __mocks__/
โ โ โโโ index.js/
๊ฒฝ๋ก๋ฅผ ๊ณ ๋ คํด์ผํ๊ธฐ ๋๋ฌธ์ ์ค์ ๋ก ์ถฉ๋ํ๋ ์ด๋ฆ์ด ์๋๋ฐ๋ '์ถฉ๋ํ๋'์ด๋ฆ์ ๊ฐ์ง ๋ ๊ฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ํ ์คํธ์์ ๋ชจ๋์ ์๋์ผ๋ก ๋ชจ์ํด์ผํฉ๋๋ค.
๊ฑด๋ฐฐ,
๋๋ฏธ๋
@cpojer ์ฌ๊ธฐ์ ์ ๋ฐ์ดํธ๊ฐ ์์ต๋๊น? ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
๋๋ฅผ์ํ ์ฝ๊ฐ์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ require๋ก ๋ชจ๋์ ์กฐ๋กฑํ๋ ๊ฒ์ ๋๋ค.
jest.mock('models/index', () => require('models/index/_mocks_/index'));
jest๊ฐ ํ์ผ์ ์ก์ง ๋ชปํ๋๋ก __mocks__
ํด๋ ์ด๋ฆ์ _mocks_
.
์ด๊ฒ์ด ์๋ํ๋ ์ด๋ ๋ _mocks_
์ __mocks__
๋ก ๋ฐ๊พธ๊ณ jest.mock์์ require ๋ถ๋ถ์ ์ ๊ฑฐํฉ๋๋ค.
์ฒซ์งธ, ๋ชจ๋ ๋ฉ์ง ์์
์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค.
๋์งธ : ์ด๊ฒ์ ์ ๋ง, ๋งค์ฐ ์ค๋ง ์ค๋ฝ์ต๋๋ค. ๋ชจ์ ํ์ผ์ด ๋ชจ์๋๋ ์ ์ฒด ์ฝ๋๋ฒ ์ด์ค์ ๋ค๋ฅธ ํ์ผ๊ณผ ์ด๋ฆ์ ๊ณต์ ํ ๋ ํ
์คํธ ํ์ผ์์ jest.mock์ ์ฌ์ฉํด์ผํ๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค. ํธ์ด ์คํ
์ ์ค์ ๋ชจ์ ๊ฐ์ ธ ์ค๊ธฐ๋ ํ์ฉํ์ง ์์ผ๋ฏ๋ก ํด๋น ํ์ผ์ ๋ชจ์ํด์ผํ๋ ๋ ํ
์คํธ์์ ๋ชจ์๋ฅผ ๋ณต์ ํด์ผํ๋ฏ๋ก ํ
์คํธ ์ค์ํธ์ ์ทจ์ฝ์ฑ์ด ์ถ๊ฐ๋ฉ๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๊ณ ํฉ๋๊น? FB๋์ด ๋ฌผ๊ฑด์ ์ฌ์ฉํฉ๋๊น? ๊ทธ๋ ๋ค๋ฉด ์ด๋ป๊ฒ? ๐
์ด ๊ฒฝ๊ณ ๋ฅผ๋ณด๊ณ ๋งค์ฐ ์ค๋ง ์ค๋ฝ์ต๋๋ค. ์์ ์ ๊ธฐ๋ค๋ฆด ์ ์์ต๋๋ค.
๋ด๊ฐ ๊ฐ์ง ๋ฌธ์ ๋ ๊ด๋ จ์ด ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
jest.mock ( 'src / utils / history')๊ฐ ์์ผ๋ฉด 'history'node_module๋ ์๋ชป ์กฐ๋กฑํฉ๋๋ค.
์๋ค ์ ์ด๋ค ์ ๋ฐ์ดํธ?
@masoudcs ๋๋ ์ด๊ฒ์ด ๊ฒฝ๊ณ ๋ฅผ ์ ๊ฑฐํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
package.json
"jest": {
/* other settings ... */
"modulePathIgnorePatterns": ["<rootDir>/node_modules/react-native/Libraries/Core/__mocks__"]
}
modulePathIgnorePatterns
๋ฐฐ์ด์ "์ค๋ณต"ํด๋๋ฅผ ์ถ๊ฐํ๋ฉด ๊ฒฝ๊ณ ๊ฐ ์ฌ๋ผ์ง๋๋ค.
๊ฐ์ฌํฉ๋๋ค @brunolm
๊ทธ๋์ ๊ทธ๊ฒ์ ๋จ์ง ๊ฒฝ๊ณ ์
๋๋ค, ๋ง์ต๋๊น?!
๋๋ ์ด๊ฒ์ด ๋์ ์ผ์ด ์ผ์ด๋์ง ์๋๋กํ๊ณ ์ถ๋ค. ์ฆ, ์ฌ๋ฌ ๋๋ ํ ๋ฆฌ์์ index.js๋ฅผ ์กฐ๋กฑํ๋ ๊ฒ
src/app/modules/module1/__mocks__/index.js
๋ฐ src/app/modules/module2/__mocks__/index.js
๊ทธ๊ฒ ์ค์ํ์ง๋ ๋ชจ๋ฅด๊ฒ ์ง๋ง ์คํ ์ค์๋ ๋ค๋ฅธ ํ๋๋ง ์ ํํ๋ค๊ณ ๋งํ๊ณ ๋ด๊ฐ ๋์ดํ ๊ฒ์ ์ด๋ ์ชฝ์ด๋ ๋ฌด์ํ ๊ฒ์ ๋๋ค.
๊ทธ๋์ ๋ฌด์ํ๋ผ๊ณ ํด๋ ๊ด์ฐฎ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ด์ฐจํผ ์ฌ์ฉํ์ง ์์์ต๋๋ค.
์, ๋ง์ํ์ ๋๋ก, ์ง๊ธ๊น์ง ์๋ฌด๋ฐ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค.
๋ฐ๋ผ๊ฑด๋, ๊ทธ๊ฒ์ํด์ผ ํ ์ผ์ํ๊ณ ์์ต๋๋ค! :)
๊ฐ์ฌ
์ด ๋ง์ง๋ง ๋ ์ปค๋ฐ์ด ์ ์ํ ๊ฒ์ ์๋ํ์ง๋ง ๊ฒฝ๊ณ ๋ฅผ ์ ๊ฑฐํ์ง ์์์ต๋๋ค.
jest.mock('dir/index', () => require('dir/__mocks_/index'));
๋ด ๊ตฌ์ฑ์ testPathIgnorePatterns: ['/_book/', ...otherStuff]
์ด ์์ง๋ง GitBook ( ./_book
๋๋ ํฐ๋ฆฌ)์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์์ด ๊ฒฝ๊ณ ๊ฐ ํ์๋ฉ๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํ์ด ๋ณด๋ฉด์ ๋ช
ํํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ฐพ์ง ๋ชปํ์ต๋๋ค. ๊ฒฝ๊ณ ํ์๋ฅผ ์ค๋จํ๊ณ ์ถ์ต๋๋ค. ์ด๋ค ๋์์ ์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค.
+1
์ด๊ฒ์ ๋ํ ์ ๋ฐ์ดํธ๊ฐ ์์ต๋๊น?
๋ํ ์์์ ์ ์ํ ๋ ๋๋ฌ์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ง ์๊ณ ๋ด ํ ์คํธ ํ์ผ์ ์ ๊ธฐ์ ์ผ๋ก ๊ฐ์ ธ์ฌ ์ ์๋๋ก ์์ ์ฌํญ์ ์ฐพ๊ณ ์์ต๋๋ค.
jest.mock('models/index', () => require('models/index/_mocks_/index'));
์ฐ๋ฆฌ์ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ๋ ์ฌ๊ธฐ๋ฅผ ์ฐธ์กฐ s์ '@dkundel ๊ฐ์ ๋ชจ์ https://github.com/facebook/jest/issues/2070#issuecomment ์ ์์ ์ ๋ค์ ์คํ์ด์ค์์ ๋ชจ๋ธ๊ณผ ๊ตฌ์ฑ ์์์ -301332202 index.js
๊ธฐ๋ณธ ์ธ ์์ถ.
๊ฒฝ๊ณ ๋ฅผ ์นจ๋ฌต ์ํค๊ฑฐ๋ ๋ชจ๋ ๋ชจ์๋ฅผ ํ๋ซ ๋๋ ํ ๋ฆฌ์ ๋์ง์ง ์๋ ๊ฒ์ ์ ํธํฉ๋๋ค. ์ผ๋ถ ๋ชจ์๋ ๊น๊ฒ ์ค์ฒฉ๋์ด ์์ผ๋ฉฐ ์ ์ ๋ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
jest.mock('pages/index/components/Component', () => require('pages/index/components/Component/_mocks_/index'));
์ฐ๋ฆฌ ๊ตฌ์กฐ์์.
ํ๋ง๋?
@karomancer ๊ตฌ์ฑ์ ์ฌ์ฉํ์ฌ ๊ฒฝ๊ณ ๋ฅผ ์ ๊ฑฐ ํ ์์๋ PR # 6037์ ์ ์ถํ์ต๋๋ค. ์์ง์ ๋ณํฉ๋์ง ์์์ต๋๋ค. ๊ธฐ์ฌ์์ ์๋ต์ ๊ธฐ๋ค๋ฆฌ๊ณ ์์ต๋๋ค.
์ด ๋ฌธ์ ๋ ๋งค์ฐ ์ค๋ง ์ค๋ฝ์ง๋ง ๋ ๊น๋ํ ๋ช ๋ช ๊ท์น์ ๋ง๋๋ ์ข์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ฐพ์ ๊ฒ ๊ฐ์ต๋๋ค.
package.json
{
"jest": {
"setupFiles": [
"<rootDir>/test.mocks.ts"
]
}
}
/* test.mocks.ts */
// modules mocked before every test
// use `jest.unmock(...)` to undo for any single test case
const mockedModules = [
"./path/to/module1/index.ts",
"./path/to/module2/index.ts",
];
mockedModules.forEach((path) => {
const mockPath = path.replace(/\.ts$/g, ".mock.ts");
jest.mock(path, () => require(mockPath));
});
์ด๋ ๊ฒํ๋ฉด anything.mock.ts
ํ์ ๋ฅผ ๋ง๋ค๊ณ ์ต์์ test.mocks
์ mockedModules
๋ฐฐ์ด์์ ์๋ณธ ๊ฒฝ๋ก๋ฅผ ์ถ๊ฐํ์ฌ anything.ts
๋ฅผ ๋ชจ์ ํ ์ ์์ต๋๋ค.
์ด ๋ฌธ์ ๊ฐ ๊ฐ์ ์ฌํญ์ผ๋ก ํ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
์ด๊ฒ์ ๋๋ฅผ ์ํด ์ผํ๋ ๊ฒ ๊ฐ์ต๋๋ค. jest.config.js์์ :
module.exports = {
// ...
modulePathIgnorePatterns: ["<rootDir>/.*/__mocks__"]
};
์์ ํ๋ก์ ํธ๊ฐ ์๊ธฐ ๋๋ฌธ์์ด ๋ณ๊ฒฝ์ ๋ฒ์ ๋ ์ํฅ์ ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
@amccloud ๊ฐ์ฌํฉ๋๋ค! ์ด๊ฒ์ ๋ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ต๋๋ค! ์๋ ์ธ๋ถ ์ ๋ณด.
๋ด ํ๋ก์ ํธ ๋ฃจํธ ๋๋ ํ ๋ฆฌ์ helpers
๋ชจ๋์ด ์์ต๋๋ค. ๋์ฐ๋ฏธ๊ฐ parseNodeFromString
ํจ์๋ฅผ ๋ด๋ณด๋ด๊ณ ์์ต๋๋ค.
๋ค๋ฅธ ๋ชจ๋ ๋ก์ปฌ ํ์ผ helpers
์์ ๋ง๋ค์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ํ
์คํธ ์ค ํ๋๋ฅผ ์กฐ๋กฑํ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ parseNodeFromString
ํจ์๋ฅผ ์ฌ์ฉํ๋ ๋ชจ๋ ํ
์คํธ๊ฐ ๋ค์ ์ค๋ฅ์ ํจ๊ป ์คํจํ๊ธฐ ์์ํ์ต๋๋ค.
FAIL src/some_dir/bla/tests/SomeClass.test.js
โ Test suite failed to run
TypeError: (0 , _helpers.parseNodeFromString) is not a function
์ด ๋ฌธ์ ๋ ์ด๋ป์ต๋๊น? @amccloud ์๋ฃจ์ ์ด ์ฌ๋ฐ๋ฅธ ๊ฒ ๊ฐ์ต๋๋ค.
modulePathIgnorePatterns: ["<rootDir>/.*/__mocks__"]
์ด ์๋ฃจ์
์ ๋
ธ๋ ๋ชจ๋์ ๋ํ ์ต์์ ๋ชจ์๊ฐ ์คํจํ๋๋ผ๋ ์๋ํฉ๋๋ค. ๊ทธ๋์ "modulePathIgnorePatterns": ["<rootDir>/src/react/.*/__mocks__"],
๋ฃจํธ __mock__ ํด๋๋ฅผ ๋ฌด์ํ์ง ์๋๋ก ๋ณ๊ฒฝํ์ต๋๋ค. ์ฌ์ ํ mock์ด ๋ฃจํธ์ ์ ์ฒด ๊ฒฝ๋ก ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ณ ์ ํ์ง ์๋ค๋ ๊ฒ์ ๋งค์ฐ ์ด์ํฉ๋๋ค. users/helper.js
& posts/helper.js
๋ ๋งค์ฐ ์ผ๋ฐ์ ์
๋๋ค. ๊ฒฝ๊ณ ๋ ์๋นํ ๊ณต๊ฐ์ ์ฐจ์งํ๋ฉฐ ์ค์ ๊ฒฝ๊ณ ๋ฅผ ์์ ํ ์จ๊ธฐ๊ณ ์ถ์ง ์์ต๋๋ค.
๊ทธ๋ ๋ค๋ฉด PR์ ํ์ฌ ์ํ๋ ๋ฌด์์ ๋๊น? ์ ์ ํ ํด๊ฒฐ์ฑ ์ด๋ ํดํน์ด ์์ต๋๊น?
์ ๊ฒฝ์ฐ์๋ ๋ชจ์ ๋ชจ๋์ด ๋ชจ๋ ๋น๋์ ํจ๊ป Dist ๋๋ ํ ๋ฆฌ์ ๋ณต์ฌ๋์์ต๋๋ค.
์ด๊ฒ์ typescript๊ฐ ๋ ๊น์ dir ๊ตฌ์กฐ์ ์ํ๋ ๊ฒฝ๋ก / ํจํด์ ์ ์ธ ํ ์์๋ ๋ฌธ์ ์ธ ๊ฒ ๊ฐ์ต๋๋ค. ์ฌ์ ํ "typescript@^3.4.5"์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ชจ๋ ํ ์คํธ ์คํ ์ ์ "rimraf dist"๋ก Dist ๋๋ ํฐ๋ฆฌ๋ฅผ ์ฒญ์ํ๊ธฐ ์์ํ์ต๋๋ค.
"test:unit": "npm run clean && stencil test --spec --snapshot",
๋๋ ํดํน์ด๋ผ๋ ๊ฒ์ ์๊ณ ์์ง๋ง ์๋ํฉ๋๋ค.
์ด๋ด ๋ด๊ฐ ์ฌ๊ธฐ์์ ์ผ์ด๋ ์ผ์ ํด๊ฒฐํ์ผ๋ฉฐ ์๋ง๋ ์ด๊ฒ์ ๋ณต์ ํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
์ธ ๊ฐ์ง ์๋ฃจ์ ๋๋ ์๋๋ฆฌ์ค :
1, ํ ์คํธ ํธ์ง๊ธฐ์์ ๋ด ์ฑ์ ๋ ๋ฒ ํธ์งํ์ต๋๋ค. ์ฆ, ๋ ๊ฐ์ ๋ค๋ฅธ ์ฐฝ์์ pod ์ค์น / ์ ๋ฐ์ดํธ ๋ฐ react-native run-ios๋ฅผ ์คํํ์ต๋๋ค. ์ด ์ค๋ฅ๊ฐ ๋ฐ์ํ์ฌ Xcode์ ๋ด ์ฑ์์ ์ค๋ณต ํ์ผ์ ๊ฒ์ํ์ง๋ง ์ฐพ์ ์ ์์์ต๋๋ค. ๊ทธ๋์ ์๋ฎฌ๋ ์ดํฐ์์ ์ฑ์ ์ญ์ ํ๊ณ react-native run-ios๋ฅผ ๋ค์ ์คํํ๋๋ฐ ์๋ํ์ต๋๋ค. ๋ ๊ฐ์ node_modules๊ฐ ๋ด scr ํ์ผ์์ node_modules์ node_modules0๊ณผ ๊ฐ์ด ๋ณต์ ๋ ๊ฒ์ผ๋ก ๋ํ๋ฌ์ต๋๋ค.
2, ๋๋๋ก ๋ด Mac์์ ์์์ ํค๋ฅผ ๋๋ฅด๋ฉด node_modules๊ฐ ์๋ฅผ ๋ค์ด SRC ํด๋์ ๋ณต์ ๋๋ฏ๋ก์ด ๊ฒฝ์ฐ์๋ ๋ง์ฐฌ๊ฐ์ง์ด๋ฏ๋ก ํด๋์์ node_modules ์ค๋ณต์ ์ดํด ๋ณด๋ ๊ฒ์ด ์ข์ต๋๋ค.
3, ๋์ผํ ์๋ฎฌ๋ ์ดํฐ์์ ๋ค๋ฅธ ์ฑ์ ์์ํ๊ณ ์ข ๋ฃ ํ ๋๊น์ง ์ฑ์ ์์ํ ์ ์์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ค๋ณต ๋ ์ฑ์ ์ฌ๋ถํ ํ ๋ค์ ์ค๋ฅ์์ด ์คํ๋์์ต๋๋ค.
์์ง๋ ์๋ฌด๊ฒ๋? CRA์์ modulePathIgnorePatterns๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
3 ๋ 10 ๊ฐ์
๋๋ ๊ฒฝ๊ณ ๋งํ๋ ๊ฒ์ด ์๋๋ผ์ด ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ ๋ Jest๊ฐ ์ค๋ฅ๋ฅผ ๋ฐ์ ์ํค๋๋ก ๊ฐ์ ํ ์ ์๋ค๋ฉด ์ข์ ๊ฒ์ ๋๋ค. ๊ฒฝ๊ณ ๋ ์ฝ๊ฒ ๋ฌด์๋ฉ๋๋ค. ๋ด ํ๋ก์ ํธ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ์ ํธํ๋ฏ๋ก์ด๋ฅผ ๋์ ํ ๊ฐ๋ฐ์๊ฐ ์ฒ๋ฆฌํด์ผํฉ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
์ด๊ฒ์ ๋๋ฅผ ์ํด ์ผํ๋ ๊ฒ ๊ฐ์ต๋๋ค. jest.config.js์์ :
์์ ํ๋ก์ ํธ๊ฐ ์๊ธฐ ๋๋ฌธ์์ด ๋ณ๊ฒฝ์ ๋ฒ์ ๋ ์ํฅ์ ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.