Upgrade to Pro — share decks privately, control downloads, hide ads and more …

testingパッケージを使った Webアプリケーションテスト 単体テストからE2Eテストまで / gocon2022spring

testingパッケージを使った Webアプリケーションテスト 単体テストからE2Eテストまで / gocon2022spring

https://gocon.jp/2022spring/sessions/a10-s/

Go Conference 2022 Springの登壇資料です。
資料の中のリンクはブログで紹介しています。

https://budougumi0617.github.io/2022/04/25/gocon2022spring/

Yoichiro Shimizu

April 25, 2022
Tweet

More Decks by Yoichiro Shimizu

Other Decks in Technology

Transcript

  1. © 2012-2022 BASE, Inc. 1
    #goconA
    @budougumi0617
    testingパッケージを使った
    Webアプリケーションテスト
    単体テストからE2Eテストまで
    Go Conference 2022 Spring
    BASE株式会社
    清水 陽一郎(@budougumi0617)

    View Slide

  2. © 2012-2022 BASE, Inc. 2
    #goconA
    @budougumi0617
    自己紹介
    所属
    BASE 株式会社 BASE BANKチーム Tech Lead
    Go、New Relicや自動化など。
    趣味
    ブログ: https://budougumi0617.github.io/
    SNS
    Twitter : @budougumi0617 
    Github : https://github.com/budougumi0617
    2022/07/20 商業誌出版予定
    清水 陽一郎 (しみず よういちろう)

    View Slide

  3. © 2012-2022 BASE, Inc. 3
    1
    2
    3
    #goconA
    @budougumi0617
    WHY - なぜテストするのか?
    WHAT - 何をテストするのか?
    HOW - どうテストするのか?
    今日の話

    View Slide

  4. © 2012-2022 BASE, Inc. 4
    1
    2
    3
    #goconA
    @budougumi0617
    テストを書くことで自信をもって変化を積み上げる
    テストと設計は表裏一体
    なぜテストするのか意識する
    今日伝えたいこと

    View Slide

  5. © 2012-2022 BASE, Inc. 5
    #goconA
    @budougumi0617
    ● 「テストがないコードはレガシーコード」だから?
    ● プロジェクトにカバレッジの基準があるから?
    Why Test

    View Slide

  6. © 2012-2022 BASE, Inc. 6
    #goconA
    @budougumi0617
    ● テストを書いたほうがいいことはみんな知っている
    ● “golang やりたいテスト形式”でググればHOWはだいたい出てくる
    ● 「なぜ」このやり方のテストを選択しているのか?が参考になれば🙏
    「なぜ」が一番大事

    View Slide

  7. © 2012-2022 BASE, Inc. 7
    #goconA
    @budougumi0617
    ● テストピラミッド
    ● アジャイルテストの4象限
    ● 様々なテストを黄金比通りに作ればいいのか?
    ● 「あったほうがいい」からやるのか?
    ● プロダクトの品質にどう寄与しているのか
    テストを書く
    https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html
    https://www.informit.com/articles/article.aspx?p=2253544&ranMID=24808

    View Slide

  8. © 2012-2022 BASE, Inc. 8
    #goconA
    @budougumi0617
    ● バグを補足できる
    ● 変化を可能とする
    ○ テストがあれば、検証しながらコードの動きを素早く変更できる
    ○ テストがなければ、コードが良くなっているのか悪くなっているのかが本 当にはわ
    からない。
    ● レビューやデバッグの効率化
    ● 結合度を低下させ、柔軟性をもたせる
    ● 実装前にAPIを観察できる
    Why Test

    View Slide

  9. © 2012-2022 BASE, Inc. 9
    #goconA
    @budougumi0617
    ● ネットショップ 作 成 サービスBASE
    オーナー様向けサービス
    ● BASEの 売 上 をそのまま
    Visa提携店で使える
    ● GoはAPIサーバ
    お題: BASEカード

    View Slide

  10. © 2012-2022 BASE, Inc. 10
    #goconA
    @budougumi0617
    ● リポジトリ
    ○ 永続化処理、外部APIを実行するためレイヤー
    ● ユースケース
    ○ 永続化処理やドメインロジックを組み合わせてユースケースを表現するレイヤー
    ● HTTPハンドラー
    ○ JSONパース/レンダリングするレイヤー
    ざっくり3層アーキテクチャ

    View Slide

  11. © 2012-2022 BASE, Inc. 11
    © 2012-2022 BASE, Inc. 11
    リポジトリ関連のテスト

    View Slide

  12. © 2012-2022 BASE, Inc. 12
    #goconA
    @budougumi0617
    ● DB処理用のメソッド
    ● UseCaseからコネクションをもらう実装
    ○ トランザクション制御をユースケース上でするため
    リポジトリ関連のテスト

    View Slide

  13. © 2012-2022 BASE, Inc. 13
    #goconA
    @budougumi0617
    ● 実DBを使ってテストしている
    ○ sqlxを使ってCASE式などを使ったSQLを書いているから
    ○ gormやentなら不要かもしれない
    ● sql-mock
    ○ 期待通りのSQLが発行されただけ
    ○ 実際にデータが取れるかはわからない
    ● fixtureはシンプルなカタチで用意
    リポジトリ関連のテスト

    View Slide

  14. © 2012-2022 BASE, Inc. 14
    #goconA
    @budougumi0617
    ● CI上で実行する時などは環境変数をみる
    ○ CircleCIだったらCIRCLECIが定義されている
    ● Cleanupでレコードを消す
    リポジトリ関連のテスト

    View Slide

  15. © 2012-2022 BASE, Inc. 15
    © 2012-2022 BASE, Inc. 15
    ユースケースのテスト

    View Slide

  16. © 2012-2022 BASE, Inc. 16
    #goconA
    @budougumi0617
    ● ユースケースレイヤーでトランザクション制御
    ○ 抽象化による難読化を避けるため
    ○ 参考: https://speakerdeck.com/sonatard/ideal-and-reality-of-abstraction-by-repository
    ユースケース関連のテスト

    View Slide

  17. © 2012-2022 BASE, Inc. 17
    #goconA
    @budougumi0617
    ● 入力に対する期待シナリオでリポジトリ層やロジックが呼ばれているか
    ○ 実DBは使っていない
    ○ sql.DBオブジェクトやTxをモックしている
    ■ Commit()が実行されたか
    ○ 永続化データが正しくロールバックされるかはDBの実装による
    ■ この層ではトランザクションをリポジトリに渡したか、Commit()を呼んだのかRollback()を呼
    んだのか分かればよい
    ユースケース関連のテスト

    View Slide

  18. © 2012-2022 BASE, Inc. 18
    © 2012-2022 BASE, Inc. 18
    HTTPハンドラーのテスト

    View Slide

  19. © 2012-2022 BASE, Inc. 19
    #goconA
    @budougumi0617
    ● JSONパースとJSONレンダリングくらいの実装
    HTTPハンドラーのテスト

    View Slide

  20. © 2012-2022 BASE, Inc. 20
    #goconA
    @budougumi0617
    ● httptest pkgを使った素朴なテスト
    ● 入力/期待JSONをファイルにしている
    ○ API仕様を理解しやすい
    ■ testdata
    ● card_setting
    ○ request
    ■ normal_case.json
    ○ response
    ■ ok.json
    ■ invalid_setting.json
    ● issue_card
    ● …
    HTTPハンドラーのテスト

    View Slide

  21. © 2012-2022 BASE, Inc. 21
    © 2012-2022 BASE, Inc. 21
    APIクライアントのテスト

    View Slide

  22. © 2012-2022 BASE, Inc. 22
    #goconA
    @budougumi0617
    ● モックサーバを自作してhttptest.Serverで起動している
    ● http.ClientのTransport(RoundTripper)をすげ替える選択肢もある
    ● 再利用性の観点で自作している
    ○ 外部連携先に接続できない開発環境でダミーサーバとして利用するため
    APIクライアントのテスト

    View Slide

  23. © 2012-2022 BASE, Inc. 23
    © 2012-2022 BASE, Inc. 23
    E2Eテスト

    View Slide

  24. © 2012-2022 BASE, Inc. 24
    #goconA
    @budougumi0617
    ● カード決済の難しさ(ひとつの決済に複数の通信が行われる)
    ○ オーソリ(残高確定)
    ○ 確定
    ○ 強制確定
    ■ 為替変動による決済金額変動
    ○ 強制確定(マイナス)
    ■ 確定後にキャンセル
    ■ 一部だけキャンセル(年間払いを途中でキャンセルetc)
    シミュレーションテスト(E2Eテスト)

    View Slide

  25. © 2012-2022 BASE, Inc. 25
    #goconA
    @budougumi0617
    ● デグレなしでエッジケース対応したい
    ● 決済レコードに状態を持たせたテストがしたい
    ○ オーソリ、確定、強制確定(マイナス)を処理した決済レコードのステータス
    ● 複数回リクエストを処理した結果なのでユニットテストでは検証できない
    ● 事前データを作る形式では”都合の良い”データになっている可能性
    シミュレーションテスト(E2Eテスト)

    View Slide

  26. © 2012-2022 BASE, Inc. 26
    #goconA
    @budougumi0617
    ● メルカリの柴田さんが書いていたE2Eフレームワークの簡易版
    ○ https://engineering.mercari.com/blog/entry/gears-microservices/
    ● 実DBに接続した本番同等のルーティングをhttptest.Serverで起動
    ● 決済業者を模して残高確認webhookを複数回実行
    ● DB上のレコードを検証
    シミュレーションテスト(E2Eテスト)

    View Slide

  27. © 2012-2022 BASE, Inc. 27
    #goconA
    @budougumi0617
    ● テストケースの実装など、メンテナビリティは低い
    ● 問題ない
    ○ ( 新 たなエッジケースの)テストケースが 追 加 されることはあっても、
    既存のテストケースが変わることはない
    ○ 仕様が変わる時 == クレジットカードの決済の仕組みが変わるとき
    ○ 完全なブラックボックステストなので脆くない
    ● テストがあることで決済ロジックも安心して変更できる
    シミュレーションテスト(E2Eテスト)

    View Slide

  28. © 2012-2022 BASE, Inc. 28
    1
    2
    3
    #goconA
    @budougumi0617
    テストを書くことで自信をもって変化を積み上げる
    テストと設計は表裏一体
    なぜテストするのか意識する
    まとめ

    View Slide

  29. © 2012-2022 BASE, Inc. 29
    © 2012-2022 BASE, Inc. 29
    Tips

    View Slide

  30. © 2012-2022 BASE, Inc. 30
    #goconA
    @budougumi0617
    ● go test shuffle=on ./…
    ○ 順不同に実行される
    ○ non-parallelなテーブルサブテストは逐次のまま
    ■ mapにするとよい
    ● go test -count=1 ./…
    ○ キャッシュを無視できる
    ○ 競合状態の再現のときなど
    ○ 明示的にキャシュを消すならば go clean -testcache
    Tips: よく使うgo testオプション

    View Slide

  31. © 2012-2022 BASE, Inc. 31
    #goconA
    @budougumi0617
    ● go test -race ./…
    ○ 競合状態を発見してくれる
    ○ テスト実行中に"実際に起きない"と検知できない
    ○ CI上の実行ではひとまずつけておいてよい
    Tips: よく使うgo testオプション

    View Slide

  32. © 2012-2022 BASE, Inc. 32
    #goconA
    @budougumi0617
    ● t.Helper()
    ● t.Cleanupが増えてすっきり書ける
    ● 共通化
    ○ JSONファイル比較アサーション
    ○ 事前データの流し込み関数
    Tips: ヘルパー

    View Slide

  33. © 2012-2022 BASE, Inc. 33
    #goconA
    @budougumi0617
    ● export_testを参照できるのはそのパッケージか..._testパッケージだけ
    ○ Go Fridayこぼれ話:非公開(unexported)な機能を使ったテスト
    ■ https://engineering.mercari.com/blog/entry/2018-08-08-080000/
    ● go test ./…
    ○ パッケージごとに別プロセスで動く(パッケージ間でメモリ空間が独立)
    ○ 並行テストの動き方
    ■ Go言語でのテストの並列化 〜t.Parallel()メソッドを理解する〜
    ● https://engineering.mercari.com/blog/entry/how_to_use_t_parallel/
    ● testdataディレクトリ
    ○ The go tool will ignore a directory named "testdata", making it available to hold ancillary data needed by the tests.
    Tips:

    View Slide

  34. © 2012-2022 BASE, Inc. 34
    #goconA
    @budougumi0617
    ● github.com/golang/mock
    ○ Goにおけるモックのデファクトツール
    ○ モックメソッドの引数に指定した構造体の差分が見にくい時
    ■ github.com/budougumi0617/cmpmock
    ● github.com/DATA-DOG/go-sqlmock
    ○ DBをモックしてくれる
    ○ いい感じに初期化されたsql.Txがほしいときなどに使う。
    ■ sql.Txは適切に初期化されていないとCommitなど実行したときに失敗する
    Tips: OSS

    View Slide

  35. © 2012-2022 BASE, Inc. 35
    #goconA
    @budougumi0617
    ● github.com/google/go-cmp
    ○ 構造体の比較をよしなにしたいとき
    ○ cmpoptsサブパッケージはちゃんと見ておいたほうがよい
    ○ SortMaps, IgnoreFields, IgnoreTypes etc…
    ● github.com/k1LoW/octocov
    ○ しゅっとカバレッジ可視化できる
    Tips: OSS

    View Slide

  36. © 2012-2022 BASE, Inc. 36
    #goconA
    @budougumi0617
    ● github.com/stretchr/testify
    ○ https://pkg.go.dev/github.com/stretchr/testify/assert#Eventually
    ● github.com/onsi/gomega
    ○ https://pkg.go.dev/github.com/onsi/gomega#Eventually
    ○ イベント駆 動な結 果 整 合 性までテストしたい場 合は素 直にtestifyやgomegaをつ
    かったほうがよさそう
    Tips: OSS

    View Slide