概要
- laravelのテストコードで実際にストレージにファイルを設置して
前提
- ローカル開発環境はDockerである。
- バケットはローカル用とローカルテスト用で別に用意されているものとする。
- MiniOコンテナとの接続は完了しており、バケットもすでに作成されているものとする。
方法
-
下記の内容をFeatureテストのテストクラスのsetUpとtearDownに記載する。
Test.phppublic function setUp(): void { parent::setUp(); // シーダーの実行 $this->seed(); Mail::fake(); $this->minioCleanUp(); } public function tearDown(): void { $this->minioCleanUp(); parent::tearDown(); } /** * テスト用MiniOのpublicバケットの初期化 * * @return void */ private function minioCleanUp(): void { // ディスクの確認(ローカルだとMiniOだけどs3のdiscの設定を流用している) $isS3 = config('filesystems.default') === 's3'; // テスト用ストレージの初期化 $bucketName = strtolower(config('filesystems.disks.s3.bucket')); $isIncludeTestToBucketName = strpos($bucketName, 'test') !== false; if ($isS3 && $isIncludeTestToBucketName) { $files = Storage::allFiles('/'); Storage::delete($files); } }
ポイント
-
単純に「テストメソッド実行前にバケット内をクリーンアップする」だけならこんなたくさん記述する必要はない。下記の内容をそれぞれsetUpとtearDownの中に記載すれば良い。
$files = Storage::allFiles('/'); Storage::delete($files);
-
ただし、これはあくまでテスト実行時の.env.testingのバケット系の記載に誤りがないという大前提のもと成り立つ。
-
もし仮に、.env.testingのバケット名の指定を間違えてテスト用バケットではなくメイン用バケットになっていたらどうなるだろうか。
-
実際にエンドユーザーが使用する環境でテストコードは基本実行しないが、なにかの間違いでS3の全オブジェクトクリーンアップ処理が走ってしまったら大事故になる。
-
そのため今回のコードでは念のため確認処理を挟んでいる。
-
具体的には下記の内容を確認し、両方ともtrueだったらクリーンアップをするようにしている。
- 指定ストレージディスクがs3になっている
- バケット名に
test
という文字列が入っている
-
$isIncludeTestToBucketName = strpos($bucketName, 'test') !== false;
の部分について-
一見
$isIncludeTestToBucketName = strpos($bucketName, 'test');
で良さそうに見える。 -
しかし
!== false
は絶対必要である。 -
strpos()という組み込み関数は第一引数の文字列の中に第二引数の文字列があるかをチェックしている。
-
ヒットしなかったらfalseかfalseと判定される値が返される。
-
ヒットした場合、「第一引数の何文字目でヒットしたか」をintで返す。
-
下記のような場合strpos()は3を返す。(最初の文字を0としてカウントしているため)
strpos('aaatest', 'test');
-
下記のような場合strpos()は0を返す。
strpos('testaaa', 'test');
-
0番目でヒットしてしまったとき0を返す。intの0はfalseと判定される。そのため
$isIncludeTestToBucketName = strpos($bucketName, 'test');
だと、0番目でヒットして、testという文字が評価対象の文字列に含まれているのにも関わらず、falseとして扱われるためである。
-