8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

TypeScript + ReactNative + Jest(ts-jest)でテスト環境を作る

Posted at

はじめに

ts-jestの導入に苦戦していたので備忘のために記事を書きます。
初っ端の導入〜サンプルコードを動かすところまで。

node_modulesバージョン

package.jsonで定義したモジュールバージョン抜粋は以下の通り。

package.json
{
	"dependencies": {
		"@types/jest": "^24.0.19", // devDependencies側で良い筈
		"@types/react-native": "^0.57.2",
		// 中略
	},
	"devDependencies": {
		"babel-jest": "^22.1.0",
		"jest": "22.4.2",
		"ts-jest": "22.0.1",
		"typescript": "2.8.4",
		"react-native": "0.57.1",
		// 中略
	},
	// 中略
}

JavaScriptの変遷を全然わかってない不勉強人間ですがES6使ってますとメモ。

参考記事様方

いつもいつもありがとうございます。沢山拝見させて頂きました…。

初めましてJESTさんということでお世話になりました。

Babelも使っているのですが社内で標準化済のものを使っていたのでbabel.config.jsというものを今更知るという(.babelrc使っていた)

まさに同じエラーに苦しんだ…

色々と苦戦はしていたのですが完成形から。

セットアップ

1. パッケージ導入

私の環境では不足していたのは@types/jestのみだったのでこちらを導入。--devで良いと思うけれど一度詰まったのでここではdependenciesに入れます。
jest,ts-jest(と、多分babel-jestも)が入っていなければこちらも導入すること。

console
yarn add @types/jest

2. package.jsontsconfig.jsonに設定を記載

ソースコードの階層は以下のようにしています。

root
 └- src
    └- main
        └- App.tsx, index.ios.tsx, 他mainソースコード
    └- test
        └- テストコード
 └- .babelrc, package.json, tsconfig.jsonなど

最終的に追加した設定は以下の通り。

package.json
{
	"scripts": {
		// yarn testコマンドを利用できるようにする
		"test": "jest"
	},
	"jest": {
		"preset": "react-native",
		"transform": {
			// 後述:エラーケース① 対応
			"^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js",
			// 後述:エラーケース② 対応
			"^.+\\.tsx?$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
		},
		"testMatch": [
			"**/test/**/*.test.tsx"
		],
		"moduleFileExtensions": [
			"tsx",
			"js"
		],
		// 後述:エラーケース③ 対応
		"globals": {
			"ts-jest": {
				"tsConfig": "tsconfig.json"
			}
		}
	}
}
tsconfig.json
{
  // 後述:エラーケース③ 対応
  "compilerOptions": {
    "types": [
        "jest"
      ]
  },
}

3. テストコードサンプルを動かしてみる

引用元: Facebook製のJavaScriptテストツール「Jest」の逆引き使用例
こちらに記載されていたサンプルコードをそのまま使わせて頂きました。

counter.tsx
export default class Counter {
  count = 0
  constructor(count) {
    this.count = count
  }

  increment() {
    this.count += 1
  }

  decrement() {
    this.count -= 1
  }
}
counter.test.tsx
import Counter from './counter'

describe('Counter', () => {
  describe('increment()', () => {
    test('increment', () => {
      const counter = new Counter(1)
      counter.increment()
      expect(counter.count).toBe(2)
    })
  })
})

準備が整ったところでyarn testをドン。

console
yarn test
yarn run v1.16.0
$ jest
 PASS  test/counter.test.tsx
  Counter
    increment()
      ✓ increment (2ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.482s
Ran all test suites.
✨  Done in 2.05s.

package.json**/test/**/*.test.tsxとなるファイルのみテストするようにしているので、counter.test.tsxのみがテスト対象とされる。

起きたエラー達

エラーケース①: Couldn't find preset "module:metro-react-native-babel-preset" relative to directory...

console
$ yarn test
yarn run v1.16.0
$ jest
 FAIL  scripts/test.js
  ● Test suite failed to run

    Couldn't find preset "module:metro-react-native-babel-preset" relative to directory (ルートフォルダ)

      at node_modules/babel-core/lib/transformation/file/options/option-manager.js:293:19
          at Array.map (<anonymous>)
      at OptionManager.resolvePresets (node_modules/babel-core/lib/transformation/file/options/option-manager.js:275:20)
      at OptionManager.mergePresets (node_modules/babel-core/lib/transformation/file/options/option-manager.js:264:10)
      at OptionManager.mergeOptions (node_modules/babel-core/lib/transformation/file/options/option-manager.js:249:14)
      at OptionManager.init (node_modules/babel-core/lib/transformation/file/options/option-manager.js:368:12)
      at File.initOptions (node_modules/babel-core/lib/transformation/file/index.js:212:65)
      at new File (node_modules/babel-core/lib/transformation/file/index.js:135:24)
      at Pipeline.transform (node_modules/babel-core/lib/transformation/pipeline.js:46:16)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.513s
Ran all test suites.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

yarn test実行時に、module:metro-react-native-babel-presetpresetにないよと怒られる。
→ babel側で対応するパターンとtypescript側で対応するパターンがあるが、前者の場合型チェックが出来なくなるらしいのでtypescript側で対応する。
.babelrcbabel.config.jsで対応する手段は前述のリンクを参照してください。

package.jsontransformの設定を追加したらこちらは解決。ついでに自動生成のscript/test.jsまでテスト対象に含めてしまって落ちていたのでtestMatchを記載した。

package.json
{
    // 前略
    "jest": {
        "preset": "react-native",
        "transform": {
            "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
        },
        "testMatch": [
            "**/test/**/*.test.tsx"
        ]
    }
}

※ コピペしたらスペースがずれていたらしく、落ちる;;;;;;ってしたのでFormatterはちゃんと使います(戒め)

エラーケース②: SyntaxError: Unexpected identifier

tsxのテストケースサンプルを投入した後、そのままではどうやら読み込まれず。

console
$ yarn test
yarn run v1.16.0
$ jest
 FAIL  test/counter.test.tsx
  ● Test suite failed to run

    (ルートフォルダ)/test/counter.test.tsx:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import Counter from './counter'
                                                                                                    ^^^^^^^

    SyntaxError: Unexpected identifier

      at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:316:17)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        1.686s
Ran all test suites.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

これも、package.jsontransform問題。

package.json
{
    "jest": {
        "preset": "react-native",
        "transform": {
            "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js",
            "^.+\\.tsx?$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
        },
        "testMatch": [
            "**/test/**/*.test.tsx"
        ],
        "moduleFileExtensions": [
            "tsx",
            "js"
        ],
        "globals": {
            "ts-jest": {
                "tsConfig": "tsconfig.json"
            }
        }
    }
}

"^.+\\.tsx?$": "<rootDir>/node_modules/ts-jest/preprocessor.js"moduleFileExtensions設定をしたら解消してテストが通るように。

エラーケース③: Cannot find name 'describe'.

テストソースで利用しているJestの関数(ここではdescribe)がts-lintに引っ掛かる。

counter.test.tsx
import Counter from './counter'

describe('Counter', () => {
  describe('increment()', () => {
    test('increment', () => {
      const counter = new Counter(1)
      counter.increment()
      expect(counter.count).toBe(2)
    })
  })
})

エラー内容。@types.jestがないよと言われる。(入っている)

Cannot find name 'describe'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`.ts(2582)

tsconfig.jsoncompilerOptions.typesjestを加えることで読み込まれるようになる。

tsconfig.json
{
  "compilerOptions": {
    "types": [
        "jest"
      ]
  },
}

おわりに

ようやく大前提が終わったので気が重いのですが、本番たるスナップショットテスト(?????)に掛かろうと思います。
ちょっと見たけど意味がわからない……!!!! 次の記事はテスト本番になると思われます。頑張ろう……。

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?