競プロのテストをgo test
でやりたかったので作った。
競技プログラミング*(以下競プロ)*でよく使われる、 標準入力からデータを取得して標準出力へ結果を吐き出すプログラムを簡単にテストしたかった。というお話。
いきさつ
競プロは、いくつかテストケースとその回答が与えられており事前にテストできるようになってます。
しかし動作確認のたびに「テストケースをコピーして…」とかやってたので非常に効率が悪い……
時間との戦いでもあるし、こんな事で時間使いたくねぇな…
「これ自動化できないかな……テストなんだしgo test
とかでテストできるならむっちゃ楽。」
リポジトリ / 実行イメージ
という事で自動化してしまったのがこちらになります。
github.com/0Delta/GolangSkeletonForSpeedrun
使い方はREADME.md
か本体コードをどうぞ。
実装
標準出力の取得
テストなので、結果を変数に格納して期待値と同じか評価する必要があります。
…が、結果は標準出力に吐き出してしまいます。
これは、テストコードに定義してあるcaptureStdout
を噛ませ、一時的に標準出力を表すos.Stdout
を自作パイプに置き換えることで実現させてます。
こちらは先人の知恵を丸パク借りていますので、詳細はこちら -> Goで標準出力をテストする方法
標準入力の代替
テストなので、標準入力へのデータ入力は自動化したいです。可能なら通常のテストと同じように、配列とかに格納してfor
で一気に行きたい。
ここはメイン処理を少し変更することで対応しました。
getLine
で、プログラムの引数が存在する場合はその最後、ない場合は標準入力を取得するようにしています。
何故最後なのかというと、go test
の後に続くフラグの数がわからないから。入力が一行だけなのであれば、コレで十分です。(つまり複数行には非対応)
後は、テストコード側でプログラムの引数を表すos.Args
に入力されるべき文字列を追加してあげればテスト時は変数を、通常実行時は標準入力を見るようになります。
で、どうなった?
めっちゃ良い
思いっきり自画自賛だが気にしない。
結果がわかりやすいし自分でテストケース増やすことも簡単、go test
はGoの標準機能なのでほぼ全ての開発環境で使えて親和性もバッチリです。
これでスケルトンを作ってしまったので、競プロが開催されたときに「標準入力からの取得どうすんだっけ…」とか「動作確認の度にテストケースをコピーして目で確認して…」とかいう悩みから完全開放され、問題を解く為に全時間を捧げることができるのが一番良いですね。
以上!
皆さんもテストを自動化して、良き競プロライフを。