こんにちは。
2020年度新入社員の松村です。
今回はタイトルにもある通り、開発環境のテストは通ったのに、本番環境のテストでメソッド制限に引っかかった話をしたいと思います。
はじめに
弊社は占いのアグリゲーションサイトである、「占い@nifty」というサービスを提供しております。
アグリゲーションサイトなので、各コンテンツプロバイダー(以下CP)様が提供してくださった占いを、弊社の占い@niftyに掲載しています。
今まではCP様が提供してくださった占いを占い@niftyで公開する前に、主に以下のテストを担当者が手動で行っていました。
- 入稿された内容と、占い@niftyに掲載される内容が等しいか
- 掲載された占いが正しく購入可能か
- 購入後に送られる購入確認メールの内容に誤りがないか
- 無料占いで購入画面が表示されないか
- 占い結果ページがリンク切れになっていないか
上記テストにはかなりの工数がかかっていたため、ソフトウエアによって自動化するプロジェクトが発足し、私はこのプロジェクトにアサインされました。
開発メンバーは私を含め3人で、スクラムでの開発でした。
テスト自動化の構成
AWSのサービスである AWS Lambda、Amazon S3、Amazon CloudWatch Events を用いて、いわゆるサーバーレスの構成で作ることになりました。
テスト自動化の構成図は以下の通りです。
今回の記事は、構成図の赤枠部分の内容です。
LambdaのランタイムはPythonを選び、Python用のAWS SDKであるboto3を用いて開発しました。
boto3について
boto3を使うと、ほとんどのAWSサービスをPythonで利用することができます。
boto3で利用可能なサービスは下記公式ドキュメントをご覧ください。
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html
今回利用したboto3のメソッドの一例として、S3のディレクトリ配下のファイル一覧をリストする、 list_objects_v2 メソッドがあります。
※ list_objects_v2 メソッドの公式ドキュメントはこちらです。
使い方は下記のように、バケット名とリストしたいディレクトリまでのパスを渡すだけでディレクトリ配下のファイルをリストすることができます。
1 2 3 4 5 6 7 |
import boto3 s3_client = boto3.client('s3') response = s3_client .list_objects_v2( Bucket="バケット名", Prefix="ディレクトリパス", ) |
問題が発生した処理について
占い@niftyで占いを購入すると、購入確認メールが送信されます。
送られた購入確認メールの内容は、購買データとしてAmazon S3に保存されます。
この購入データを取得して、購入メールの検査を行います。
また、占い@niftyの検査担当者が、検査対象の占いを業務時間内に購入し、検査しているので、Amazon CloudWatch Eventsを用いて購買データの自動検査を平日の10時~20時で2時間おきに実行することにしました。
自動検査対象日の購買データ一覧を取得する際に、 list_objects_v2 メソッドを用いて購買データ一覧を取得した後、各項目の整合性をチェックする処理を実装しました。
本番テスト時に問題発生
無事にすべての実装が完了したので、テストに入ります。テストは、あらかじめ作成したテスト仕様書に基づいて開発環境でテストをした後、本番環境へデプロイしてテストを行う、という流れです。
開発環境のテストは何事もなく無事に通りましたので、本番環境へデプロイした後、本番環境のテストを行いました。
ところが、開発環境では無事に通っていたテストケースが、本番環境だと落ちてしまいました。
言語やライブラリのバージョン、IAMロールなどは開発環境と同じバージョン、設定なので、本番環境でテストが通らなかったことを不思議に思いつつ、ログを見て原因を探しました。
原因と対処法
結論からいうと、 list_objects_v2のメソッド制限によって対象ファイルをすべて取得できていなかったことが原因でした。
list_objects_v2 メソッドは公式ドキュメントにもある通り、一度の実行で最大1000件までしか取得ができず、それ以上ファイルが存在する場合は NextContinuationToken というトークンが返ってきます。返ってきたトークンを list_objects_v2 メソッドの引数に与えてやることで、前回の続きからファイルをリストしてくれます。
list_objects_v2 を利用するうえで、ファイル数が1000件以上存在する場合は以下のようにする必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import boto3 s3_client = boto3.client('s3') contents = [] next_token = None while True: if next_token: response = s3_client.list_objects_v2( Bucket="バケット名", Prefix="ディレクトリパス", ContinuationToken=next_token, # ContinuationTokenにnext_tokenを渡すことで前回の続きから取得 ) else: response = s3_client.list_objects_v2( Bucket="バケット名", Prefix="ディレクトリパス", ) # データの取得は中身に応じて適切に処理してください contents.append(response) # 続きのコンテンツがあるか if 'NextContinuationToken' in response: next_token = response['NextContinuationToken'] else: next_token = None break |
何故開発環境のテストは通ったのか
そもそも何故、メソッド制限があるにもかかわらず開発環境のテストが通ってしまったかというと、本番環境のデータ数とテスト環境のデータ数に大きな差があったことが原因でした。
本番環境には、本番稼働しているサイトからの購買データが蓄積されているため、膨大な量のデータ数ですが、開発環境は必要最低限のテストデータしか置かれていなかったため、今回の1度の実行で最大1000件までというメソッド制限に引っかからずにテストが通ってしまいました。
感想
学生の頃は何かを実装する際に公式ドキュメントよりもQiita等のやってみた記事をよく読んでいましたが、公式ドキュメントを読むことの大切さを改めて実感しました。
また、開発環境でテストを行う際は、本番環境にできるだけ近い形でテストすることが大切だということを実感しました。
今後は新しい技術を使う際は必ず公式ドキュメントを参照したいと思います。
読んでいただきありがとうございました。