Edited at

競プロのテストを「go test」でやりたかったので作った


競プロのテストをgo testでやりたかったので作った。

競技プログラミング(以下競プロ)でよく使われる、 標準入力からデータを取得して標準出力へ結果を吐き出すプログラムを簡単にテストしたかった。というお話。


いきさつ

競プロは、いくつかテストケースとその回答が与えられており事前にテストできるようになってます。

しかし動作確認のたびに「テストケースをコピーして…」とかやってたので非常に効率が悪い……

時間との戦いでもあるし、こんな事で時間使いたくねぇな…

「これ自動化できないかな……テストなんだしgo testとかでテストできるならむっちゃ楽。」


リポジトリ / 実行イメージ

という事で自動化してしまったのがこちらになります。

github.com/0Delta/GolangSkeletonForSpeedrun

使い方はREADME.mdか本体コードをどうぞ。

image.png


実装


標準出力の取得

テストなので、結果を変数に格納して期待値と同じか評価する必要があります。

…が、結果は標準出力に吐き出してしまいます。

これは、テストコードに定義してあるcaptureStdoutを噛ませ、一時的に標準出力を表すos.Stdoutを自作パイプに置き換えることで実現させてます。

こちらは先人の知恵を丸パク借りていますので、詳細はこちら -> Goで標準出力をテストする方法


標準入力の代替

テストなので、標準入力へのデータ入力は自動化したいです。可能なら通常のテストと同じように、配列とかに格納してforで一気に行きたい。

ここはメイン処理を少し変更することで対応しました。

getLineで、プログラムの引数が存在する場合はその最後、ない場合は標準入力を取得するようにしています。

何故最後なのかというと、go testの後に続くフラグの数がわからないから。入力が一行だけなのであれば、コレで十分です。(つまり複数行には非対応)

後は、テストコード側でプログラムの引数を表すos.Argsに入力されるべき文字列を追加してあげればテスト時は変数を、通常実行時は標準入力を見るようになります。


で、どうなった?

めっちゃ良い

思いっきり自画自賛だが気にしない。

結果がわかりやすいし自分でテストケース増やすことも簡単、go testはGoの標準機能なのでほぼ全ての開発環境で使えて親和性もバッチリです。

これでスケルトンを作ってしまったので、競プロが開催されたときに「標準入力からの取得どうすんだっけ…」とか「動作確認の度にテストケースをコピーして目で確認して…」とかいう悩みから完全開放され、問題を解く為に全時間を捧げることができるのが一番良いですね。

以上!

皆さんもテストを自動化して、良き競プロライフを。