Pythonを使った APIサーバー開発を始める際に 整備したCIとテスト機構 / python-api-ci-test
by
Kazuki Higashiguchi
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
© - BASE, Inc. X Pythonを使った APIサーバー開発を始める際に 整備したCIとテスト機構 . . PyCon JP - @hgsgtk
Slide 2
Slide 2 text
© - BASE, Inc. 本⽇話すこと https://pycon.jp/ /sessions CIでのコード検査‧⾃動テストを取り上げます。
Slide 3
Slide 3 text
© - BASE, Inc. 本⽇話すこと CIによるコード検査‧⾃動テストの 開発者⾃⾝にとっての メリット を話します。 https://pycon.jp/ /sessions
Slide 4
Slide 4 text
© - BASE, Inc. 話すこと • 学習サイクル促進のためのCI導⼊‧⾃動 テストの考え⽅ • Pythonでのコード検査‧⾃動テスト整 備のためのキーワード • コード検査‧⾃動テストから得られる フィードバック
Slide 5
Slide 5 text
© - BASE, Inc. 話さないこと • CIツールの⽐較 • 詳細なCIの設定⽅法 • テスティングフレームワークの⽐較
Slide 6
Slide 6 text
© - BASE, Inc. : @hgsgtk Who am I? 東⼝ 和暉 ( Higashiguchi Kazuki ) Back-end Engineer (Go, PHP, Python ) BASE BANK, Inc. (BASE, Inc.) / Dev Division / Tech Lead
Slide 7
Slide 7 text
© - BASE, Inc. お品書き .CI‧コード検査/テストに対する捉え⽅ .CI導⼊‧コード検査 .⾃動テスト作成‧実施 .まとめ
Slide 8
Slide 8 text
© - BASE, Inc. お品書き .CI‧コード検査/テストに対する捉え⽅ .CI導⼊‧コード検査 .⾃動テスト作成‧実施 .まとめ
Slide 9
Slide 9 text
© - BASE, Inc. CI (Continuous Integration) • 継続的インテグレーション • ビルド‧テストを頻繁に繰り返し⾏うこ とにより、問題を早期に発⾒、開発の効 率化‧省⼒化を図る⼿法
Slide 10
Slide 10 text
© - BASE, Inc. CIはなぜ⼊れたい?開発の効率化‧省⼒化? • エラーを⼩さな単位で早期に修正するこ とによる、修正コストの削減 • ex. コミット単位でコンパイル‧テス ト‧静的解析 …etc
Slide 11
Slide 11 text
© - BASE, Inc. このトークでの捉え⽅:学習サイクル促進 • 業務開発での commit‧ pushから得 られるフィードバックを増やす • XXX に対するフィードバック • コーディング • コード設計
Slide 12
Slide 12 text
© - BASE, Inc. CIで防ぎ CIに学ぶ
Slide 13
Slide 13 text
© - BASE, Inc. コーディングに対するフィードバック • PEP ‧PEP といったコーディン グ‧ドキュメントスタイルを守っている か • すべてを読み込むのは⼤変‧漏れている 可能性もある • コード検査で確認し、指摘結果から学ぶ
Slide 14
Slide 14 text
© - BASE, Inc. コード設計に対するフィードバック • テスト、特にユニットテストを書くこと で、テスタビリティの声を聞く • テストがしやすい‧テストがしにくいの 肌感をフィードバックとして受ける • 関⼼の分離がされた疎結合なパーツが協 調するコード設計へ
Slide 15
Slide 15 text
© - BASE, Inc. フィードバックからすぐアクションする • テストで振る舞いを保護する • 保護されたコードの内部詳細の実装‧ コーディングを改善していく
Slide 16
Slide 16 text
© - BASE, Inc. お品書き .CI‧コード検査/テストに対する捉え⽅ .CI導⼊‧コード検査 .⾃動テスト作成‧実施 .まとめ
Slide 17
Slide 17 text
© - BASE, Inc. 背景:題材事例となるアプリケーション • DB‧外部APIへ依存するAPIサービス • エンドポイントは4つほど、⽐較的⼩さ いがビジネスロジックを持った • ex. ⾦額計算などを⾏う
Slide 18
Slide 18 text
© - BASE, Inc. 様々なCIツール • 様々CI導⼊するためのツールがある • Jenkins, Travis CI, CircleCI etc • 本資料ではCircleCIを⽤いた事例を紹介
Slide 19
Slide 19 text
© - BASE, Inc. CircleCI jobs 例 https://circleci.com/gh/hgsgtk/pycon -app/tree/master
Slide 20
Slide 20 text
© - BASE, Inc. CircleCIでのコード検査実施
Slide 21
Slide 21 text
© - BASE, Inc. Pythonコードスタイルチェック • pycodestyle • https://pypi.org/project/pycodestyle/ • flake • http://flake .pycqa.org/en/latest/ • Pylint • https://www.pylint.org • autopep • https://github.com/hhatto/autopep
Slide 22
Slide 22 text
© - BASE, Inc. コードスタイル pycodestyle • Pythonコードスタイルガイドチェック ツール • PEP - Style Guide for Python Code • https://www.python.org/dev/peps/pep- /
Slide 23
Slide 23 text
© - BASE, Inc. pycodestyleからのフィードバック • Python Codeのスタイルガイドに準拠 しているかどうかが指摘される • 「Pythonの標準的なコードが書けてい るか?」
Slide 24
Slide 24 text
© - BASE, Inc. Pythonドキュメントスタイルチェック • pydocstyle • https://pypi.org/project/pydocstyle/
Slide 25
Slide 25 text
© - BASE, Inc. pydocstyle • Pythonのdocstring規約への準拠を確 認する静的分析ツール • PEP — Docstring Conventions • https://www.python.org/dev/peps/pep- /
Slide 26
Slide 26 text
© - BASE, Inc. pydocstyleからのフィードバック • “Code is read much more often than it is written” by Guido • 「読まれるコードドキュメントが作れて いるか?」
Slide 27
Slide 27 text
© - BASE, Inc. Pythonコード型検査 • mypy • http://mypy-lang.org/
Slide 28
Slide 28 text
© - BASE, Inc. mypy • コード上の型を静的解析するツール • PEP — Type Hints • https://www.python.org/dev/peps/pep- /
Slide 29
Slide 29 text
© - BASE, Inc. mypyからのフィードバック • 「型アノテーションを設定するコード‧ 設定に違反したコードが書かれていない か?」
Slide 30
Slide 30 text
© - BASE, Inc. CI導⼊‧コード検査のまとめ • CIツールを⽤いる • コーディングスタイル‧ドキュメントス タイル‧型検査を実施する • それらからコーディングに対するフィー ドバックをもらう
Slide 31
Slide 31 text
© - BASE, Inc. お品書き .CI‧コード検査/テストに対する捉え⽅ .CI導⼊‧コード検査 .⾃動テスト作成‧実施 .まとめ
Slide 32
Slide 32 text
© - BASE, Inc. ⾃動テスト実施の選択肢 • テストコードを作成‧実⾏するためのテ スティングツールを利⽤する • pytest • https://docs.pytest.org/en/latest/ • unittest • nose etc
Slide 33
Slide 33 text
© - BASE, Inc. pytest テストコード例
Slide 34
Slide 34 text
© - BASE, Inc. ⾃動テストでしたいこと • コード設計へのフィードバックを得る • 関⼼の分離がされた疎結合なパーツが 協調するコード設計か • 既存の振る舞いを保護し、リファクタリ ングをスピーディにする
Slide 35
Slide 35 text
© - BASE, Inc. そのために考えること .外部環境からの隔離 .依存関係の差し替え可能なコード設計
Slide 36
Slide 36 text
© - BASE, Inc. そのために考えること .外部環境からの隔離 .依存関係の差し替え可能なコード設計
Slide 37
Slide 37 text
© - BASE, Inc. そのために考えること(1):外部環境からの隔離 • テストスコープを対象アプリケーション 内に留めたい • 対象外(ex. 外部APIなど)を含めた場 合ネットワーク状態などに依存し不安定 なテストになりうる
Slide 38
Slide 38 text
© - BASE, Inc. 背景:アプリケーション構造(概要) 外部 API DB HTTP REQUEST HTTP Handler Database Access Inside API Application API Client Domain Logic
Slide 39
Slide 39 text
© - BASE, Inc. (補⾜)背景:アプリケーション詳説 • HTTP Handler: aiohttp • Asynchronous HTTP Client/Server for asyncio and Python. • http://docs.aiohttp.org/en/stable/ • Database Access: sqlalchemy • The Python SQL Toolkit and Object Relational Mapper • https://www.sqlalchemy.org/
Slide 40
Slide 40 text
© - BASE, Inc. テスト⽤ライブラリを活⽤する 外部 API DB HTTP REQUEST HTTP Handler Database Access Inside API Application API Client Domain Logic pytest-aiohttp • pytest plugin for aiohttp • 擬似的なリクエストを再現 • https://github.com/aio-libs/pytest- aiohttp
Slide 41
Slide 41 text
© - BASE, Inc. テスト⽤ライブラリを活⽤する 外部 API DB HTTP REQUEST HTTP Handler Database Access Inside API Application API Client Domain Logic kevin /vcrpy • 実⾏されたHTTPリクエスト/レスポンス を記録‧再⽣する • https://vcrpy.readthedocs.io/en/ latest/
Slide 42
Slide 42 text
© - BASE, Inc. テスト⽤ライブラリを活⽤しないもの 外部 API DB HTTP REQUEST HTTP Handler Database Access Inside API Application API Client Domain Logic
Slide 43
Slide 43 text
© - BASE, Inc. テスト⽤ライブラリを活⽤しないもの • データベースへの問い合わせをモックす るかどうか • たとえば、Goでは DATA-DOG/go- sqlmock という実⾏されるSQLが期待 通りかを検証するモックを作成する⽅法 がある • https://github.com/DATA-DOG/go-sqlmock
Slide 44
Slide 44 text
© - BASE, Inc. モックに置き換えるかどうか • ⻑所は、テストの速度‧安定度 • ⼀⽅、短所は、統合した際に期待通り動 作するという安⼼感 • ex. SQLが本当に正しい?
Slide 45
Slide 45 text
© - BASE, Inc. 結果的に⾏った施策 外部 API DB HTTP REQUEST HTTP Handler Database Access Inside API Application API Client Domain Logic • テスト⽤DBを作成する (本例ではコンテナ)
Slide 46
Slide 46 text
© - BASE, Inc. テスト⽤DBを作成する
Slide 47
Slide 47 text
© - BASE, Inc. テスト⽤DBを利⽤する ※ スキーマ‧フィクスチャ管理については時間の都合上‧‧‧
Slide 48
Slide 48 text
© - BASE, Inc. 「外部環境からの隔離」のフィードバック • テスト⽤ライブラリで外部環境との接点 を差し替えれる • ⼀⽅で、すべてのテストケースでこれら で差し替えるようなコードの場合、疎結 合なコード設計になっていない可能性を ⽰唆
Slide 49
Slide 49 text
© - BASE, Inc. そのために考えること .外部環境からの隔離 .依存関係の差し替え可能なコード設計
Slide 50
Slide 50 text
© - BASE, Inc. 背景:アプリケーション構造(概要) 外部 API DB HTTP REQUEST HTTP Handler Database Access Inside API Application API Client Domain Logic
Slide 51
Slide 51 text
© - BASE, Inc. 背景:アプリケーション構造(概要) 外部 API DB HTTP REQUEST HTTP Handler Database Access Inside API Application API Client Domain Logic たとえば、HTTP Handlerのテストをするのに DB‧外部APIすべてライブラリで差し替えるの は「前準備のコスト」が⾼い
Slide 52
Slide 52 text
© - BASE, Inc. 依存関係の差し替え可能なコード設計 • 依存関係をなるべく差し替え可能へ • DI(Dependency Injection: 依存関係の 注⼊)可能な設計へ
Slide 53
Slide 53 text
© - BASE, Inc. DI可能にする constructorからオブジェクトを受け付ける
Slide 54
Slide 54 text
© - BASE, Inc. DI可能にする テスト時には仮の値を返すテストダブルに置き 換える ※ テストダブル: テスト固有の同等物(ex. スタブ‧モック)
Slide 55
Slide 55 text
© - BASE, Inc. 依存関係の差し替え⼿段 • ⾃分でテスト⽤の代替クラスを作成 • モックライブラリ利⽤ • pytest-mock • https://pypi.org/project/pytest-mock/ • spy, stub, mockが可能
Slide 56
Slide 56 text
© - BASE, Inc. 「依存関係の差し替え可能なコード設計」 のフィードバック • テストの前準備のコスト‧実⾏速度が、 疎結合なコード設計へ⽬を向けるきっか けへ
Slide 57
Slide 57 text
© - BASE, Inc. おまけ 〜⾃動テストの維持のために〜 • pytest-randomly で不安定なテストに 気づく • https://pypi.org/project/pytest-randomly/ • 実⾏順に依存するテストは、⼀般的に不安定な テストと呼ばれる、⾃動テスト維持にはデメ リットになる Refs: “Pythonでの開発を効率的に進めるためのツール設定” at PyCon JP by @aodag さん https://www.slideshare.net/aodag/python-
Slide 58
Slide 58 text
© - BASE, Inc. お品書き .CI‧コード検査/テストに対する捉え⽅ .CI導⼊‧コード検査 .⾃動テスト作成‧実施 .まとめ
Slide 59
Slide 59 text
© - BASE, Inc. まとめ • CIを回すことで継続的なフィードバック 環境を作る • コード検査からコーディングを、テスト からコード設計へのフィードバックをも らう
Slide 60
Slide 60 text
© - BASE, Inc. まとめ • コード検査‧⾃動テストなどはある種 「⾯倒だけどやったほうが良いこと」と 捉えられがち • 開発者にフィードバックをくれるものと 捉えて、「前向き」な捉え⽅をする⼀つ のアイデアでした