Rustでテスト駆動開発

この記事は私のRustでテスト駆動開発の練習の記録です。 これまで求められなかったのもあり、テスト駆動開発はおろかテストもやったことがありません。 でもIT系の色々な情報を見て、「流石に全然テスト使ったこともありません」では宜しくないかなと 思ったので、簡単なお題を元にテスト駆動開発の練習をしてみようかなと思います。 ちなみに言語はRustを使います。

今回のお題は、「1を加算する関数をテスト駆動開発で作る」です。

とりあえず、こんな感じでコードを書いてみました。

//! 「Hello, world!」と、5+1の計算結果を出力するプログラム

fn main() {
    println!("Hello, world!");
    /* こんなプログラム(1加算した結果を出力する)を作りたい
    let arg = 5;
    println!("{} + 1 = {}", arg, add_one(5));
    */
    return;
}

fn add_one(num: u32) {
    return;
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_works() {
        assert_eq!(2, add_one(1));
        assert_eq!(3, add_one(2));
        assert_eq!(4, add_one(3));
        assert_eq!(17, add_one(16));
        assert_eq!(122, add_one(121));
    }
}

まず、main関数で行いたい関数を記述しましたが、 その中で使われる"add_one()"関数はまだ出来てないので一旦コメントアウトしています。

次にadd_one関数ですが、最初は空の関数にしています。

そして本題のテスト関数。it_worksの中に、add_one関数で期待する出力結果を、 assert関数としていくつかを書いています。 いくつか書いているのはより信頼性を上げるためですね。 1つだけ合っていてもそれで本当に関数が正しく動いているか不安なので。 ここでは単純に1を加算するだけなので正直不要ですが、 複雑になってくると役に立つのかなぁと思ったりします。

さて、これでまずcargo runをしてみると、 ワーニングが出るものの実行はできて、hello world!が出力されます。

そしてcargo testをしてみるとどうなるかというと、エラーがたくさん出ます。 これはまだadd_one関数内で1加算する処理を記述していないので当然ですね。

では、add_one関数を、所望の動作をするように記述を変更していきます。 変更結果は下記です。

//! 「Hello, world!」と、5+1の計算結果を出力するプログラム

fn main() {
    println!("Hello, world!");
    /* こんなプログラム(1加算した結果を出力する)を作りたい
    let arg = 5;
    println!("{} + 1 = {}", arg, add_one(5));
    */
    return;
}


fn add_one(num: u32) -> u32 {
    return num + 1;
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_works() {
        assert_eq!(2, add_one(1));
        assert_eq!(3, add_one(2));
        assert_eq!(4, add_one(3));
        assert_eq!(17, add_one(16));
        assert_eq!(122, add_one(121));
    }
}

これでcargo testをするとどうなるかというと、無事にOKと出ます。 これでテストは通過しましたので、テストしたadd_one関数を使いたい場所である メイン関数内の処理を少し変えていきたいと思います。

これまではまだ処理が完成していないということでその部分をコメントアウトしましたが、 もうテストも通過して関数が完成したので、コメントアウトを外します。

外した後は以下のような記述になります(上のコードからコメントアウトを外しただけです)

//! 「Hello, world!」と、5+1の計算結果を出力するプログラム

fn main() {
    println!("Hello, world!");

    let arg = 5;
    println!("{} + 1 = {}", arg, add_one(5));

    return;
}


fn add_one(num: u32) -> u32 {
    return num + 1;
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_works() {
        assert_eq!(2, add_one(1));
        assert_eq!(3, add_one(2));
        assert_eq!(4, add_one(3));
        assert_eq!(17, add_one(16));
        assert_eq!(122, add_one(121));
    }
}

これでcargo runをすると結果は

Hello, world!
5 + 1 = 6

と、無事に書こうと思っていたプログラムを書くことができました。

今回はこれで終わりです。またテスト駆動開発の練習記事を上げたいなと思います。