俺が
俺の為に AWS の EC2 インスタンスや AMI, タグ等を操作する作ったツールをいくつかリリースしている.
ほとんどを
見よう見まねの Go 言語で作っているので, なかなか Go 言語の雰囲気 (ディレクトリ構成やパッケージ管理とかも) に慣れないし, ちゃんとテストも書けていないのでずーっと修行が必要である.
直近で作ったやつは
SSM パラメータストアを操作するやつ
業務でパラメータストアを操作する必要があったので, これまでのノウハウを最大限に活かすことで二時間位でリリース出来た. この手をツールを作ると必ず公式のドキュメントを斜め読みし, AWS CLI のドキュメントのパラメータに寄せようとするので, 地味にそのサービスの勉強にもなることに気付いた. さらに, 単純な API のラッパーでしかないので, わざわざ Go 言語で書く必要は無いのかなーと思うことがあるが, MacOS や Linux, Windows 環境で動かすことが出来たり, インストールの手順も簡素化出来るという点では Go 言語で書くメリットは十分にあると考えている.
今回作った pStore については, まだまだ改修の余地はあるが, 以下のようにパラメータストアに登録しているパラメータの一覧, パラメータの追加, 削除がいい感じで行えるはず.
# パラメータの一覧取得 $ pStore +-------------------------------------+--------------------------+--------------+---------------------+ | NAME | VALUE | TYPE | LASTMODIFIEDDATE | +-------------------------------------+--------------------------+--------------+---------------------+ | /123456/88888 | kawahara-test | StringList | 2018-09-29 08:09:43 | | test.test1 | ****************** | SecureString | 2018-09-28 22:42:23 | +-------------------------------------+--------------------------+--------------+---------------------+ # パラメータの追加 $ pStore -put -name="foooooon" -value="baaaaaaarn" $ pStore +-------------------------------------+--------------------------+--------------+---------------------+ | NAME | VALUE | TYPE | LASTMODIFIEDDATE | +-------------------------------------+--------------------------+--------------+---------------------+ | /123456/88888 | kawahara-test | StringList | 2018-09-29 08:09:43 | | foooooon | baaaaaaarn | String | 2018-09-29 08:37:53 | | test.test1 | ****************** | SecureString | 2018-09-28 22:42:23 | +-------------------------------------+--------------------------+--------------+---------------------+ # パラメータの削除 $ pStore -del -name="foooooon" $ pStore +-------------------------------------+--------------------------+--------------+---------------------+ | NAME | VALUE | TYPE | LASTMODIFIEDDATE | +-------------------------------------+--------------------------+--------------+---------------------+ | /123456/88888 | kawahara-test | StringList | 2018-09-29 08:09:43 | | test.test1 | ****************** | SecureString | 2018-09-28 22:42:23 | +-------------------------------------+--------------------------+--------------+---------------------+
詳しくは README を見てねとなる.
コマンドラインツールのテストをどうするか
AWS のリソースをどうやって用意するか
AWS のリソースに対してどのようにテストするか. いくつか参考になる記事を既に書かれている方がいらっしゃってとても参考になった.
有難うございます.
特に冒頭の記事に紹介されていた dockertest というモジュールは次のタイミングで利用してみたい. (今回は docker-compose を利用している)
ということで, 今回のテストについては AWS 環境は moto を利用することにした.
moto には moto_server というサーバーモードが用意されているので, このサーバーモードを利用して擬似的に API レスポンスを返す環境を用意した. また, moto_server は docker-compose を利用して起動するようにしてみた.
コマンドの出力結果をテストする
コマンドラインツールの出力をテストする場合, どのような方法が良いのかは以下の記事やスライドがとても参考になった.
出力結果をテストするということは, I/O に依存するテストということになるらしい.
I/O に依存するテストの例として, Ruby の場合だと StringIO クラスを利用してテストを書くと良いようだ.
require "rspec" describe "stdout をテストする." do it "hello が出力されること." do $stdout = StringIO.new puts "hello" output = $stdout.string expect(output).to eq("hello\n") $stdout = STDOUT end end
これを実行すると, 以下のように出力される.
$ rspec test_spec.rb --format documentation stdout をテストする. hello が出力されること. Finished in 0.00374 seconds (files took 0.18315 seconds to load) 1 example, 0 failures
Go 言語だと bytes.Buffer を利用すると良いとのこと.
package main import ( "bytes" "os/exec" "testing" ) func TestCommand(t *testing.T) { cmd := exec.Command("echo", "hoge") stdout := new(bytes.Buffer) cmd.Stdout = stdout _ = cmd.Run() if stdout.String() != "hoge\n" { t.Fatal("Not matched") } }
これを実行すると, 以下のように出力される.
$ go test -v === RUN TestCommand --- PASS: TestCommand (0.01s) PASS ok go-test 0.016s
ということで, pStore のテストは
実行してみると, 以下のような出力になる.
$ make test Creating network "tests_default" with the default driver Creating moto-server ... done === RUN TestVersionFlag --- PASS: TestVersionFlag (1.54s) === RUN TestStdoutList --- PASS: TestStdoutList (1.60s) === RUN TestStdoutPut --- PASS: TestStdoutPut (3.33s) === RUN TestStdoutDel --- PASS: TestStdoutDel (3.33s) === RUN TestStdoutPutSecure --- PASS: TestStdoutPutSecure (4.43s) === RUN TestStdoutPutList --- PASS: TestStdoutPutList (4.93s) === RUN TestConvertDate --- PASS: TestConvertDate (0.00s) PASS ok pStore 19.186s Stopping moto-server ... done Removing moto-server ... done Removing network tests_default
ただ, これだけなんだけど.
以上
永遠の初心者が「俺のツールス」を通して, 少しでもプログラミングのスキルが上がると嬉しいなと思っている.