競技プログラミング用テスト
モチベーション
ある日AtCoderにて人のコードを眺めていたところテストを搭載したスニペットを使っている人がいました1。
「かっこいい❤️」
自分でも作ってみました。
実装
fn main() {
// 入力
let n = input::<usize>();
let a = input::<usize>();
// 何らかの処理
// 出力
println!("{}", max_ave);
println!("{}", cnt);
}
#[cfg(test)]
mod tests {
#[test]
fn tester() {
// テストケースをここに書く
// (入力, 期待する出力)
let inputs = [
("
5 2 2
1 2 3 4 5
", "
4.500000
1
"),
("
4 2 3
10 20 10 10
", "
15.000000
3
"),
];
for (input, expected) in inputs.iter() {
call(input, expected.to_string());
}
}
fn call<T: AsRef<str>>(input: T, expected: String) {
use std::process::{Command, Stdio};
use std::io::{Read, Write};
let mut cmd_echo = Command::new("echo")
.arg(input.as_ref())
.stdout(Stdio::piped())
.spawn()
.unwrap();
let mut cmd_run = Command::new("cargo")
.arg("run")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.unwrap();
// 実行と標準出力の受け取り
if let Some(ref mut stdout) = cmd_echo.stdout {
if let Some(ref mut stdin) = cmd_run.stdin {
let mut buf: Vec<u8> = Vec::new();
stdout.read_to_end(&mut buf).unwrap();
stdin.write_all(&buf).unwrap();
}
}
let res = cmd_run.wait_with_output().unwrap().stdout;
let res_string = String::from_utf8(res.to_vec()).unwrap();
// convert '\n' into space
let actual = res_string
.replace("\n", " ")
.trim_end_matches(' ')
.trim_start_matches(' ')
.to_owned();
let expected = expected
.replace("\n", " ")
.trim_end_matches(' ')
.trim_start_matches(' ')
.to_owned();
// split into a vector
let actual = actual
.split(' ')
.map(|s| s.parse::<f64>().unwrap())
.collect::<Vec<_>>();
let expected = expected
.split(' ')
.map(|s| s.parse::<f64>().unwrap())
.collect::<Vec<_>>();
assert_eq!(actual, expected);
}
}
実行
$ cargo test
工夫した点
fn main() {
// 入力
let n = input::<usize>();
let a = input::<usize>();
// 何らかの処理
// 出力
println!("{}", max_ave);
println!("{}", cnt);
}
#[cfg(test)]
mod tests {
#[test]
fn tester() {
// テストケースをここに書く
// (入力, 期待する出力)
let inputs = [
("
5 2 2
1 2 3 4 5
", "
4.500000
1
"),
("
4 2 3
10 20 10 10
", "
15.000000
3
"),
];
for (input, expected) in inputs.iter() {
call(input, expected.to_string());
}
}
fn call<T: AsRef<str>>(input: T, expected: String) {
use std::process::{Command, Stdio};
use std::io::{Read, Write};
let mut cmd_echo = Command::new("echo")
.arg(input.as_ref())
.stdout(Stdio::piped())
.spawn()
.unwrap();
let mut cmd_run = Command::new("cargo")
.arg("run")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.unwrap();
// 実行と標準出力の受け取り
if let Some(ref mut stdout) = cmd_echo.stdout {
if let Some(ref mut stdin) = cmd_run.stdin {
let mut buf: Vec<u8> = Vec::new();
stdout.read_to_end(&mut buf).unwrap();
stdin.write_all(&buf).unwrap();
}
}
let res = cmd_run.wait_with_output().unwrap().stdout;
let res_string = String::from_utf8(res.to_vec()).unwrap();
// convert '\n' into space
let actual = res_string
.replace("\n", " ")
.trim_end_matches(' ')
.trim_start_matches(' ')
.to_owned();
let expected = expected
.replace("\n", " ")
.trim_end_matches(' ')
.trim_start_matches(' ')
.to_owned();
// split into a vector
let actual = actual
.split(' ')
.map(|s| s.parse::<f64>().unwrap())
.collect::<Vec<_>>();
let expected = expected
.split(' ')
.map(|s| s.parse::<f64>().unwrap())
.collect::<Vec<_>>();
assert_eq!(actual, expected);
}
}
$ cargo test
工夫した点
先述したサイト1の実装はsolve関数に回答のための主要な処理を書き、main関数から呼び出していました。テストでは
solve関数を呼び出し、入力は全rustaceanがいいねしたであろうtanakhさんのinputマクロ2に手を加えたものを使用していました。
これに対し自作のテストはmain関数をテストから完全に独立させて自由に書けるようにしました。
コードについて
TopCoder や AtCoder は改行とスペースを区別しないらしいので改行コードを全てスペースに直しています。
テストケース
テストケースはinputs変数 Vec<()>
に書いている
のですが、先述したサイト1のFireFox拡張を使えば
よりスッキリ書くことができると思います今度試してみます。
感想
シェルのパイプ処理がクレートなしで書けたのがよかったです
だけど少し複雑で大変だったです。
その他
こうした方がいいよなど思う所がありましたら是非コメントください❤️
参考
Author And Source
この問題について(競技プログラミング用テスト), 我々は、より多くの情報をここで見つけました https://qiita.com/Cassin01/items/930bf3cf728c410ad38e著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .