t_hazawaの日記

株式投資とWebエンジニアリングのブログです。株式投資の目次は→です。 https://t-hazawa.hatenablog.com/entry/2021/02/12/220933

業務のJSを1テストケースだけJestにしてみた

経緯

  • 業務のJS(結構モダン)をTypeScript にしたい
  • テストが全くないので、テストをまず作りたい
  • テストフレームワークは流行ってるみたいなのでJestにしよう
  • 前回(38日前)、Jest自体は TypeScript の単体テストで Jest 使おう - Qiita をやってみて、一応使えるようになった
  • 今回は、実際の業務のコードを1つJest にしてみる

概要

  • めちゃくちゃ詰まったポイントがあった
    • 業務のコードの拡張子が .js だと、 「ES mocules の import を使いなさい」みたいなError がでたが、 .ts にしたら解消した
    • Jest でテストコード(window.alertが文言指定で出るか) 自体は一瞬で書けた

かかった時間

  • 5/22, 24 作戦考える (5日間開く)
  • 5/28 Jest やりはじめる (~5/30)
  • 6/1 import export のエラーに苦しみ始める
  • (6/18 まで評価資料5月分の方をする)
  • 6/19~6/25 そのエラーに取り組む (1日10~30分)
  • 6/26 ~6/29 そのエラーを突破できたので、先を進める
  • 6/30 ブログを書き始める
  • つまり、2週間弱かな?
  • このブログを書くのに 2022/07/05 1:43 まで 6日間、80分かかった

やったこと

最終的にいい感じに通った時のコード

  • Marumaru という機能があると思ってください
  • npm t するとテストが通る (上のqiita 通りに組んだので)
marumaru.test.ts

import zembu from "../src/marumaru";

beforeAll(() => {
  // window.alertをモックにする。Jestではモックにしないとエラーになる
  window.alert = jest.fn()
});

test('test', () => {
    zembu.add_marumaru('hikisuu1', 'hikisuu2', 'hikisuu3');
    expect(window.alert).toHaveBeenCalledWith('ログインしてね');
});

marumaru.ts

import $ from "jquery";
import "jquery.cookie";

const add_marumaru = function (hikisuu1, hikisuu2, hikisuu3) {
  略
    alert('ログインしてね');
};

略

export default {
  add_marumaru,
  add_kakukaku
};
  • …と、何の変哲もない(?) ES Modulesなコードだった
    • しかし、 marumaru.ts ではなく marumaru.js にしてたため、長いこと import 周りで悩んだ

詰まる前編

export のエラー文言が出る試行錯誤編

cross-env編

にっちも察知もいかないから0からやる編

  • ↑↑↑のQiita 自体で練習はできたので、それから、少しずつ、やりたいコードに変えていけば、おかしくなったところがどこか気づける作戦
  • tsconfig.json の "module": "commonjs", がだめそう 2022/06/21 22:54
    • 最終的には此れで問題無かった 2022/07/04 2:43
  • package.json の "type": "module", も 最終的には此れで問題なかった
// 近しいpackage.jsonのtypeがmoduleなので、このファイルはESMで読み込まれる
import './sample/setup/init.js'; 

// ./node_modules/foo/package.jsonにはtypeが書いてないため、CJSで読み込まれる
import 'foo';

とのことなので、 type: module だと、 eS modules になるのだろう  ぜ ぜ - まぁ、おいおいわかっていくだろう

まだまだ試行錯誤編

  • なんか、いけそうな気もしてるたので、なかなか0からというか、上手くいったやつから寄せていかなくて苦労してる
  • module.exports を export default { にもどしたら、おなじみの SyntaxError: Unexpected token 'export' がでた。
    • 一度諦めてcommonJS形式にしたときの記録
      • JSは同じことについて運種類も書き方があって難しい ユーザが必要な機能を次から次に実装していいた結果
        • とはいえ、ややこしいだけで普通に習得していけるものなのだろうと思う 難しくて時間がかかるけど
  • やっぱり最初からやろうか。
  • 最初から練習でうまくできたqiita をやったら そのまま npx tsc -init したら、かってに module:commonjs になった
    • 最終的にもこれでうごいてた
  • npx tsc -init
Created a new tsconfig.json with:                                                                                       
                                                                                                                    TS      
  target: es2016
  module: commonjs
  strict: true
  esModuleInterop: true
  skipLibCheck: true
  forceConsistentCasingInFileNames: true
  • "module": "es6", / Specify what module code is generated. / にしてみた 2022/06/22 22:52 11m だめだった 2022/06/22 22:52 ES2022でもだめ e 
    • タいしゅうてきには "module": "commonjs",

モジュールの CommonJS形式と ES Modules 形式

再び、上手くいった練習と見比べ

  • ちゃんとテストがうごいてる jest_rensyuu と見比べたり、jest_rensyuu に合わせていって、設定には問題なく、コードに問題があることを発見した
  • export - JavaScript | MDN
    • 書き方が大量にありすぎて難しすぎる js 2022/06/24 1:31
  • jest_rensyuu では ES modules で上手くいってるのでこのままでいけそうな気もしなくもない。
  • export default と export const で違いがあるらしい (default export, named export)
  • 中途半端には jest は es modules export, import に対応してそう 2022/06/25 0:35
  • 役立った素晴らしい記事

少し前進

  • export const add_marumaru = function (hikisuu1, hikisuu2, hikisuu3) { みたいな形式から export function add_marumaru (hikisuu1, hikisuu2, hikisuu3) { にしたら進みだした

やっと解決編

  • ファイルの名前を marumaru.js から marumaru.ts にしたらじごくくの Must use import to load ES Module: C:\Users\tetsuo_yamada\marumaru_jest\src\marumaru.js がたなくなった
  • ts-loader みたいなのが挟まってるから?(?)
    • やってればおいおい分かるだろう(?)

普通にjestを書いていく編

  • referenceerror document is not defined jest
  • よくあるエラーぽい
  • jest の環境ではそのままだと docuent がないよと。 2022/06/26 21:13
  • ぴったりそうな記事
  • 数あるJavaScriptテストツールの中からjestを選んだのは、jest-puppeteer、jest-image-snapshotなどpuppeteer関連で使い勝手が良さそうだったからです。

  • puppeteer がいるのかな ?
    • 要らなさそうだった 2022/07/05 1:41
  • 作成時にテスト環境としてnode.jsかjsdomを選択していると思います。node.j指定だとこれからのテストでdocument is not definedとエラーになるためjsdomを指定します。

  • // testEnvironment: "node",
  • testEnvironment: "jsdom",
  • なるほど。頼れる 
  • npm install jest-environment-jsdom がいりそう

alert をテストする編 2022/07/05 1:42

感想

  • JSは書き方がたくさんあってタイへん

この次

  • 多分、運用できる状態を整えて、1関数分テストを完備して、導入する
    • TSまで行けるか?
    • 似た部分が多い関数なのでなんとか集約できるかも