RustでPrivateメソッドもファイルを分けてテストをしたい。

# はじめに
Privateメソッドのテスト要否に対する部分は一旦置いとく。
テストしたいぜー、でも、同じファイルに書くのは、テストコードが多くなりすぎて見通し悪くなるから避けたいぜー

みたいな感じで色々試行錯誤してたどり着いた（と言ってもモジュールの可視性とかの話を調べれば一発だったっぽい）
ので備忘録的にメモしているやつでござーます。

# とりあえず動かしてみたいという方へ
https://github.com/segfo/private_method_test_example

# シンプルにテストを書いてみよう
適当なプロジェクトを作ります。
```
cargo new testcode_example --lib
```
トップレベルのフォルダ構成
```
./
│   .gitignore
│   Cargo.lock
│   Cargo.toml
│
├───src
│       lib.rs
│
└───target
(snip)
```
それでは、`src/lib.rs`に以下を追記していきます
``` Rust:src/lib.rs
pub fn pow(x: u32) -> u32 {
    pow_impl(x)
}

fn pow_impl(x: u32) -> u32 {
    x * x
}

#[test]
fn pow_test() {
    let x = pow(2);
    assert_eq!(x, 4)
}
#[test]
fn pow_impl_test() {
    let x = pow_impl(2);
    assert_eq!(x, 4)
}
```

よいですね。ただ、テストが増えていくと見通しが悪くなってしまいます。
というわけで、テストは分けましょう。

あと、`src/lib.rs`に書き続けるのも自分の趣味ではないので計算をするので、別モジュール（math）へ集約しようと思います。

# テストを分ける前の準備（ファイル分割）
```
./
│   .gitignore
│   Cargo.lock
│   Cargo.toml
│
├───src
│   │   lib.rs
│   │
│   └───math <-- 新しく作ったディレクトリ
│           exponentiation.rs <-- ここに実装を移しました。
│           mod.rs
└───target
(snip)
```

```Rust:math/exponentiation.rs
pub fn pow(x: u32) -> u32 {
    pow_impl(x)
}

fn pow_impl(x: u32) -> u32 {
    x * x
}

#[test]
fn pow_test() {
    let x = pow(2);
    assert_eq!(x, 4)
}
#[test]
fn pow_impl_test() {
    let x = pow_impl(2);
    assert_eq!(x, 4)
}
```
```Rust:math/mod.rs
pub mod exponentiation; // モジュールを公開する
```
代わりにlibにはmathモジュールを使うコードを書いておきます。

``` Rust:src/lib.rs
pub mod math;

fn calc() {
    // 公開されてるAPIなのでOK
    let pow = math::exponentiation::pow(10);
    // 公開されていないAPIなのでビルドエラーが起こる
    let pow_inner = math::exponentiation::pow_impl(10);
    assert_eq!(pow, 100);
}
```
移植が完了しました。
次は、テストコードも分離していきます。

# テストコードの分離（失敗編）

```
./
│   .gitignore
│   Cargo.lock
│   Cargo.toml
│
├───src
│   │   lib.rs
│   │
│   └───math
│           exponentiation.rs
│           exponentiation_tests.rs <-- テストメソッド群
│           mod.rs
└───target
(snip)
```

```Rust:math/exponentiation.rs
pub fn pow(x: u32) -> u32 {
    pow_impl(x)
}

fn pow_impl(x: u32) -> u32 {
    x * x
}
```

```Rust:math/exponentiation_test.rs
use crate::math::exponentiation::*;
#[test]
fn pow_test() {
    let x = pow(2);
    assert_eq!(x, 4)
}
#[test]
fn pow_impl_test() {
    let x = pow_impl(2);
    assert_eq!(x, 4)
}
```


```Rust:math/mod.rs
pub mod exponentiation;
#[cfg(test)]
pub mod exponentiation_tests; // テストモジュールを公開してcargo testできるようにする
```

よし、テストをしてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30037/0d1795b9-ee9d-6dfd-8bbf-c525b81be64b.png)

ですよねー！！！！！！
pow_implは`exponentiation_tests.rs`から見えないよ！って言われてます。
同じファイルには書きたくないし、pubを付けて公開もしたくない・・・どうしよう？？？

# モジュール内での可視性はpubにし、モジュールの可視性をprivateにする（成功）
Rustはファイル単位での可視性を設定できるわけですが
モジュールでの可視性も設定できるというのが自分の中では盲点でした。

``` Rust:math/mod.rs
pub mod exponentiation;
mod exponentiation_impl; // 追加：pubは付けずにモジュールを定義する
#[cfg(test)]
pub mod exponentiation_tests;
```

``` Rust:math/exponentiation_impl.rs
pub fn pow_impl(x: u32) -> u32 {
    x * x
}
```
```Rust:math/exponentiation.rs
use crate::math::exponentiation_impl::*; // 追加
pub fn pow(x: u32) -> u32 {
    pow_impl(x)
}
```

```Rust:math/exponentiation_tests.rs
use crate::math::exponentiation::*;
use crate::math::exponentiation_impl::*; // 追加
#[test]
fn pow_test() {
    let x = pow(2);
    assert_eq!(x, 4)
}
#[test]
fn pow_impl_test() {
    let x = pow_impl(2);
    assert_eq!(x, 4)
}
```

```
./
│   .gitignore
│   Cargo.lock
│   Cargo.toml
│
├───src
│   │   lib.rs
│   │
│   └───math
│           exponentiation.rs
│           exponentiation_impl.rs <-- テストしたいけど非公開にしたいメソッド
│           exponentiation_tests.rs <-- テストメソッド群
│           mod.rs
└───target
(snip)
```

めでたく通りましたし、lib.rsで隠蔽されてるimplメソッドを呼ぼうとするとちゃんとエラーになりました。
若干手間ですが、ファイル分離ができてとても幸せな感じですね。

それでは。