0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS CLIのスクリプトをAIに書かせたら、テストまで任せてみる

0
Last updated at Posted at 2026-10-31

image.png

生成AIにスクリプトを書いてもらうとき、「書いて」で終わらず、期待どおりに動くかの検証まで依頼すると、成果物が変わります。

今回は、指定したEC2を1台停止するスクリプトを、AWSへ接続せずにテストします。

停止要求と停止完了を分ける

処理は次の3段階です。

停止を要求する → 停止完了を確認する → 成功を表示する

AWS CLIには、停止を要求するstop-instancesと、停止状態になったかを15秒ごとに確認するwait instance-stoppedがあります(40回、約10分で確認できなければ失敗します)。停止要求・停止完了の確認

停止要求が通っただけで、停止完了と判断しないようにします。

次をstop-ec2.shとして保存します。

#!/usr/bin/env bash
set -euo pipefail
export AWS_PAGER=""
export AWS_CLI_AUTO_PROMPT=off

if [[ $# -ne 2 || -z "$1" || -z "$2" ]]; then
  echo "Usage: $0 REGION INSTANCE_ID" >&2
  exit 2
fi
region=$1
instance_id=$2

if ! aws ec2 stop-instances \
  --region "$region" --instance-ids "$instance_id" >/dev/null; then
  echo "Stop request failed: $instance_id" >&2
  exit 1
fi

if ! aws ec2 wait instance-stopped \
  --region "$region" --instance-ids "$instance_id"; then
  echo "Could not confirm stopped state: $instance_id" >&2
  exit 1
fi

echo "Stopped: $instance_id"

偽物のawsコマンドに差し替える

実AWSで都合よく失敗を起こす必要はありません。

一時ディレクトリにawsという実行ファイルを作り、そのディレクトリをPATHの先頭に追加します。検証対象のスクリプトは変更せず、外部コマンドだけを差し替えます。

偽物は1本です。環境変数TEST_CASEで動きを切り替えます。

TEST_CASE 偽物の動作
success 停止要求・完了確認とも成功
stop-failure 停止要求が失敗
wait-failure 停止要求は成功し、完了確認が失敗

さらに、呼ばれたコマンドをファイルへ記録します。これで「停止要求が失敗したら、完了確認を呼ばない」ことや、「引数が足りなければ、awsを一度も呼ばない」ことも検証できます。

テストを実行する

次を、同じディレクトリのtest-stop-ec2.shとして保存します。

#!/usr/bin/env bash
set -euo pipefail
script_dir=$(cd "$(dirname "$0")" && pwd)
test_dir=$(mktemp -d)
trap 'rm -rf "$test_dir"' EXIT
fake_bin="$test_dir/bin"
mkdir "$fake_bin"

# 偽物のawsを作る
cat > "$fake_bin/aws" <<'FAKE'
#!/usr/bin/env bash
set -eu
printf '%s\n' "$*" >> "$AWS_CALL_LOG"
case "$1 $2" in
  "ec2 stop-instances")
    [[ "$TEST_CASE" != "stop-failure" ]]
    ;;
  "ec2 wait")
    [[ "$3" == "instance-stopped" ]]
    [[ "$TEST_CASE" != "wait-failure" ]]
    ;;
  *)
    echo "Unexpected command: $*" >&2
    exit 99
    ;;
esac
FAKE
chmod +x "$fake_bin/aws"

# ケースごとに終了コード・出力・呼び出し記録を取得する
run_case() {
  local name=$1 expected_status=$2 status=0
  TEST_CASE="$name" \
  AWS_CALL_LOG="$test_dir/$name.log" \
  PATH="$fake_bin:$PATH" \
  bash "$script_dir/stop-ec2.sh" \
    ap-northeast-1 i-0123456789abcdef0 \
    > "$test_dir/$name.out" 2> "$test_dir/$name.err" || status=$?
  test "$status" -eq "$expected_status"
}

# 期待する呼び出しと出力を用意する
printf '%s\n' \
  'ec2 stop-instances --region ap-northeast-1 --instance-ids i-0123456789abcdef0' \
  > "$test_dir/stop-only.expected"

cat "$test_dir/stop-only.expected" > "$test_dir/both.expected"
printf '%s\n' \
  'ec2 wait instance-stopped --region ap-northeast-1 --instance-ids i-0123456789abcdef0' \
  >> "$test_dir/both.expected"

printf 'Stopped: i-0123456789abcdef0\n' > "$test_dir/success.expected"

# 正常系
run_case success 0
diff -u "$test_dir/success.expected" "$test_dir/success.out"
test ! -s "$test_dir/success.err"
diff -u "$test_dir/both.expected" "$test_dir/success.log"
echo 'PASS: success'

# 停止要求が失敗したら、完了確認を呼ばない
run_case stop-failure 1
test ! -s "$test_dir/stop-failure.out"
grep -Fq 'Stop request failed: i-0123456789abcdef0' "$test_dir/stop-failure.err"
diff -u "$test_dir/stop-only.expected" "$test_dir/stop-failure.log"
echo 'PASS: stop-failure'

# 完了確認が失敗したら、成功を表示しない
run_case wait-failure 1
test ! -s "$test_dir/wait-failure.out"
grep -Fq 'Could not confirm stopped state: i-0123456789abcdef0' "$test_dir/wait-failure.err"
diff -u "$test_dir/both.expected" "$test_dir/wait-failure.log"
echo 'PASS: wait-failure'

# 引数が足りなければ、awsを呼ばない
status=0
AWS_CALL_LOG="$test_dir/usage.log" \
PATH="$fake_bin:$PATH" \
bash "$script_dir/stop-ec2.sh" ap-northeast-1 \
  > "$test_dir/usage.out" 2> "$test_dir/usage.err" || status=$?
test "$status" -eq 2
grep -Fq 'Usage:' "$test_dir/usage.err"
test ! -e "$test_dir/usage.log"
echo 'PASS: usage'

実行します。

bash test-stop-ec2.sh

成功すると次が表示されます。

PASS: success
PASS: stop-failure
PASS: wait-failure
PASS: usage

確認しているのは、終了コード・標準出力・標準エラー・呼び出したコマンドと順序です。

testやdiffが期待との違いを検出すると、テストスクリプトは失敗終了します。一時ディレクトリは実行ごとに作るので、前回のログが混ざりません。終了時にはtrapで削除します。

AIには、壊した場合も確認させる

今回のコードは、上記の4ケースが通ることを実行して確認しました。

さらに、検証対象を一時的に変更しました。

意図的に加えた変更 結果
停止完了の確認を削除 テストが失敗
完了確認の失敗を無視 テストが失敗
停止対象を別のIDに変更 テストが失敗
引数チェックを削除 テストが失敗

正しいコードで通り、仕様を壊すと落ちる。 テスト自体も、このように確かめられます。

AIへの依頼も具体的にします。

偽物のawsコマンドをPATHの先頭に置き、スクリプトを実行して検証してください。正常系・停止要求の失敗・完了確認の失敗・引数不足を再現し、終了コード、出力、呼び出し記録を照合してください。意図的に壊した場合にテストが落ちることと、未確認の範囲も報告してください。

検証した範囲を明確にする

このテストで確認したのは、スクリプトの分岐・引数・出力です。本物のAWS CLIは呼ばず、EC2も停止していません。

認証、IAM権限、AWS CLI自体の待機動作は、停止してよい検証用インスタンスで別途確認します。また、完了確認の失敗は「停止状態を確認できなかった」という意味であり、「EC2が必ず稼働中」という意味ではありません。

AIにはコードだけでなく、実行したテスト、結果、未確認の範囲まで成果物にしてもらう。短いスクリプトでも、そこまで依頼する価値があります。

apios.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?