[勤怠FEギルド] Jestを使ってファイル・ディレクトリの命名規約をテストする

こんにちは。クラウド勤怠チームでエンジニアをしております katuo です。今回の記事ではチーム内でJestを使ってファイル・ディレクトリの命名規約を自動テストできるようにした話について書いていこうと思います。

※ タイトルの「勤怠FEギルド」はクラウド勤怠のフロントエンドの技術的負債の解消や生産性向上のためのコード整備を業務時間内の20%を使って行うチームのことを指しています。

コード規約作成に伴う問題

現在クラウド勤怠ではフロントエンドの再設計・コード規約の整備が進んでいます。コード規約が整備されて、可読性が向上したり、意思決定コストが下がったりするなどの恩恵を受ける一方で、PRレビューでディレクトリ/ファイル命名規約に関するレビューコストが全体として増加してしまいました。(例: 「〜の階層に定義するファイルは〇〇の形式で記述してください!」)

現在、クラウド勤怠ではフロントエンドのコード規約はGithubのWikiで管理しています。日常的に業務でコード規約を管理しているメンバーは問題ないのですが、そうでないメンバーは最新コード規約を把握するのが難しく、キャッチアップのハードルが上がってしまい、メンバー間でコード規約の理解度の格差が発生するようになってしまったのが1つの原因だと思われます。

⁠対策

Jestのテストを追加する

上記の問題を解消する1つの対策として、ファイルの命名規約に違反していないかを確認するJestのテストを追加しました。クラウド勤怠ではPRを作成時にCircle CIのworkflowでJestのテストが実行されます。

よって、ファイルの命名規則に違反したコードをPR作成時に自動で検知できるようになりました。その結果、ファイルの命名規則に関するレビューを人間がする必要がなくなり、テストに落ちることで自らコード規約を読む機会が提供できたりするなどの収穫がありました。

Jestを選択した経緯

導入後に知ったのですが、ファイル・ディレクトリの命名規約は静的解析のプラグイン(eslint plugin …etc)で解決するアプローチがデファクトのようです。当初、Jestを選択した理由は今ある仕組みでそのままテストが書けるというのと、カスタマイズが柔軟にできそうと判断したからです。なので「Jestでこういうテストが書けるんだ〜」といったノリでこの先読んでいただけると助かります。

テスト内容

実際に追加したJestのテストを一部紹介します。テストの内容はシンプルで、該当のディレクトリに存在する.vueファイルはAttのprefixが付与されたPascal Caseであるかを確認しています。

import path from 'path'
import glob from 'glob'

const isAttPascalCase = (str: string) => {
  return /^Att[A-Z][A-Za-z]*$/.test(str)
}

/**
 * if you are adding any vue components to atoms, molecules, or components directories,
 * please name it in Pascal Case with Att prefix (ex: AttFormTable.vue).
 */
describe('vue components filename in atoms, molecules, components directories', () => {
  const options = {
    ignore: [
      'node_modules/**',
         // 略
    ],
  }

  // TODO: rename file name to Pascal Case with Att prefix
  const ignoreFiles: string[] = [
    'app/javascript/vue/atoms/att-button.vue',
    // 略
  ]

  options.ignore = ignoreFiles.concat(options.ignore)

  const filePaths = glob.sync('**/*.vue', options)
  filePaths.forEach((filePath: string) => {
    const filename = path.basename(filePath).replace('.vue', '')

    test(`${filename} should be Att pascal case`, () => {
      expect(isAttPascalCase(filename)).toBeTruthy()
    })
  })
})

今回、ファイル検索に glob を利用しました。

globを利用するとshellのような使い方でファイル検索のパターンを簡単に記述することができます。またファイル検索時にopitonsを渡すことで、検索対象外にするファイルの指定などを行うことができます。上のコードではテストで無視するディレクトリ、現在命名規約に沿っていない修正予定のコードなどを検索対象外にしています。

上で紹介したテストは非常にシンプルなものですが、Jestとglobを活用することでディレクトリ構造や指定階層のファイルの命名がチームのコード規約に沿っているかを確認する複雑なテストもカスタムでどんどん追加していくこともできます。

最後に

方向性としてコード規約などは人間が管理するのではなく、静的解析やテストで縛って管理を仕組み化・自動化があるべき姿なんだと再認識しました。日々他の業務に追われる中、規約に関するドキュメントを読みこむというのは難しいですからね。

仕組み化が少し面倒だったりするとついつい自動化を後回しにしてしまいがちですが、中長期で見たときに余分なコミュニケーションコストなどが発生し、チームメンバーの貴重な時間を奪ってしまうことにもなりえます。ここで小さな一歩を踏み出すことで、チームのToil解消に繋がることもあるので、自動化の観点は常に持って業務に取り組んでいきたいと思います。

最後までお読みいただきありがとうございました。


マネーフォワードでは、エンジニアを募集しています。
ご応募お待ちしています。

【会社情報】
Wantedly
株式会社マネーフォワード
福岡開発拠点
関西開発拠点(大阪/京都)

【SNS】
マネーフォワード公式note
Twitter – 【公式】マネーフォワード
Twitter – Money Forward Developers
connpass – マネーフォワード
YouTube – Money Forward Developers

Pocket