TDDへの道が見えてきた

ここ最近は、TDDへの道筋をつけるのが個人的な目標だったりしています。
で、色々奮闘して多少道筋がついたのでメモっておこうかと。


感想を先に言っておくと、色々大変だった。大変とは言っても技術的にとかではなく精神的にかなりキツかった。でも難しいという意味では無い。
今までだってテストをしていなかった分けではないです。自分の場合はちょっと作って、動かして動作確認して、のパターンが結構多いのだけどTDDじゃあ無かった。

テストの実行方法を知る

まず、ここの知識が無いので1から構築するのが大変でした。
そもそも情報が少ないので今でもこのやり方が正しいのか、一般的なのかが分かりません。
こういう何が一般的か?というバランス感覚ってどうやって身につければ良いのでしょうね?


さて、実際のテストの実行方法。
言語はPythonフレームワークDjangoです。
まあ仕事なのでPythonに多少不満を持ちつつも使っていたり... せめてPythonマルチバイトの部分だけでもなんとかして欲しいですよね。


ともかくテストはnose-test使っています。
http://pythonpackages.com/package/django-Nose が分かりやすいかな。
流れを簡単に説明すると、

  • テスト用DBを作ってデータを用意する。
  • テストを書く!
  • "REUSE_DB=1 ./manage.py test"でテストする。こうすればテスト用DBのデータは消えない。


この辺は言語やフレームワークによって色々あるけど、まず最低限テストを用意して実行できるようにしましょう、という話。当たり前だけどね。

TDD

TDDの何が大変かというと、今までのプログラミングスタイルを変える必要がある部分がしんどい。
ある程度の経験があるプログラマだとその人それぞれのプログラミングのスタイル、もしくはリズム、があります。これ普段は意識しないけどTDDをやって始めて気付きました。


TDDって「テストを書く」→「コードを書く」→「テストを実行する」の流れが基本ですが、この流れに持っていくのが精神的に辛い。そりゃあ、いままでの自分のリズムから外れるのだから。
最終的にはここに慣れるのは実践あるのみでしょう。
でもやってみると分かりますが、精神的な辛さ以上に安心感はかなり大きいです。テストはしているので作ったプログラムをある程度自信をもって公開できます。リズムの問題もある程度経つと慣れてきますし。


上で書いたこれと、TDDの違いはテストコードが後に残ることじゃあ無いかと思う。後でだれでもどんなテストを実行したかが分かるのが大きい。

今までだってテストをしていなかった分けではないです。自分の場合はちょっと作って、動かして動作確認して、のパターンが結構多いのだけどTDDじゃあ無かった。

自動テスト

あとは自動テストです。とはいってもJenkinsを使って24時間テストしろ、ではなくてTDDをやりながらの自動テストです。


これが今の課題で、TDD中にある程度のコード(テストコード含む)を書くと、テストその物に時間がかかり、テストが終わるまでコードが書けなくなります。
これがコーディングのリズムを狂わす原因の1つではないかと思っているところです。


ひとまず、guardとwatchrというRuby製の汎用のツールがありこれを使い出しました。
これはファイルを更新すると、あらかじめ指定したコマンドを呼べるというツールです。inotifyとかその辺(実際にはfseventかな?)を使って実現しているのでしょう。
結局、今はとりあえずwatchrに落ち着いて、ファイルを保存するとテストが実行できる所まではきたので、あともう少しかな。


今の懸念点は、テスト実行のタイミングがファイル保存時なので、開発途中のどう考えてもエラーになるだろう、って時点での実行はしてほしくないこと。どうしますかね..

まとめ

TDDのやり始めは結構しんどい。
TDDを知っていてもやらない人が懸念していることは、多分初めのうちは正しい。時間がいつも以上にかかるだろう、今のコードはテストする段階に達していなくテストし辛い、etc...。


でもやってみれば、そのうち慣れていくし全部のコードをテストなんか出来るわけが無いのである程度妥協さえすれば、TDDは出来る。
多分一気に完璧にTDDはできない(出来る人もいるのかもしれないけど...)。
それでも、バグが見つかってからの修正時間まで考えるとTDDにかける時間の方が短いと思う。


まだTDDを実践いなかったらTDDはやる価値はあると思う。多少しんどくても。
というのが今の気持ち。