[[📚テスト駆動開発]]のメモ。
- [[📰テスト駆動開発 読書メモ ~TypeScript編~]] を[[Rust]]でチャレンジしなおしたもの
- もともと[[Rust]]版を先にやっていたが、**設計思想が異なり難しすぎた**ので[[📰テスト駆動開発 読書メモ ~TypeScript編~]]に切り替えた経緯がある
## オレオレルール
本書は[[Java]]で書かれているが、言語は[[Rust]]で同じ意味の内容を書いていく。狙いは2つ。
- [[Rust]]の復習やキャッチアップを行うため
- 丸写しできない環境をつくることで理解度を深めるため
なお、[[IDE]]は[[Neovim]]を使用する。これは単に[[Neovim]]力を高めたいから。具体的には操作スピードと環境の向上である。
<div class="link-card">
<div class="link-card-header">
<img src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png" class="link-card-site-icon"/>
<span class="link-card-site-name">minerva.mamansoft.net</span>
</div>
<div class="link-card-body">
<div class="link-card-content">
<div>
<p class="link-card-title">📜2023-09-10 RustでTDD写経するためにNeovimを使った環境構築</p>
</div>
</div>
<img src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/minerva-image.webp" class="link-card-image" />
</div>
<a
class="internal-link"
data-href="📜2023-09-10 RustでTDD写経するためにNeovimを使った環境構築"
></a>
</div>
%%[[📜2023-09-10 RustでTDD写経するためにNeovimを使った環境構築]]%%
### リポジトリ
リポジトリは[[GitHub]]に公開する。
<div class="link-card">
<div class="link-card-header">
<img src="https://github.githubassets.com/favicons/favicon.svg" class="link-card-site-icon"/>
<span class="link-card-site-name">GitHub</span>
</div>
<div class="link-card-body">
<div class="link-card-content">
<div>
<p class="link-card-title">GitHub - tadashi-aikawa/rust-tdd</p>
</div>
<div class="link-card-description">
Contribute to tadashi-aikawa/rust-tdd development by creating an account on GitHub.
</div>
</div>
<img src="https://opengraph.githubassets.com/ea6ef0d37a3e39be418dc9b3ac78b04cdcf5c8f9adbf90e632e1263668c5ba4d/tadashi-aikawa/rust-tdd" class="link-card-image" />
</div>
<a href="https://github.com/tadashi-aikawa/rust-tdd"></a>
</div>
## Are you ready?
ここからが本編。
# まえがき
### テストの価値
- 開発が予測可能になる
- チームの信頼感が増す
- 書いていて気持ちいい
### 作業の順序
| 用語 | 意味 |
| ---------------- | -------------------------------- |
| レッド | 動作しないしコンパイルも通らない |
| グリーン | テストが成功する? |
| リファクタリング | 重複の除去 |
### 勇気と不安
- テスト熱中症
### 本書を読み終えたあとの姿
- シンプルに始める
- 自動テストを書く
- リファクタリングで設計判断を1つずつ行う
# 第I部 多国通貨
### 対応順序
1. テストを1つ書く
2. 全テストを実行させ、1のテスト失敗を確認する
3. 小さな変更を行う
4. 全テストを実行させ、1のテスト成功を確認する
5. リファクタリングで重複を削除する
## 第1章 仮実装
細かいステップを踏み続けられる(can)であることが大事。
> [!positive] 普段の開発でもログ出力やダミー実装で休憩ポイントを設けて、少しずつ開発していってるからこれは分かる。[[TDD]]とは別に、通常の開発も (遠回りにならない程度の) 小刻みなステップは大事だと思う
https://github.com/tadashi-aikawa/rust-tdd/tree/0728036dafb2cd06f97e8606add46b3ab49f59a0
## 第2章 明白な実装
| 用語 | 意味 |
| ---------- | -------------------------------------------- |
| 仮実装 | 定数ベタ書きからはじめて変数に置き換えていく |
| 明白な実装 | 頭の中の実装をすぐコードに落とす |
> [!thinking] 自信があるときは明白な実装モード、自信がなくなったら仮実装モードにシフトというのは分かりやすい戦略の1つ。自分は仮実装モードからスタートすることが多いけど、無意識のうちに2つのモード切替を実はしているのかもしれない...🤔
[[Rust]]の[[バイナリクレート]]として作っていたが[[ライブラリクレート]]としても作り直した。理由は以下。
- 未使用警告が全体に出るのが気持ち悪い
- テスト実行が主目的なのでこっちの方が適切なはず
https://github.com/tadashi-aikawa/rust-tdd/tree/7763b33e7cbf2f37a2a9352d77ada4fd925f6f41
## 第3章 三角測量
- [[Value Object パターン]]
- [[別名参照問題]]
> [!positive] 普通にequalsの実装方法しか頭になかった😇
```rust
#[test]
fn test_equality() {
assert_eq!(Dollar::new(5).equals(Dollar::new(5)), true);
}
```
だと不十分で... [[三角測量]]を行うには2つ目の実例がいる。
```rust
#[test]
fn test_equality() {
assert_eq!(Dollar::new(5).equals(Dollar::new(5)), true);
assert_eq!(Dollar::new(5).equals(Dollar::new(6)), true);
}
```
> [!thinking] [[Rust]]だとnullや他Objectとの比較は不要な気がするんだけど、どうなんだろう...? その辺は静的型チェックで弾けるし、弾くべきところかと思うのだが...
https://github.com/tadashi-aikawa/rust-tdd/tree/8e79925b28eb1c40c757595f38ffad3e608d85c5
## 第4章 意図を語るテスト
> [!positive] 『テストは意図を語る』という表現好き。複雑な処理を隠蔽するための関数化も大事だけど、テストコードのインターフェースは読めば伝わる方が遥かに大事だと思っている。
> [!positive] [[Java]]の実装に引きずられていたら、[[Rust]]の実装を忘れていた...。[[Rustのassert_eqマクロで比較する対象はPartialEqトレイトとDebugトレイトの実装が必須]]なことや[[derive属性]]などを思い出した。
https://github.com/tadashi-aikawa/rust-tdd/tree/e09f22e29b58b2ce6108131d1701e323bc3b3478
## 第5章 原則をあえて破るとき
> [!positive] 自分はよく『正義のコピペ』という名前で呼んでる
https://github.com/tadashi-aikawa/rust-tdd/tree/de782c2354e0f6728c99a5f585db89ca84a0129c
## 第6章 テスト不足に気づいたら
> [!thinking] [[Rust]]だと継承は使えないから[[トレイト]]の実装になるのかな... [[derive属性]]でいくつかは実装できてる気はする
[[トレイト]]だと共通の[[フィールド (Rust)|フィールド]]を定義できないので、 [[Rustのニュータイプパターンを利用しつつ、self.0を使わない方法]]を応用して切り抜ける。
https://github.com/tadashi-aikawa/rust-tdd/tree/acdfc55ad15fc7b360fa1e14994ad8c0417cf7aa
> [!thinking] [[Derefトレイト]]実装を共通化したいけど、やり方が分からん。。
https://github.com/tadashi-aikawa/rust-tdd/tree/b0e1d2c6e12614f70374f47f75c00eb0a921262a
## 第7章 疑念をテストに翻訳する
```rust
#[test]
fn test_equality() {
assert!(Dollar::new(5).eq(&Dollar::new(5)));
assert!(!Dollar::new(5).eq(&Dollar::new(6)));
assert!(Franc::new(5).eq(&Franc::new(5)));
assert!(!Franc::new(5).eq(&Franc::new(6)));
assert!(!Franc::new(5).eq(&Dollar::new(5)));
}
```
`eq`の型は自分自身しか認めていなかったのでエラーになる。(これを許容したかったからObjectにしてたのか。。)
```error
mismatched types
expected reference `&rust_tdd::franc::Franc`
found reference `&rust_tdd::dollar::Dollar` (rustc E0308)
```
https://github.com/tadashi-aikawa/rust-tdd/tree/4e063e4c9b96a178352388439a43837dfb166b1c
## 第8章 実装を隠す
==ここで一旦休止し [[📰テスト駆動開発 読書メモ ~TypeScript編~]] を進めることにした==