IDEとかなんやよくわからんねんけど、「テスト駆動開発」を写経したいという人向けガイド


# これは何？

名著として名高いKent Beckの「テスト駆動開発」の新訳版の訳者t_wadaさんは、この本は写経すべしと説いています。教えに従って写経をしてみたい。悟りを開いてみたい。みたいんだけど、それ以前にIDEのインストールで躓いてにっちもさっちも・・・という初心者向けのガイドです。そういう勉強会を社内でやったんですわ。

IDEは素晴らしいものなんで、そのうちそっちも勉強してください。

Macを対象にしています。その他の環境では何がどのぐらい違うのかよくわかりませんけど、だいたい大筋で同じでどうにかなるんじゃないのかなあ。

# 準備

使うものは以下

* GitHub(または、GitHub Enterprise)
* Git
* JDK
* Gradle

以下の準備をしておいてください。

1. GitHubのアカウントをとって、SSHのKeyを登録します。
2. Git, JDK, Gradleをインストールします。

やり方は調べましょう。Qiitaにもいっぱいガイドがあるはずです。触ったことがない？。一応、その前提で以下、書いていきますが、ググれば大丈夫。

# リポジトリの作成

GitHubで、新しいリポジトリを作りましょう。どんな名前にするのかは自由。そう、自由です。

![スクリーンショット 2020-03-12 17.34.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300900/8508d549-e381-5521-d9dd-8a4a77412a95.png)

出来たら、リポジトリをクローンするための情報を入手しておきましょう。

![スクリーンショット 2020-03-12 17.34.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300900/69e10880-35e7-f8f6-20d9-ac9d8f86c927.png)

# クローン

GitHubで作ったリポジトリを自分のPCへ持ってきましょう。 好きなディレクトリで実行して構いません。

~~~
> git clone git@github.ibm.com:TAMBARA/tdd_study.git
Cloning into 'tdd_study'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.
~~~

tdd_studyというディレクトリが出来ているので、中を見てみましょう。

~~~
> ls -la
total 8
drwxr-xr-x    4 tambara  staff   128  3 12 17:38 .
drwxr-xr-x+ 109 tambara  staff  3488  3 12 17:38 ..
drwxr-xr-x   10 tambara  staff   320  3 12 17:38 .git
-rw-r--r--    1 tambara  staff    61  3 12 17:38 README.md
~~~

README.mdはGitHubさんが作ったものです。.gitはGitさんが使う情報です。他にはなにもなし。

Gitさんのご機嫌を伺っておきますか。

~~~
> git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean
~~~

何も変更が加えられていないと、こんな感じです。

# Gradle init

何にもないとどこに何を作ったら良いのか、不安になります。なので、オススメ構成を作って貰いましょう。Gradleがいろいろよろしくやってくれます。では、初期構成を作って貰いましょう。

~~~
> gradle init
Starting a Gradle Daemon (subsequent builds will be faster)

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 2

Select implementation language:
  1: C++
  2: Groovy
  3: Java
  4: Kotlin
  5: Swift
Enter selection (default: Java) [1..5] 3

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Select test framework:
  1: JUnit 4
  2: TestNG
  3: Spock
  4: JUnit Jupiter
Enter selection (default: JUnit 4) [1..4] 4

Project name (default: tdd_study): 
Source package (default: tdd_study): 

> Task :init
Get more help with your project: https://docs.gradle.org/6.2.2/userguide/tutorial_java_projects.html

BUILD SUCCESSFUL in 3m 3s
2 actionable tasks: 2 executed
~~~

注意点です。

* type of projectはapplicationを選びます。basicにすると、何も作ってくれません。
* test frameworkはJUnit Jupiterを選びます。本に合わせるためです。
* Project nameは、ホントは本に合わせてmoneyにすべきだったんですが、間違えました。まあ、いいでしょう。

では、何が作られたのか確認してみましょう。

~~~
> ls -la
total 64
drwxr-xr-x   13 tambara  staff   416  3 12 18:00 .
drwxr-xr-x+ 109 tambara  staff  3488  3 12 17:38 ..
drwxr-xr-x   10 tambara  staff   320  3 12 17:53 .git
-rw-r--r--    1 tambara  staff   154  3 12 18:00 .gitattributes
-rw-r--r--    1 tambara  staff   103  3 12 18:00 .gitignore
drwxr-xr-x    6 tambara  staff   192  3 12 17:57 .gradle
-rw-r--r--    1 tambara  staff    61  3 12 17:38 README.md
-rw-r--r--    1 tambara  staff  1156  3 12 18:00 build.gradle
drwxr-xr-x    3 tambara  staff    96  3 12 17:57 gradle
-rwxr-xr-x    1 tambara  staff  5764  3 12 17:57 gradlew
-rw-r--r--    1 tambara  staff  3056  3 12 17:57 gradlew.bat
-rw-r--r--    1 tambara  staff   358  3 12 18:00 settings.gradle
drwxr-xr-x    4 tambara  staff   128  3 12 18:00 src
~~~

いっぱい作られていますが、gradleという単語が含まれたファイルやディレクトリはすべてGradleさんのためのものなので、今は気にしなくて良いです。ということは、srcというディレクトリだけですね。これはsourceの略なんで、ここにソースコードを置けや、ということです。

# 最初のコミット

やたらファイルが増えましたが、このことについてGitさんはどうお考えか、伺っておきましょう。

~~~
> git status
On branch master
Your branch is up to date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	.gitattributes
	.gitignore
	build.gradle
	gradle/
	gradlew
	gradlew.bat
	settings.gradle
	src/

nothing added to commit but untracked files present (use "git add" to track)
~~~

なんか、知らんファイルが増えてるけど気にしなあかんのん？という感じのようです。`git add`して気にして貰いましょう。とりあえず、全部。

~~~
> git add --all
~~~

さて、ご気分は変化されたでしょうか。

~~~
> git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	new file:   .gitattributes
	new file:   .gitignore
	new file:   build.gradle
	new file:   gradle/wrapper/gradle-wrapper.jar
	new file:   gradle/wrapper/gradle-wrapper.properties
	new file:   gradlew
	new file:   gradlew.bat
	new file:   settings.gradle
	new file:   src/main/java/tdd_study/App.java
	new file:   src/test/java/tdd_study/AppTest.java

~~~

コミットする気まんまんですね。コミットしましょう。コミットメッセージはちゃんと書きましょう。

~~~
> git commit -m 'gradle initしただけ'
[master c22d029] gradle initしただけ
 10 files changed, 382 insertions(+)
 create mode 100644 .gitattributes
 create mode 100644 .gitignore
 create mode 100644 build.gradle
 create mode 100644 gradle/wrapper/gradle-wrapper.jar
 create mode 100644 gradle/wrapper/gradle-wrapper.properties
 create mode 100755 gradlew
 create mode 100644 gradlew.bat
 create mode 100644 settings.gradle
 create mode 100644 src/main/java/tdd_study/App.java
 create mode 100644 src/test/java/tdd_study/AppTest.java
~~~

Gitさんもすっきりした面持ちです。

~~~
> git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean
~~~

# いよいよテスト

## 初めてのテスト実行はコンパイルエラー

さて、いよいよソースコードを触っていきましょう。Finderでファイル構成を確認してみましょうか。

~~~
> open .
~~~

とすると、Finderが開きます。

![スクリーンショット 2020-03-12 18.07.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300900/28459932-f1be-eb23-6fed-b5f9dc78f9f8.png)

srcディレクトリの下はこんな感じになってるんですね。ご想像の通り、mainの下にアプリケーションのコードを、testの下にテストのコードを書きます。

「テスト駆動開発」の1章を見ながら、テストコードを書いていきましょう。AppTest.javaをMoneyTest.javaに名前を変えて、本の通りに編集します。

![スクリーンショット 2020-03-12 18.13.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300900/a81ecda4-dc05-a41c-b143-83c3c9a1fe75.png)

出だしの`package`のところだけ、本と違うことになっちゃってますが、ここは目をつむって下さい。さっき間違えたところです。

テストがかけたから、実行しましょう。テストの実行は`gradle test`です。

~~~
> gradle test

> Task :compileTestJava FAILED
/Users/tambara/tdd_study/src/test/java/tdd_study/MoneyTest.java:9: エラー: シンボルを見つけられません
        Dollar five = new Dollar(5);
        ^
  シンボル:   クラス Dollar
  場所: クラス MoneyTest
/Users/tambara/tdd_study/src/test/java/tdd_study/MoneyTest.java:9: エラー: シンボルを見つけられません
        Dollar five = new Dollar(5);
                          ^
  シンボル:   クラス Dollar
  場所: クラス MoneyTest
エラー2個

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileTestJava'.
> Compilation failed; see the compiler error output for details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 18s
2 actionable tasks: 2 executed
~~~

いろいろ怒られているようで怯みますが、臆することなく眺めてください。`compileTestJava FAILED`と書いているからには、コンパイルが通らなかったようです。`Doller`クラスってなんやねんと言われているようです。いや、こっちも知らんし。テストしか書いてないので、当然ですね。

## テストは実行されたけど、失敗している

コンパイルエラーではテストができません。今度はApp.javaをDollar.javaに書き換えて、本の通りに編集しましょう。なんせ写経ですから。

![スクリーンショット 2020-03-12 18.19.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300900/7e4cb557-310d-7228-cb17-76f26ef26d57.png)


![スクリーンショット 2020-03-12 18.18.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300900/142e402a-292f-e9d5-8f49-5e819d3adf69.png)

`Dollar`クラスの定義ができました。中身はカラっぽですけど。さあ、テストだ。

~~~
> gradle test

> Task :test

MoneyTest > testMultiplication() FAILED
    org.opentest4j.AssertionFailedError at MoneyTest.java:11

1 test completed, 1 failed

> Task :test FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':test'.
> There were failing tests. See the report at: file:///Users/tambara/tdd_study/build/reports/tests/test/index.html

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 5s
3 actionable tasks: 3 executed
~~~

`test FAILED`と出ていますが、気を落とす必要はありません。今度はテストが実行されたのだから大きな前進です。というか、`Dollar`クラスの中身が空っぽなのに、テストが成功したらヤバいです。ちゃんとテストが失敗するのを確認するのが大事です。

そういえば、ここにレポートが出ているよ、と書いてありますね。`file:///Users/tambara/tdd_study/build/reports/tests/test/index.html`をブラウザで表示してみましょう。

![スクリーンショット 2020-03-12 19.38.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300900/c19a7dc1-7355-12c0-d2b3-8fc00d66c618.png)

赤い。赤いね。これが、テストがレッドだという状態です。


## ついにテストが成功

では、本に従ってコードを直しましょう。

![スクリーンショット 2020-03-12 18.22.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300900/45950e3e-e4a5-099c-93fe-4df5f2fa3174.png)

どう考えてもこの修正で良いわけないんですが、テストを通過させるにはこれで十分。この後の展開は本をじっくり楽しんで下さい。

~~~
> gradle test

BUILD SUCCESSFUL in 2s
3 actionable tasks: 2 executed, 1 up-to-date
~~~

そっけないですが、どうやらテストが成功したようです。レポートファイルも見てみましょう。

コンディション・グリーンでございます。

![スクリーンショット 2020-03-12 19.40.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300900/a9977295-f4d3-f0ed-2082-2a9ac40f4b8c.png)

# プッシュ

では、ここまでの成果をコミットしましょう。まず、Gitさんのご機嫌を伺います。

~~~
> git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	deleted:    src/main/java/tdd_study/App.java
	deleted:    src/test/java/tdd_study/AppTest.java

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	.DS_Store
	src/.DS_Store
	src/main/.DS_Store
	src/main/java/.DS_Store
	src/main/java/tdd_study/Dollar.java
	src/test/.DS_Store
	src/test/java/.DS_Store
	src/test/java/tdd_study/MoneyTest.java

no changes added to commit (use "git add" and/or "git commit -a")
~~~

なんか作った覚えのない`.DS_Store`というファイルがたくさんあって目障りですな・・・。これが何なのかは調べて貰うとして、これはコミットする必要はありません。Gitさんに気にして貰う必要もない。そういうファイルは、.gitignoreに書いておく決まりになっています。末尾に1行足しておきましょう。

~~~
> vi .gitignore
> cat .gitignore 
# Ignore Gradle project-specific cache directory
.gradle

# Ignore Gradle build output directory
build

.DS_Store
~~~

Gitさんのご機嫌はいかがでしょうか。

~~~
> git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   .gitignore
	deleted:    src/main/java/tdd_study/App.java
	deleted:    src/test/java/tdd_study/AppTest.java

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	src/main/java/tdd_study/Dollar.java
	src/test/java/tdd_study/MoneyTest.java

no changes added to commit (use "git add" and/or "git commit -a")
~~~

自動で作られたApp.javaとAppTest.javaがなくなって、Dollar.javaとMoneyTest.javaが増えました。そうそう、.gitignoreの変更も上がってますね。では、addして、commitしましょう。

~~~
> git add --all
> git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   .gitignore
	deleted:    src/main/java/tdd_study/App.java
	new file:   src/main/java/tdd_study/Dollar.java
	deleted:    src/test/java/tdd_study/AppTest.java
	new file:   src/test/java/tdd_study/MoneyTest.java

> git commit -m '1章 最初のグリーンがでたところ'
[master f4c8b07] 1章 最初のグリーンがでたところ
 5 files changed, 24 insertions(+), 28 deletions(-)
 delete mode 100644 src/main/java/tdd_study/App.java
 create mode 100644 src/main/java/tdd_study/Dollar.java
 delete mode 100644 src/test/java/tdd_study/AppTest.java
 create mode 100644 src/test/java/tdd_study/MoneyTest.java
~~~

さて、ここまでは自分のPCの中の話。このコミットをGitHubに送ると、チームのメンバーにアドバイスも貰えるというもの。そのためには、プッシュをします。

~~~
> git push
Enumerating objects: 34, done.
Counting objects: 100% (34/34), done.
Delta compression using up to 4 threads
Compressing objects: 100% (20/20), done.
Writing objects: 100% (33/33), 58.37 KiB | 6.49 MiB/s, done.
Total 33 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), done.
remote: detect-secrets-stream (beta) ver=164-1ac7e673b9acf31ed1ba86a8422cf59cb8a848be FAQ: https://ibm.biz/detect-secrets-stream-faq
remote: 
remote: Successfully send push metadata.
remote: Push info collect pre-receive hook finished within 3 seconds.
To github.ibm.com:TAMBARA/tdd_study.git
   47be568..f4c8b07  master -> master
~~~

これでGitHubからでも自分の作ったファイルが参照できます。

![スクリーンショット 2020-03-12 18.32.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300900/7203c951-1851-c5ed-dbf4-afb61119fca7.png)

自分の書いたコードを見られるのはこっぱずかしいですが、見られないと上達しません。キリのよいタイミングでプッシュしましょう。

それでは、「テスト駆動開発」の写経を完走できることをお祈りしております。チャオ。