PHPUnitで単発/月額決済サービス自動テスト
Document Details
Uploaded by Deleted User
meijin
Tags
Summary
この資料は、PHPUnitを用いた単発/月額決済サービスの自動テストに関する講演資料です。決済機能のテストの重要性や自動テスト手法、具体的な実装方法について解説しています。また、テストコード作成の際の問題点や解決策についても触れています。
Full Transcript
PHPUnitで 単発/月額決済ありサービスを 自動テストしている話 株式会社NoSchool CTO / meijin 目次 - 自己紹介 - Pay.jpを用いた決済の仕組みと月額決済の苦悩 - PHPUnitを用いたPay.jp SDK実行のテストコード記述 - 告知 2 自己紹介 3 自己紹介 - twitter:...
PHPUnitで 単発/月額決済ありサービスを 自動テストしている話 株式会社NoSchool CTO / meijin 目次 - 自己紹介 - Pay.jpを用いた決済の仕組みと月額決済の苦悩 - PHPUnitを用いたPay.jp SDK実行のテストコード記述 - 告知 2 自己紹介 3 自己紹介 - twitter: @meijin_garden - career: 奈良高専 → LIFULL → NoSchool CTO - skill: Laravel/Nuxt.ts/Next.js/Nest.JS/AWS(Fargate)/Firebase 4 オンライン家庭教師マナリンクを開発しています オンライン家庭教師の CtoCマッチング。 単発課金の指導コースと 月額課金の指導コースがあり、 ご家庭ユーザーがクレカで決済する。 5 Pay.jpを用いた決済の仕組み 6 月額決済機能のシーケンス図(※一部割愛) 7 月額決済機能のシーケンス図(※一部割愛) とにかく実行手順が多い ○ 決済種別の判定→認可判定→決済処理 →支払いステータス更新・先生の売上データ更新→メール等の通知 ローカルでテストするのが面倒 ○ いちいちNuxtを起動してテスト用のクレカを入力するのか? ○ 月額課金の2ヶ月目以降の動作テストが無理 8 テストコードの作成方針 9 入出力の結合テストだけでも書く - APIを叩く結合テストだけは絶対に書く - 入力 - 決済エンドポイントにトークン等のPOST - 出力 - DBへの保存、Pay.jpへの通信、メール等の通知実行 - 単体テストは必要に応じて - 結合テストさえあればリファクタや改修に取り組める 10 Pay.jp SDKのラッパー実装を やってみた 11 Pay.jp SDKを呼び出すだけのラッパーを内製する Charge::createがPay.jp SDKの処理。 これを単に呼び出すだけのクラスを作る。 12 Pay.jpラッパーを作ると嬉しいこと - (前提)Pay.jpのAPIは公式SDK経由で実行する - https://github.com/payjp/payjp-php - ラッパーによってSDKへの依存度が下がる - コードから直接Pay.jp SDKを実行すると依存度が強くなる - SDKの仕様変更の影響範囲がテストコードも含め増えてしまう - ラッパーへのin/outは内製のValueObjectにする 13 ラッパーを利用するときはInjectionする Dependency Injectionすることで、 テスト時にモックに差し替えが可能になる。 14 テストコードでモックに差し替え app->instance()メソッドにより モックをコードに注入できる。 15 所感① - [KEEP]実際の決済処理を実行せずにテストできる - 開発が高速 - Pay.jpのテスト環境を汚さない - リファクタが捗る(リリース後、改修のたびにリファクタをしている) - [PROBLEM]Mock化のコードなどが職人芸になりがち - 職人芸をまとめたオリジナルの基底TestCaseクラスを作ったり READMEを書いたりして職人芸の緩和に務める 16 所感② - [TRY]interfaceにして、app->bind()で差し替える - class PayjpCharge implements ChargeInterface - app->bind(ChargeInterface::class, MockChargeInterface::class) - Mockery::mock('alias:(以下略)’)の書き方よりは慣れ親しんでいる&型安全 - 決済以外の処理は基本的にInterfaceに寄せているので合わせていきたい - 必ずErrorをthrowする実装クラスでTransactionのテストもできる 17 その他試行錯誤していること 18 複数のPay.jpラッパーをまとめるAdaptorの開発 一度に複数のラッパーを実行するので、 【定期課金の実行】といった責務で まとめたAdaptor/Interfaceを作り、 色々なサブスク機能で再利用可能にする 19 サブスク更新時のテスト 20 POSTされるデータのFixtureを作る - Pay.jpから、課金後1ヶ月毎に 登録したCallback Endpointに課金EventがPOSTされる仕様 - このタイミングで先生の売上更新があるのでめっちゃ重要 - Eventの中にサブスクIDとか金額が含まれている - それで該当のサブスクの検索とか売上更新処理をやる - このEventのFixtureを作る 21 例:サブスク更新時のEventを返す関数 テスト用のサブスク IDなどを受け取って、 Payjp\Event型の課金Eventを返すファクトリ。 テスト時はEventオブジェクトをモック化して テストデータの IDで更新処理をテストできる! 22 GitHub Actionsの設定 23 GitHub Actionsの設定 kirschbaumdevelopment/laravel-test-runner:7.4 を使わせてもらっています 24 自動テストを導入した所感 - [KEEP]リファクタリングの障壁が下がる - [KEEP]ドメイン知識の薄い業務委託のエンジニアさんにも 決済処理に関わってもらいやすい≒リスクが小さい - [PROBLEM]GitHub Actionsは実行時間で課金なので、 いずれは実行時間を短縮する工夫が要るかも。 25 最後に告知 26 Webエンジニア採用中!(副業でお試し勤務OK) - Nuxt.js/Next.js/NestJS/Laravel/AWS(Fargate)/Firebase/Pay.jp - テストコード(PHPUnit/jest)×GitHub Actions×Dockerデプロイ - 現在フルタイム3名(内開発1名...寂しい)、ご家庭・先生方の双方のニーズや課題 をヒアリングしつつ売上を立てていく日々 - ベンチャーなのでもちろんSOも検討します オンライン家庭教師という新しい生き方を広めつつ、 既存の学習市場のニーズを満たしていく事業の話を聞きたい方、お声がけください! 名人さん | マナリンクCTO https://twitter.com/Meijin_garden 27 ご清聴ありがとうございました 28 マナリンクについて https://manalink.jp - 小〜高校生向けオンライン家庭教師サービス - Nuxt.js(TS, composition-api) × Laravel(PHP7.4)で開発 - 開発体制はフルタイム1名+週1業務委託2名(2020年11月時点) 29 マナリンクでの 単発/月額決済機能の 開発と、テストについて 説明していきます 30 1. マナリンクにおける決済機能 31 マナリンクにおける決済機能 - 先生が指導内容をまとめた”指導コース”を作成 - 短期の単発課金も、長期の月額課金もある - サイト上でご家庭が指導コースを閲覧し、 クレジットカードで決済する 32 (月額)決済機能の苦悩 - 決済の瞬間に実行する手順が多い - 決済種別の判定→認可判定→決済処理 →支払いステータス更新・先生の売上データ更新→メール等の通知 - ローカルでテストするのが面倒 - いちいちNuxtを起動してテスト用のクレカを入力するのか? - 月額課金の2ヶ月目以降の動作テストが無理 33