最近であった不具合メモ

保守していると長らく放置されていた不具合とかに出会うことがある。「あたし開発してないのに〜」と思っちゃうが、放置されていた不具合の原因はレビューやテストで重点的にチェックするべき箇所にできるはず!と前向きに考えるようにしている。

ということで、最近出会った不具合を忘れないようにメモしておく。

APIパラメータ用の型定義にtypoがあってパラメータが取得できない

APIから画面を表示するぞ!APIは自分たちで開発してるからI/Fも固定!よ〜し、GETの処理用にinterface作って使うぞ!ってなっていた。でも、interfaceにtypoがあってデータ取得できていなかった。

APIのレスポンスパラメータ例。

{
  "name": "test",
  "stats": "doing",
  "timestamp": "2021-04-22T08:02:17",
  "content": "test task",
}

TypeScriptのinterface。色々と間違っている

interface TestType {
  name: string;
  stat: string; // 本当はstatsが正しい
  // timestampが抜けている
  content: string;
}

データを取得してStore保存する処理で型アサーション(store = params as TestTypeみたいな感じ)を使っていた。これが原因で型とAPIのレスポンスが異なってもエラーにならず、放置されていた。 結合テストに「APIのパラメータと同じ値になっていること」のケースも入っていなかった。結果、アプリケーションがリリースされる前に気づけなかった模様。

対策

  • APIのパラメータにも型定義するぞって決めたなら、APIの設計書やレスポンスと突き合わせてチェックするべき
    • レビューでも見落とされていた
  • 型アサーションを使ってたらあまり意味ないのでは
    • でも、自分は実際どうやって型付けするのが良いのかちゃんとわかってない

ライブラリの仕様を考慮できてない

自分が保守しているプロダクトは日付の変換にDay.jsを使っている。軽量だしドキュメントもわかりやすい。

day.js.org

dayjs()は引数なしの場合、直近の日付・時刻が自動でセットされる。 また、dayjs(undefined)dayjs()扱いになるし、dayjs(null)は無効扱いになる。

APIから取得したパラメータにdayjs().format()をかけて表示していた。 何も考えずに使うとパラメータがundefinedの場合、今の時刻が勝手にセットされてしまう。

仕様的にはパラメータがない場合は空欄にしたい、という仕様だったが、これと矛盾する状態になっていた。 これも結合時のテストケースから漏れており、放置されてしまっていた。

<template>
  <!-- format変換したデータを表示 値がないときは空にしたい -->
  <div>{{ postDate }}</div>
</template>
<script>
  // timestampで取得した値をYYYY-MM-DD変換して表示したい
  get postDate() {
    return dayjs(timestamp).format('YYYY-MM-DD');
    // timestampがundefinedのとき、実際の動きは次の処理になっていた
    // return dayjs().format('YYYY-MM-DD');
  }
</script>

ライブラリを使う前にちゃんとドキュメントを読むべきだし、テストケースにパラメータがundefinednullの場合どうなるかを確認する観点が必要だった。


結合テストは「画面表示されるか」、「操作に応じてステータスが変わるか」のケースが多く、境界値やバリデーションNGの入力テストもなかった。 単体テスト書けないなら結合テストでこの辺のケースが網羅されてないと不安だよな〜と思う。普通はどのくらいテストするものなんだろう…?