jest test에서 import 를 못 쓰네요?

노요셉·2019년 10월 23일
13

jest에서 import 구문을 쓰니 에러가 발생합니다.

  ● Test suite failed to run

    /Users/yosephnoh/Documents/dev/im14-2019-07-toy-problems/37-numberToEnglish/NTE.test.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import vm from "vm";
                                                                                                    ^^

    SyntaxError: Unexpected identifier

      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:579:25)

레퍼런스에서 jest.config.js라는 jest 설정파일을 설정해두는 것을 알게 되었어요.
그래서 babel-jest를 설치하길래 babel jest를 키워드로 구글링해보니 공식문서가 나오네요.

공식문서에서 하라는데로 다음과 같은 여러 패키지를 설치해줄게요.
yarn add --dev babel-jest @babel/core @babel/preset-env

그리고
jest.config.js github이란 키워드로 구글링하면서
설정이 많이 되어있는 코드를 찾고, 각각의 필드를 jest 공식문서에서 찾아서 사용하려고 합니다.

module.exports = {
    moduleFileExtensions: ["js", "json", "jsx", "ts", "tsx", "json"],
    transform: {
        '^.+\\.(js|jsx)?$': 'babel-jest'
    },
    testEnvironment: 'node',
    moduleNameMapper: {
        '^@/(.*)$': '<rootDir>/$1'
    },
    testMatch: [
        '<rootDir>/**/*.test.(js|jsx|ts|tsx)', '<rootDir>/(tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx))'
    ],
    transformIgnorePatterns: ['<rootDir>/node_modules/']
};
  • transform
  • testEnvironment
    테스트 환경을 명시할건가봐요. 기본적으로 jsdom이래요.
    Node.js환경에서 테스트하는 거면 node 라고 명시하라네요.
  • transformIgnorePatterns
    정규표현식에 매칭되는 파일은 transform 이 되지 않는다고 하네요.
  • testMatch
    Jest가 테스트 파일을 찾을때 쓰인데요.
    (default: [ "/tests//.[jt]s?(x)", "**/?(.)+(spec|test).[jt]s?(x)" ])
    tests 폴더에 .js,.jsx,.ts,.tsx로 끝나거나, 파일이름 뒤에 .test, .spec 붙는 것들도 포함시키라는 의미래요.
  • moduleNameMapper
  • moduleFileExtensions
    Option moduleFileExtensions is needed when working with TypeScript. The only thing it is doing is telling Jest which file extensions you can import in your files without making precise the file extension
    왼쪽에서 오른쪽으로 적힌 순서대로
    Jest가 file extension이 정확한 file extension 없이도 import 를 할 수 잇게 해준다네요?

이해가 안되는 부분들은 계속 업데이트해야겠어요..

그래도 해결이 안되요.. jest뭐지..

 npm run jest 37-numberToEnglish/NTE.test.js

> immersive-toy-problems@1.0.0 jest /Users/yosephnoh/Documents/dev/im14-2019-07-toy-problems
> cross-env jest "37-numberToEnglish/NTE.test.js"

 FAIL  37-numberToEnglish/NTE.test.js
  ● Test suite failed to run

    /Users/yosephnoh/Documents/dev/im14-2019-07-toy-problems/37-numberToEnglish/NTE.test.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import vm from "vm";
                                                                                                    ^^

    SyntaxError: Unexpected identifier

      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:579:25)

구글링 해보면 다들 babel.config.js도 같이 설정을 해줘야 한대요.
Babel은 create-react-app에서 본 것 같은데요. 왜 이게 제 환경에서 필요할까요?

현재 제 상황은 jest에서 import statement를 쓰고싶어요.
그래서 "jest es6" 키워드로 검색을 해보니 babel하고 많이 나와서 babel을 검색해봤어요.

Babel은 간단하게 요약하면요.
Babel은 ES6+ 코드를 ES5 이하의 버전으로 트랜스파일링합니다.
(ES6이상) js -> (ES5이하)js

Babel 설정까지만 해주면 jest에서도 es6 이상의 문법을 사용할 수 있습니다.

해결한 방법

제가 한 방법을 요약해보면요.
필요한 패키지를 설치합니다.
yarn add --dev babel-jest @babel/core @babel/preset-env

프로젝트 루트디렉토리에 jest.config.js를 만들고
jest.config.js를 다음과 같이 설정했어요.

module.exports = {
    moduleFileExtensions: ["js", "json", "jsx", "ts", "tsx", "json"],
    transform: {
        '^.+\\.(js|jsx)?$': 'babel-jest'
    },
    testEnvironment: 'node',
    moduleNameMapper: {
        '^@/(.*)$': '<rootDir>/$1'
    },
    testMatch: [
        '<rootDir>/**/*.test.(js|jsx|ts|tsx)', '<rootDir>/(tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx))'
    ],
    transformIgnorePatterns: ['<rootDir>/node_modules/']
};

babel.config.js가 .babelrc와 비슷한 녀석인것 같아요. 지금은 jest가 우선이라..
일단 넘어가겠습니다.

프로젝트 루트디렉토리에 babel.config.js를 만들고

module.exports = {
    "presets": ["@babel/preset-env"]
}

테스트가 동작은 되네요.

image.png

레퍼런스 : Jest tests can't process import statement - vue-cli
레퍼런스 : Using TypeScript - GatsbyJS
레퍼런스 : Babel과 Webpack을 이용한 ES6 환경 구축 - poimaweb

추가내용

toy-problem이 mocha로 되어있어서 jest로 바꾸게 되었어요.

그러면서 알게된 것들이 있어서 정리를 하게되었습니다.

node.js로 import를 사용할 수 없어요.

세팅을 해줘야해요.

크게 두가지 방법이 있습니다.

  • node로 바로 실행하기
  • 바벨로 트랜스파일 해서 트랜스파일된 파일을 노드로 실행하기

node로 바로 실행하기

node 파일명.js 로 실행하잖아요. 이렇게 babel-node를 통해 트랜스파일을 만들지 않고 바로 실행 방법입니다.
1. 미리 필요한 패키지를 설치합니다.

yarn add @babel/node @babel/preset-env @babel/core

in package.json

  "devDependencies": {
    "@babel/core": "^7.6.4",
    "@babel/node": "^7.6.3",
    "@babel/preset-env": "^7.6.3"
  },
  
    "scripts": {
	...,
    "babel": "babel-node"
  },
  1. babel.config.js 설정하기!
    프로젝트 루트 디렉토리에 babel.config.js를 만들어서 다음과 같이 해주세요.
    요거 사용법은요 아래 공식홈페이지에서 보시면 설명이 친절하게 나와있습니다.
    레퍼런스 : Configuring Babel - Babel
module.exports = {
    "presets": [
        "@babel/preset-env"
    ]
}
  1. import 할 js파일과 import 될 js 파일을 만들게요.
    a.js, b.js

a.js

export function print1() {
    console.log("export print1 is working");
}

function print2() {
    console.log("non-export print2 is working");
}

print1();
print2();

b.js

import "./a.js";

출력결과

npm run babel src/b.js

> babel-node "src/b.js"

export print1 is working
non-export print2 is working

이 것은 import를 사용할때 babel을 적용하는데 중점을 두고 설명하고 있습니다.
import 방식이나 export 방식에 대해서는 MDN에서 찾아보시면 됩니다.

이렇게 node로 import 를 사용할 수 있게 되었습니다.

사실 이런거 왜 쓰냐에 대한 의문에 대한 제 답은
가장 좋은 답은요. 그냥 js파일에서요 import 써보세요. 에러가 날겁니다. 그래서 구글링을 통해서 방법을 찾으시면 더 이해가 잘 될겁니다.

레퍼런스 : NodeJS로 ES6 코드 실행하기 - DaleSeo
레퍼런스 : Using Babel - babeljs.io
레퍼런스 : @babel/cli - babeljs.io
레퍼런스 : @babel/node - babeljs.io

바벨로 트랜스파일 해서 트랜스파일된 파일을 노드로 실행하기

  1. 미리 필요한 패키지를 설치합니다.
yarn add @babel/node @babel/preset-env @babel/core @babel/cli

다음과 같이 프로젝트가 구성되어있습니다.

-lib
-src
	-a.js
    -b.js
-babel.config.js
-package.json
  1. npm script에 babel을 사용할 수 있게 수정해줍니다.
    in package.json
  "scripts": {
  	...
    "build": "babel src -d lib",
    ...
  },

src 디렉토리에 파일에 babel을 적용해서요 트랜스파일된 파일들을 lib 디렉토리에 넣어달라 라는 의미입니다.

그리고 node <트랜스파일된 파일>을 실행합니다.
물론 실행할 수 있는 방법은 너무 다양합니다. 그런 방법중 하나 일 뿐입니다.

  1. 트랜스 파일을 합니다
npm run build

> babel src -d lib

Successfully compiled 2 files with Babel.

그 결과 lib 디렉토리에 바벨로 인해 트랜스파일된 것을 확인할 수 있습니다.

-lib
	-a.js
    -b.js
-src
	-a.js
    -b.js
-babel.config.js
-package.json

레퍼런스 : BabelJS(바벨) - 제로초 블로그

더 살펴봐야할 것들

jest.config.js 각각의 필드들 살펴봐야되고요.
babel에 대해서도 좀 더 살펴봐야겠어요.

틀린 내용이 있을 수 있습니다. 꼭 피드백 남겨주셔서 공유가 되길 바랍니다.

profile
서로 아는 것들을 공유해요~

3개의 댓글

comment-user-thumbnail
2019년 10월 24일

너무 쉽게 잘 설명해주셔서 항상 감사합니다. express도 연재 부탁드립니다.

답글 달기
comment-user-thumbnail
2021년 8월 10일

엄청 헤매고 있었는데 쉽게 설명해주셔서 해결했습니다. 감사합니다.

답글 달기
comment-user-thumbnail
2024년 1월 5일

친절한 설명 감사합니다.
도움이 많이 됐네요

답글 달기