---
# System prepended metadata

title: 2021/03/28 メンター相談
tags: [3月, メンター相談]

---

# 2021/03/28 メンター相談

###### tags: `メンター相談`,`3月`

### E2Eテストで、モックやスタブを使うことはあるでしょうか？

- windowのモックはよくやる
    - twitterシェアボタン
        - 実際に投稿画面に行ってしまうので、その場合は、windowオブジェクトをモックすることが多い
        - テストの安定性を高めるために行う
- 外部APIの通信で、異常系を起こしたい場合は、リクエストレスポンスをモックすることがある
    - 異常系が引き起こすために実際のAPIを使うのは怖い
- テストの安定性を高めるために、使うことは多い
- 時刻のモック
    - しばらく時間が経つとログアウトするなどの時に、cypressで時間を進めたり
    - タイムゾーンが異なる場合に、時間外取引ができないなっていることを確認したり

### cypressのテストはどの程度まで行うべきでしょうか？

- プラハで書いた時
    - 簡単に自動化できる、面倒なテストは、cypressで自動化している
- アラートが表示される系は、E2Eテストはしやすい

### E2Eテストを行う際は、cypressをどこまで信用していいのでしょうか？スクショや動画などもcypressで撮ることができると思いますが、人手でのテストは必要な部分は何かしらあると思います。何か基準などはありますでしょうか？

- 使い勝手などの部分は人手のテストになる
    - クリック範囲が狭すぎるとかはcypress
    - 読み込みがうまくできていない
    - クリックしてドラッグする時に動きが変など
- 人間によるテストを完全に排除することはできないと思う

### テスト手法の採用基準に関しては、プラハさんリクルート時代ではどのような基準を持っていましたか？

- フロントエンド、バックエンド
    - バックから書き始める
        - 単体テストから書き始める
        - 結合テスと、統合テストは、リクルートでは、100%近くでやっていた
        - プラハでは、そこまでやってないので、DBの書き込みなどはサボることが多いが、単体テストはサボることが多い
    - フロント
        - 人手でぽちぽちやるテストを書く
        - 何度もやるテストはE2Eテストで自動化することが多い
    - どのくらいのプロジェクトからテストを書くか
        - 1か月以上のプロジェクトでは必ず書く
        - 2週間ほどの開発でのプロジェクトでは書かないかもしれない
- テストの比率
    - googleのサイトでもあるように、単体テストを一番重視し、E2Eテストなどは少なくしている
        - https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html
    - E2Eテストは書かないことが多い
    - 仕様変更があるとしても、Unitテストの方から優先的にやる
        - 仕様変更がある場合は、テストは基本落ちてしまう

### Assertion Rouletteを防ぐために何かしていることはありますか？

- 何が原因でテストが落ちたのかわかりづらいのが困る
- エラーメッセージがわかりづらい
    - xUnit Patterns
        - assertがたくさんあると、多くのテストフレームワークでは実測値と期待値しか表示されないと書いてあるが、それは最近のテストフレームワークの進化で解決されているので、エラーメッセージがわかりづらいというのは、assertion rouletteの問題点にはならなくなってきている
            - 最近だと行数も表示される
        - 時々あるのが、テストデータが大量にあって、ループ内でアサートをしている場合は、どれが落ちたかがわからないので、これはよくない（t-wadaさんブログ参照）
            - https://t-wada.hatenablog.jp/entry/design-for-testability#%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88-%E3%82%A2%E3%82%B5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%AB%E3%83%BC%E3%83%AC%E3%83%83%E3%83%88Assertion-Roulette
- 1テストの中でたくさんのことを確認しようとしているのが、assertion rouletteのよくないところ
    - 1箇所が壊れた時に、何個もテストが落ちてしまうのは、テストが重複している可能性があるので、テストを分けるべき

### コミットの単位はどの粒度に分けていますか？

- 2パターンある
    - 手元でやる時は細かくコミットしている
        - yarnしたらコミットなど
    - pushする時には、rebaseして変えている
        - ロールバックできるようにするため
- プッシュする時は1つのコミットに分けようとしている
- 1プルリクエストあたり5ファイル
- 1コミットあたり1つのことをやるべき
    - でないとロールバックしづらいから
    - ロールバックできる単位でコミットする
- 基本実装とリファクタリングは分けてコミットしている
    - リファクタリングで泥沼にハマったら、困るから
- コミットメッセージの書き方
    - bodyにはどうやったかではなく、なぜそうやったのかを書く場合もある
        - 松原さんの現場ではこの書き方推奨の人が多かった
        - 最初のコミットのうちはあまりやらないが、リファクタリングの時はwhyを書く
    - 過去形でコミットメッセージを書くな、という人もいる
        - `fixed`など
        - これを直すとこうなるという進行形で書く
        - https://chris.beams.io/posts/git-commit/
- プラハでは、angularのコミットメッセージフォーマットにしたがっていたが、最近はgit emojiを使っている
    - https://gitmoji.dev/

### フルインデックススキャンとフルテーブルスキャンにパフォーマンス上の差はありますか？

- 差はある
- 違い
    - フルインデックススキャン
        - 場合によっては、こちらの方が遅い
        - 例えば
            - 索引が最後にあって、「象」を探そうとする
            - さ行のレコードを全部取得するのは大変
            - 行ったり来たりする
            - DBにとっても人間にとっても、検索速度が遅くなる
        - この行ったり来たりが遅くなる原因。これが多い場合は、シーケンシャルリードの方が早い。
        - ランダムリード
            - 読み込むブロックの数が大量になる
    - フルテーブルスキャン
        - シーケンシャルリード
            - ブロックごとに分かれている
            - 1ブロックとってきたら、その中には関連するデータが入っている
    - オプティマイざが、インデックススキャンの方が遅いのにフルテーブルスキャンを選ぶことはないと思う（開発者が意図的にフルテーブルスキャンを指定していない限り）
- そもそも、インデックスを利用する場合は全件検索ではなくて一部取得するとき
    - そのため、全件取得や並び替えのみを行うサービスの場合はインデックスtを貼るよりもカバリングインデックスを採用するかな。

### 2つのインデックスが存在する場合、オプティマイザによるインデックスの採用基準は何になるでしょうか？また、インデックスを作成する際に気をつけていることや失敗談を教えていただきたいです

- カーディナリティは条件の1つになる
- より絞りやすいものを選ぶ
- オプティマイザトレースを使った中身のトレースを行える
    - どんな返答をして作られたのかが、わかる
    - potential_range_indexesでどれを使うかを検討する
    - その後に、何件使うかのsummaryが出る
- インデックスで大事なのは、重複させないこと、無駄なインデックスを発生させないこと
    - インデックスを作るほど、遅くなる
    - 松原さんはオプティマイざを使わないといけないくらいの状況に陥ったことがない
        - そうなる前に、不要なインデックスがないかを疑う
- 注意
    - インデックスを貼った時は、explainのみだとわからないこともあるので、実際に流して確認してみることも重要
        - 速度など
- カーディナリティが高い方に、インデックスを貼る方が良い

### インデックスを貼ったカラムに対してGROUP BYを行った場合、どのようにインデックスが使われるのでしょうか？？

- 両方ありうる
- 後者は、テンポラリーテーブルなので、一番遅いgroup byに当たる
    - もし今回もう1つgroup byがあった場合は、後者になる
- 前者の方が早い
    - mysqlでは、できるだけ前者でやろうとするはず
- 2パターンある
    - mysqlのサイトに出てくる
    - loose index scan
        - フルインデックススキャンをしなくても済む時
        - インデックス全部をスキャンせずに、飛ばしながら進む
    - tight index scan
        - 注意
            - count関数は、minやmaxのようなaggregate関数ではないのでloose index scanにはならず、tight index scanとなる
            - 今回のクエリだと、tight index scanとなる

### インデックス名には、命名規則などはありますでしょうか？？

- `idx`をつける
- 複合インデックスの場合は、順番を間違えないように注意

### 参考

- アサーションルーレットってそもそも何が原因なんだっけ？について言及している記事
    - http://xunitpatterns.com/Assertion%20Roulette.html
- フルテーブルスキャンとフルインデックススキャンのパフォーマンス上の差分を検証している記事
    - https://www.percona.com/blog/2012/11/23/full-table-scan-vs-full-index-scan-performance/
    - https://yakst.com/ja/posts/2385
- loose | tight index scanに関する説明
    - https://dev.mysql.com/doc/refman/8.0/en/group-by-optimization.html
    - https://mysqlserverteam.com/what-is-the-scanning-variant-of-a-loose-index-scan/
- オプティマイザの決定を追っかけるための設定
    - https://qiita.com/hmatsu47/items/b99f5e1fb3e6675e07d8
- もしinnoDBの内部が本当に気になる方がいたら、こちらの資料が良さそうです！
    - https://dbstudy.info/files/20120310/mysql_costcalc.pdf