Terraform v1.6でTerraform testを試し、S3バケット名の確認を行った

# やりたいこと
・2023/08にリリースされたv1.6のTerraform testの動作を知りたい

# 前提
・AWSアカウント作成済み
・AWS IAMユーザーを作成し、access_keyとsecret_keyを発行済み
・Terraformインストール済み
　（v1.6であること）
・AWS CLIインストール済み
・VSCODEインストール済み
　（お好みのエディターで大丈夫）
・Pythonインストール済み
　（今回はpython3.9でlambadaを作ってみたいですが、極簡単なソースコードなのでバージョンどうてもいいかと思う）

# 環境
```
$ terraform -v 
Terraform v1.6.0
on windows_amd64
+ provider registry.terraform.io/hashicorp/aws v5.19.0

$ python -V
Python 3.9.13

```
# 構築リソース
・AWS S3

# ディレクトリ構成
```ruby:qiita.rb
root 　　   
  ┣━ main.tf
  ┣━ variables.tf
  ┗━ main.tftest.hcl
```

# ソースの中身

## main.tf
・provider情報（AWS）を記載
・今回は便宜上、作成したいS3のresource blockもmain.tfに書く

```ruby:main.tf
# AWS プロバイダの設定
provider "aws" {
  access_key = var.access_key
  secret_key = var.secret_key
  region     = var.region
}

resource "aws_s3_bucket" "main" {
  bucket = "test202310061024"
}
```

## variables.tf
・variables.tfに全ソース共通の変数を書く
・AWSアクセス情報をコードに記載するのはセキュリティ上よくないという観点があるので、Windows環境変数に書くなど、やり方はほかにいろいろある。。。

```ruby:variables.tf
variable "region" {
  default = "ap-northeast-1"
}

variable "access_key" {
  default = "自分のaccess_key"
}

variable "secret_key" {
  default = "自分のsecret_key"
}
```

## main.tftest.hcl（テストファイル本体）
・「S3のバケット名が正しく設定されたか」という確認をしたい

```ruby:main.tftest.hcl
run "test_s3_name" {
  assert {
    condition = aws_s3_bucket.main.bucket == "test202310061024" # テストする内容
    error_message = "バケット名の値が予期した名称と一致しませんでした" # エラーメッセージ
  }
}
```
# 実行

## 一回目：余計にterraform applyをやったのでテスト失敗
いままで通りのコマンドで、先にS3リソースを構築したんですけど、

```
terraform plan
```
```
terraform apply
```

テストを実行すると
```
terraform test
```
「あなたはすでにこのバケットを持っているよ」って怒られた。。。
```ruby:実行結果
Error: creating Amazon S3 (Simple Storage) Bucket (test202310061024): BucketAlreadyOwnedByYou:
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3538617/4e2cde6e-9f5e-fea6-15c8-49c293d257b1.png)

こちらのサイトでによると、

「**各テストファイルで指定された構成内でインフラストラクチャをプロビジョニングする(プロビジョニングを省略する＝planのみでテストすることも可能)**」、とのことでした。。。

https://www.ntt-tx.co.jp/column/iac/230908/

要は、「**terraform applyで実際リソースを構築しなくても、構築前テストできる、リソースのパラメータがちゃんと設定されているかチャックできる**」というのは、Terraform testのメリットらしいので、

逆に、余計にterraform applyしたら、「**Terraform testは既存のリソースに対してテストできない**」ということですかね。。。



## 二回目：terraform applyの前にテストしたら成功！
先ほどは作ってしまったリソースを削除してから、テストを実行すると、
```
terraform test
```
ちゃんとバケット名の値をチェックしてくれたそうです！
```ruby:実行結果
main.tftest.hcl... in progress
  run "test_s3_name"... pass
main.tftest.hcl... tearing down
main.tftest.hcl... pass

Success! 1 passed, 0 failed.
```

## 三回目：わざと失敗させてみる
テストケースを微修正し、バケット名チェックを「test202310061024-fail」して、もう一回実行すると、

```ruby:main.tftest.hcl
run "test_s3_name" {
  assert {
    condition = aws_s3_bucket.main.bucket == "test202310061024-fail" # テストする内容
    error_message = "バケット名の値が予期した名称と一致しませんでした" # エラーメッセージ
  }
}
```
```
terraform test
```
ちゃんとバケット名の不一致を検知し、エラーメッセージを出してくれた！

```ruby:実行結果
main.tftest.hcl... in progress
  run "test_s3_name"... fail
╷
│ Error: Test assertion failed
│
│   on main.tftest.hcl line 10, in run "test_s3_name":
│   10:     condition = aws_s3_bucket.main.bucket == "test202310061024-fail" # テストする内容
│     ├────────────────
│     │ aws_s3_bucket.main.bucket is "test202310061024"
│
│ バケット名の値が予期した名称と一致しませんでした
╵
main.tftest.hcl... tearing down
main.tftest.hcl... fail

Failure! 0 passed, 1 failed.
```

# 終わりに
2023/06にリリースされたimport blockの続きに、terraform testもリリースされて、単体テストっぽい動きができるようになりました！Terraformがどんどん進化して便利になりましたね！