Atcoderのコンテストにチマチマでているのですが、最近Rustでテスト生成や提出ができるCLIツールを作っている方を見かけました。
https://github.com/tanakh/cargo-atcoder
丁度コンテスト時に入出力例をいちいち試すのが面倒だと感じていたので、Rubyでもテストを自動生成するGemをつくってみました。
使い方
インストール
gem install green_day
なりでインストールしてください。
ログイン
bundle exec green_day login
でユーザー名とパスワードを要求されるので入力してください。
Atcoderからのset-cookieの中身をcookie-storeというファイルに保存します。セッションを消したかったらこのファイルを削除してください。
セッションがないと開催中のコンテストにアクセスすることができません。
作業用ディレクトリ及びテストの作成
このコマンドでコンテスト用のディレクトリ及びテストを生成できます。
bundle exec green_day new <contest-name>
例えばabc150を対象にしたいときは下のようになります。
bundle exec green_day new abc150
こうするとこんな感じのディレクトリ構成になります。
abc150
├── A.rb
├── B.rb
├── C.rb
├── D.rb
├── E.rb
├── F.rb
└── spec
├── A_spec.rb
├── B_spec.rb
├── C_spec.rb
├── D_spec.rb
├── E_spec.rb
└── F_spec.rb
自動生成されるテストは例えばabc150のA問題ならこんな感じになります。
require 'rspec'
RSpec.describe 'test' do
it 'test with "2 900\\n"' do
io = IO.popen("ruby abc150/A.rb", "w+")
io.puts("2 900\\n")
io.close_write
expect(io.readlines.join).to eq("Yes\\n")
end
it 'test with "1 501\\n"' do
io = IO.popen("ruby abc150/A.rb", "w+")
io.puts("1 501\\n")
io.close_write
expect(io.readlines.join).to eq("No\\n")
end
it 'test with "4 2000\\n"' do
io = IO.popen("ruby abc150/A.rb", "w+")
io.puts("4 2000\\n")
io.close_write
expect(io.readlines.join).to eq("Yes\\n")
end
end
後はabc150/A.rb
に提出用のコードをそのまま書けばOKです。
n, m = gets.split.map(&:to_i)
if 500 * n >= m
puts "Yes"
else
puts "No"
end
いつものようにrspecでテストすることができます。
> rspec abc150/spec/A_spec.rb
...
Finished in 0.15933 seconds (files took 0.08655 seconds to load)
3 examples, 0 failures
テスト名に入力例をそのまま入れているのでテスト結果はそれをみて判断してください。
3) test test with "4 2000\n"
Failure/Error: expect(io.gets).to eq("Yes\n")
expected: "Yes\n"
got: "No\n"
(compared using ==)
Diff:
@@ -1,2 +1,2 @@
-Yes
+No
後書きとか
一応CIではRuby 2.7.0とAtcoder用にRuby2.3.3でテストしています。
(ローカルでは2.3系は入れるのが面倒だったので未確認です)
入出力例のスクレイピングは全コンテスト試したわけではないので、未対応のケースがあるかもしれません。もし見つけたら教えてくれると嬉しいです。
提出まわりはつくっていないのですが気が向いたら作ります。
2020/02/11追記
spec.files
を消したままなのを忘れてリリースしてました。
すいませんでした!!!!!!!!
修正しました!!!!!!!
2020/02/18追記
複数行の回答の出力に対応しました