Rust、使ってみたいなぁって思って、いつもやってるAtCoderで試してみようと思いました。

はじめに – AtCoderコンテストにRustで参加するためのガイドブック

を参考に、テストのあたりを改良してみました。実際に解くのはまだやってないです……

いろいろインストール

上記を参考にRustをインストール。さらにcargo-generateのインストール(同ガイドブック。以下略)をします。

ガイドに従って雛形のプロジェクトをゲットします

$ cargo generate --git https://github.com/rust-lang-ja/atcoder-rust-base --branch ja
?  Project Name: abc000
?   Creating project called `abc000`...
✨   Done! New project created /Users/ユーザー/programing/Rust/abc000

Project Name:のあとのabc000は自分で入力。

$ cd abc000

移動。

中身

    • abc000/src/main.rs

 

    • ここに解答を書く。

 

    abc000/testsテスト関係。主にここをいじる

カスタマイズ

テストケースの作成のところに、Rustのテスト機能を使ってテストケースを試す方法が載ってます。ただ、テストケースがプログラム中に書き込んであって ちょっとカッコ悪い/コピペする時位置調整がめんどい のでファイルから読み込むようにします。

rust: ファイル読み書き – nju33 を参考にabc000/tests/sample_inputs.rsを以下のように書き換えます。

use std::fs;
use cli_test_dir::*;

#[test]
fn sample() {
  let input = fs::read_to_string("tests/input.txt").unwrap();
  let output = fs::read_to_string("tests/output.txt").unwrap();

  let testdir = TestDir::new("main", "");
  let res = testdir.cmd()
    .output_with_stdin(input)
    .tee_output()
    .expect_success();
  assert_eq!(res.stdout_str(), output);
  assert!(res.stderr_str().is_empty());
}

途中の.tee_output()は、出力をテスト結果画面に出力するオプション、のようなものなので出力が長いとき等は削るのもあり。

さらに、入出力サンプルを入れるファイルをabc000/tests/input.txt・abc000/tests/output.txtと作成します。ガイドライン通りに雛形をゲットしているとABC086 – C – Travelingの解答コードが入っているので、それに合わせて

2
3 1 2
6 1 1

Yes

とします。(特にoutput、最後の改行をやらないと一致判定で失敗するので注意)

お試し

テストしてみます。

$ cargo build

これはこのプロジェクトを使う前準備的なもの、らしい。proconioを使えるようにしたりする。

$ cargo test
   Compiling abc000 v0.1.0 (/Users/ユーザー/programing/Rust/abc000)
    Finished test [unoptimized + debuginfo] target(s) in 1.64s
     Running target/debug/deps/main-028731574152944b

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/sample_inputs-c49f316d7d463d6e

running 1 test
Yes
test sample ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

サンプルの通過が判定できました!あとは各ケースをコピペすればいい。ctrl+Actrl+Vで全体を上書きできるので楽。

さらに改良

一致判定はしないで、単に出力をしてみたいときもあるのでabc000/tests/sample_inputs.rsを書き換えます。

use std::fs;
use std::io::Write; //new!!
use cli_test_dir::*;

#[test]
fn sample() {
  let input = fs::read_to_string("tests/input.txt").unwrap();
  let output = fs::read_to_string("tests/output.txt").unwrap();

  let testdir = TestDir::new("main", "");
  let res = testdir.cmd()
    .output_with_stdin(input)
    .tee_output()
    .expect_success();
//assert_eq!(res.stdout_str(), output); ここじゃなくて
  assert!(res.stderr_str().is_empty());

  //new!!
  let mut file = fs::File::create("tests/view.txt").unwrap();
  write!(&mut file, "{}", res.stdout_str()).unwrap();

  assert_eq!(res.stdout_str(), output); //後ろに回す
}

Rust – ファイルに書き込む | rust Tutorial を参考にしました。出力をabc000/tests/view.txtに書き出してくれます。

テストはエラーが出た時点で終了してしまうので、output.txtとの一致判定は最後に回しました。とにかくview.txtに出力して欲しいので。

おしまい

Rust、入力がめっちゃめんどくさい雰囲気だったんですけどproconioなるクレート(ライブラリ的な?)のおかげで楽にできます。ありがてぇ。

参考

    • AtCoderコンテストにRustで参加するためのガイドブック

 

    • rust: ファイル読み書き – nju33

 

    Rust – ファイルに書き込む | rust Tutorial
广告
将在 10 秒后关闭
bannerAds