Help us understand the problem. What is going on with this article?

競技プログラミング用テスト

More than 1 year has passed since last update.

モチベーション

ある日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

工夫した点

先述したサイト1の実装はsolve関数に回答のための主要な処理を書き、main関数から呼び出していました。テストでは
solve関数を呼び出し、入力は全rustaceanがいいねしたであろうtanakhさんのinputマクロ2に手を加えたものを使用していました。

これに対し自作のテストはmain関数をテストから完全に独立させて自由に書けるようにしました。

コードについて

TopCoder や AtCoder は改行とスペースを区別しないらしいので改行コードを全てスペースに直しています。

テストケース

テストケースはinputs変数 Vec<()>に書いている
のですが、先述したサイト1のFireFox拡張を使えば
よりスッキリ書くことができると思います今度試してみます。

感想

シェルのパイプ処理がクレートなしで書けたのがよかったです
だけど少し複雑で大変だったです。

その他

こうした方がいいよなど思う所がありましたら是非コメントください❤️

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした