社内最長老のシステムにPHPUnitで立ち向かう方法

2564c99f616f1ecfc0f617a6fe87e2a9?s=47 penguin045
December 01, 2019

 社内最長老のシステムにPHPUnitで立ち向かう方法

表題の通りです

2564c99f616f1ecfc0f617a6fe87e2a9?s=128

penguin045

December 01, 2019
Tweet

Transcript

  1. 社内最長老のシステムに PHPUnit で立ち向かう方法 やなせ たかし

  2. 自己紹介 やなせ たかし 株式会社ラクスで働いています。 PHP 歴 9 か月 Scala 大好きマン

    2
  3. 今日話すこと 18 年稼働しているシステムの PHP をバージョンアップをしたときの戦い方 • レガシーネタです。 • 適用範囲は限定的です。 •

    PHP8 完全対応!ではありません。 話さないこと • レガシーシステムとの戦い方 • 実装の話 3
  4. 背景 • PHP 7.1 => 7.3 へのバージョンアップをすることになった ◦ ちょうど今日 EOL

    ですね • 調査までは PJ 横断だが、設計・実装担当は 1 人 ◦ しかも PHP 歴 3 か月 • 実装まではつつがなく終了 4
  5. _人人人人人人人人人人人_ > 突然の全機能テスト <  ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄ 5

  6. ルール 環境 • 老舗サービス (18 年モノ ) • ソースコードは当然レガシーなものが多い テストクリアの条件

    • 重要機能はカバレッジ 100% (C0) を取ること • 非重要機能は全機能の動作確認が完了している 6
  7. 戦い方を考える 手札 • 一部共通関数の PHPUnit • 一部シナリオの Selenium テスト •

    正常系の回帰テスト ( 手動 ) 戦術 • 既存テストは利用する • 不足分を PHPUnit で担保する 7
  8. トランザクションスクリプト対策 戦術:とにかくモックを使う • これまで自動テストでモックを使ってこなかった • 呼び出している関数を大胆にモック化 • 呼び出し先はテスト済みなので、テストの責務外 8

  9. uopz 拡張(User Operations for Zend) • Zend エンジンの振舞いを操作する拡張 • あらゆる関数をモック化するために使用

    • 引数にクロージャが渡せて、過去のデファクトだった runkit より使い勝手がいい • トランザクションスクリプト内の関数を狙い撃ちしてモック化 しなければならないケースで活躍 9
  10. テスト作成開始 10

  11. 甘すぎる見通し 11

  12. トランザクションスクリプトには 12

  13. 勝てなかった 13

  14. 高すぎるカバレッジ取得の壁 14

  15. どうやってもルール通りカバレッジは取れない • 条件分岐に入るのが至難の業 ◦ 放置されている謎のロジック ◦ 巨大なトランザクションスクリプト ◦ 変数の再代入・フラグの再利用が横行 •

    グローバル変数の濫用 => テストするべきかどうかを精査したほうが早い 15
  16. テストの取捨選択が必要 16

  17. カバレッジ取得するもの • 既存テストでカバーできるもの • 重要機能にまつわる小さな関数・メソッド ◦ 他の関数に依存していないもののみ ◦ 依存が少なければモックなどでテストする 17

  18. これらは問題ない 18

  19. 本丸に切り込む 19

  20. トランザクションスクリプトとの戦いかた • ほとんどが機能を実現しているロジック • 関数呼び出しはほとんどモックで置き換えた • それでも通せない重複した構造のコードが多過ぎた => ここで取捨選択をすることに決定 20

  21. トランザクションスクリプトとの戦いかた 前提 • 見えている部分のみテストできればよい • 呼び出し先はテスト済みのはず 新たな方針 • 内部状態は問題にしない •

    コンパイルが通るような状態なら充分である • 通せないものは通せない 21
  22. トランザクションスクリプトとの戦いかた 守りたいもの • 文法的な正しさを担保すること ◦ たとえそれが手作業であったとしても 捨てても構わないもの • カバレッジ 100%

    という安心感 22
  23. カバレッジ取得しなかったもの • return だけしているブロック ◦ 戻り値のチェックをしたいわけではない • 単純な操作のみのブロック ◦ 文字列結合だけしている

    ◦ 変数に代入しているだけ • 例外を投げているだけのブロック ◦ 投げるだけならエラーにはならないはず ◦ レアケースが多すぎるため、コストが高すぎる 23
  24. 無事生還 24

  25. まとめ • 切り分けは大事 ◦ コアロジックはしっかりテストしよう ◦ 構文のテストがいるような個所も • 知識は詰め込めばわりと入る ◦

    この経験で PHP に対して知見が深まったのは事実 ◦ 言語化できるにはまだ壁がある状態 • コンパイラがある幸せ ◦ みんな Scala やろう 25