ブログトップ 記事一覧 ログイン 無料ブログ開設

やさしいデスマーチ このページをアンテナに追加 RSSフィード

札幌のWebエンジニアの綴る日常と開発の日々。
GoogleAppEngine/slim3/Django/NetBeans/Swing/JavaFXを中心にお届け。

2013-02-11

『JUnit実践入門』正誤表(6) #junitbook

| 01:12 | 『JUnit実践入門』正誤表(6) #junitbookを含むブックマーク

誤植速報その6です。

その1からその5までは初刷のみの誤植で2刷では修正済みです。

その1(2刷反映済),その2(2刷反映済),その3(2刷反映済), その4(2刷反映済), その5(2刷反映済), 技評さんの公式サイトです(おって反映されます)。

P362 テストケースのリスト5番目(最後)

誤)

Itemが1つ追加されている状態で、addで同じItemオブジェクトを追加するとgetNumで1が取得できる

正)

Itemが1つ追加されている状態で、addで異なるItemオブジェクトを追加するとgetNumで1が取得できる

リスト18.10のテストコード(最後のテストケース)に対応するテストケースです。テストコードに誤植はありません。

P19.9 複数行テキストのアサーション

テストコード中の期待値に誤りがあります。

誤)

public class MultiLineStringTest {
    @Test
    public void joinで文字列が連結される() throws Exception {
        String ls = System.getProperty("line.separator");
        String expected = "Hello" + ls + "World";
        assertThat(MultiLineString.join("Hello", "World"), is(text(expected)));
    }
}

正)

public class MultiLineStringTest {
    @Test
    public void joinで文字列が連結される() throws Exception {
        String ls = System.getProperty("line.separator");
        String expected = "Hello" + ls + "World" + ls;
        assertThat(MultiLineString.join("Hello", "World"), is(text(expected)));
    }
}

公開済みのサンプルコードは正しいコードとなっており、書籍のみ誤植になります。

ご迷惑をおかけして申し訳ありません。

(7)に続く...

2013-02-05

SQLアンチパターンにおけるPostgreSQLパッチ #sqlap

| 11:16 |  SQLアンチパターンにおけるPostgreSQLパッチ #sqlapを含むブックマーク

SQLアンチパターンMySQLがベースになっているのでPostgreSQLではそのまま動かない。とりあえずサンプルデータベースの変更ポイント。

  • BLOBをBYTEAに変更
  • UNSIGNGEDがないので省略
  • DATETIMEをTIMESTAMPに変更

テーブルを削除したい場合はDROP文をIF EXISTSオプションを付けて冒頭に書いておけばOK。

DROP TABLE IF EXISTS 
  Accounts, BugStatus, Bugs, 
  Comments, Screenshots, Tags, 
  Products, BugsProducts;

修正後のSQLって公開してもいいのかな?

id:t-wada さんに公開OKといただきました。

(追記)リポジトリ公開しました

写経しながらとなりますが、こちらのリポジトリにおいておきます。

https://bitbucket.org/shuji.w6e/sqlap

最初のセットアップスクリプトこちら

t-wadat-wada 2013/02/05 16:34 ぜひぜひ公開して頂ければと思います!

shuji_w6eshuji_w6e 2013/02/05 16:51 ありがとうございます。
早速、リポジトリをpublicにしました。

2013-01-17

北海道Devキャンプ2013 ーニセコのお知らせ

21:44 |  北海道Devキャンプ2013 ーニセコのお知らせを含むブックマーク

7月の連休(予定)となりますが、ニセコのコテージとかを数日借りて、TDDBCをベースとした開発合宿を行う予定です。

とは言っても、TDDBC関係者が中心となっているだけで、TDDとかやらなくても全く問題ありません。やることが特に決まっていないならば、TDDBCのお題を解いてみたり、その辺の話題で盛り上がったりできればいいな、という程度です。

また、今回のキャンプでは開発合宿だけではなく、温泉・サイクリングやラフティングといったアクティビティ・バーベキューなど北海道を楽しんで、仲間と一緒にリフレッシュしようというのがテーマです。

遊ぶものはおって決めていきたいと思いますが、サイクリングだけは確定。1人でも朝走りますw

なお、遊ぶための道具については持ち込んでもらっても、ニセコでレンタルしてもOKです(実費)。

と、こんなノリで、北海道に遊びに来たいと感じた人は、こちらから参加表明を!なお、この参加登録は本登録ではなく、だいたいの人数把握のためです。本登録のための募集は3月以降になります。

2012-12-24

JavaのテストコードからはじめるGroovy #gadvent2012

| 23:09 |  JavaのテストコードからはじめるGroovy #gadvent2012を含むブックマーク

本エントリーは、G* Advent Calendar 2012の24日目のエントリーです。前日は、@tetsurokitaharaさんのGroovyにProcessingを!でした。

何をネタに書こうかなと悩んだのですが、思うほどG*なネタは持っておらず、JUnitネタとなりました。実は、書籍「JUnit実践入門」でもGroovyを活用するトピックを入れる予定だったのですが、紙面の都合上、入れる事ができませんでした*1。そこで、少しだけですが、本エントリーで補足したいなと思います。

テストコードでGroovyを使う

Groovyは、Javaと親和性の高いプログラミング言語です。上司を説得する場合は「GroovyはJavaの拡張ライブラリです(キリッ」と言っても良いでしょう。本当は開発環境やビルドツールの設定などで一工夫しなければ利用できませんが、その辺は裏でしれっとやってしまえばOKです。

とはいっても、いきなりGroovyやるぞと言ってもチームのメンバーはびっくりしてしまうかもしれません。そこで少しずつ洗脳していくために、テストコードをGroovyで書くところから始めるとスムーズに導入できる可能性が高まると思います。

なぜならば、Groovyはこれまで書いていたJUnitのテストコードを、同じように、簡単に、楽して書くことができるからです*2

なお、EclipseでGroovyの開発を行うには、Market Placeで「Groovy」を検索し、Groovy-Eclipseをインストールするのが簡単です。お使いのEclipseに合わせて「Groovy-Eclipse for Juno」か「Groovy-Eclipse for Indigo」を選択してください。

テストコードの比較

Javaを利用したテストコードのサンプルは次のようになります。

public class CalculatorTest {
    @Test
    public void _4を2で割ると2を返す() throws Exception {
        Calculator sut = new Calculator();
        assertThat(sut.divide(4, 2), is(2.0));
    }
}

一方、Groovyで記述すると次のように書けます。

class CalculatorTest {
    @Test
    void "4を2で割ると2を返す"() {
        def sut = new Calculator()
        assertThat(sut.divide(4, 2), is(2.0))
    }
}

違いをみていきましょう。

publicの省略

Groovyでは、クラスやメソッドのアクセス修飾子を省略した場合、publicとなります。したがって、classの前のpublicやメソッド定義のpublicを省略できます。書いてあっても問題ありません。

セミコロンの省略

Groovyでは、黒魔術を使わなくとも、セミコロンを省略できます。

メソッド名の先頭に数字の利用

Groovyでは、メソッド名を文字列のようにダブルクオーテーションで囲むことができます。すると、Javaでは定義できなかったメソッド名を定義できます。例えば、先頭に数字を使うことや、小数点・カンマ・句点などが利用できるため、テストケース名(メソッド名)が理解しやすくなります。

throws Exceptionの省略

Groovyでは、例外はすべて非チェック例外のように振る舞います。したがって、Javaで必要であったthrows句やtry-catch句を省略可能です。

このことは、プロダクションコードを書く場合には、チェック例外を使用するか非チェック例外を使用するかで議論の分かれる部分かもしれません。しかし、テストコードでは議論の余地無く、throws Exceptionでしょう。でも、書くのが面倒…ならばGroovyです。

変数の型を省略

Groovyでは、変数をdefというキーワードを使い、宣言することができます。Java的にはObject型として宣言されていることと等価であるため、「Object sut」と宣言していることと変わりません。

Groovyでは、実行時に呼び出されたメソッドがあるかをチェックし、ない場合は例外を送出します。これはコンパイル時のチェックが甘くなるため、Javaの静的メリットを小さくするかもしれません。

ですが、ここで書いているのはテストコードです。メソッドが存在しないで例外が発生することは全くデメリットになりません。

それGroovyならできるよ

これから書くJavaのテストコードの拡張子はgroovyとし、簡単に省略できるところをGroovy化しましょう。

そして、テストコードを書いていくと、様々な「こんなこと出来たらなぁ」が発生します。特に、Rubyなどスクリプト言語を扱った経験があれば、ヒアドキュメントが書きたい、リストを簡単に宣言したいといった気分になるはずです。

そんな時は、「プログラミングGROOVY 」を開き、解決できないか確認してみてください。

少しずつGroovyっぽいコードになってくはずです。

もう、プロダクションコードもGroovyでいいんじゃね?

Yes!

明日は @kazuchikaです。

プログラミングGROOVY

プログラミングGROOVY

JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)

JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)

*1:Groovyの解説やインストール方法などを書くと少なく見積もっても後50Pは必要となったので

*2:テストコードを書いてない人は、まずJUnit実践入門をお買い求めください

2012-12-15

軽量なテスト駆動開発を目指して #TddAdventJp

| 01:58 |  軽量なテスト駆動開発を目指して #TddAdventJpを含むブックマーク

これは、TDD Advent Calendar jp:2012 の16日目のエントリーです。前日のエントリーは、@pocketberserkerさんの「Specs2のParameterized Testのはなし」でした。

ご存じの方も多くなっていると思いますが、「テスト駆動開発(以下、TDD)」とはテストコードを先に書くテストファーストを基盤とした開発手法です。先にテストコードを書く事により、これからどのようなプロダクションコードを書こうとしているかを明確にすることができることが特徴です。このため、テストの技法というようりは設計技法です。

テスト駆動開発実践することにより多くのメリットを得ることができます。このことは2011年のAdvent Calendarで言及しました(TDDを学ぶべき10の理由 #TddAdventJp)。TDDは簡単に導入することができる一方で、実践するのは非常に難しいスキルです。特に簡単な計算機などのTDDはできたとしても、その後にちょっと複雑な、そう自動販売機アプリケーションのようなプログラムTDDで開発する所に壁がある気がします。

そこで、今年のエントリーでは「軽量なテスト駆動開発を目指して」と題して、そんなTDDのやり方をなんとなく習得した人が、TDD実践していく上でのヒントとなればと思います。自分がテスト駆動開発を行う時にどんな考えで最初のテストコードを書いているかをまとめたので、参考になれば幸いです。

イメージ図

f:id:shuji_w6e:20121216012609p:image

TDDが難しいワケ

TDDで難しいワケとして、どのようにクラスを分割し、どの程度テストすれば良いかの判断が難しいことがあります。これに対するひとつの回答は「不安がなくなるまで行う」ですが、不安は簡単になくなるものではありません。

そして、TDDを習得することによって、より不安になるというジレンマがあります。特にある程度大きな機能を分割し、TDDを行っていくと、「もう少しテストを追加しないと...」と不安となり、過剰にテストを書いてしまいがちです。「本当にこのクラス設計で大丈夫か?」と不安になってしまうと、最初のテストを書くことが不安になり、最初の1歩を踏み出す勇気が持てません。簡単なメソッドでもテストを書かないと怖い…と思ってしまうと、幾らテストを書いても開発は終わりません。

不安を安心に変えるためのテスト駆動開発が、むしろ開発者を不安にさせている、そんなことはないでしょうか?

はじめの不安は何か?

テスト駆動開発の肝は「不安を安心に変換するサイクルとリズム」です。

もし、最初のステップで「このクラスのこのインターフェイスは本当に使われるだろうか?」といった不安があった場合、その状態で「レッドーグリーンーリファクタリング」とTDDのサイクルを回してもその不安は消えません。2回目、3回目のTDDのサイクルを回すことにより「もし、これがまったく使われなかったらどうしよう…」とより不安が大きくなることもあるでしょう。

はじめに解消する不安を選択することが重要です。

いつ、テストをやめるのか?

テスト駆動開発では、TDDのサイクルを回しながら、不安がなくなった時点でサイクルを止め、次の機能の実装などに移ります。

よくあるケーストして、例外のテストをどこまでしたらば良いか困ったことはないでしょうか?Javaであれば、パラメータにnullが渡された場合の挙動など、「必要となるか解らないけど、不安だからテストしなきゃ…」となる場合があります。不安なのでテストするは正しいのですが、不安な理由は「良く解らない」からなのです。

どこでテストをやめれば良いかを把握するには、何が不安となっているかを知ることが重要です。

軽量テスト駆動開発とは?

軽量テスト駆動開発とは、行うべきテストを見極め、必要なテストコードしか書かないテスト駆動開発です。当たり前のような話ですが、自分の経験的にもテストを書きすぎてしまう傾向があったため、こんなネーミングにしました。

その肝は、何を不安と考えているかを明確にすることと、不安とならないテストは書かないことのふたつです。

なお、自分の感覚としては最盛期に比べ、テストの数は2/3くらいになった気がします。代わりにテストパターンを増やしたり、網羅的にテストを行えるように工夫したりできる余裕が生まれています。

それでは、簡単にですが自分のアプローチを紹介します。

はじめに外部的振る舞いを確認しよう

はじめに解消する「不安」は、アプリケーションの要件を満たす外部的振る舞いです。

外部的振る舞いは、要件定義や外部設計では(システムの)外部境界とも呼ばれ、内部実装に依存しない、アプリケーションの入出力の仕様です。

例えば、FizzBuzz問題*1であれば、指定された値までの数値または文字列を出力することが外部的振る舞いです。

ここで不安はないと感じるかもしれませんが、自分は文章だけの仕様は安心できません。

具体的な例を考える

外部的振る舞い(仕様)では、システムへの要件は列挙されていますが、具体的な例ではありません。このため、誤解して実装してしまうかもしれません。仕様自体に問題があることもあります。このような問題を回避するには、具体的な値を例として考える事です。

FizzBuzz問題であれば、例えば10を入力した場合に「1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz」と表示されるように、ひとつだけ例を作りましょう。

これでひとつ不安が解消されました。

検証可能にする

外部的振る舞いを例にすることで、不安がひとつ解消されましたが、まだTDDを行う段階ではありません。次に行うことは、例を検証可能な形(=テストコード)にすることです。

FizzBuzz問題では入力値に対する標準出力が外部的振る舞いになります。これを検証する方法はあるかもしれませんが、思いつかないことやプログラミング言語の制約などでできないかもしれません。

重要な事は不安を素早く安心に変える事です。

例えば、Javaで「リストをループして標準出力する」というプログラムであれば不安はないでしょう。つまり、入力値に対し、FizzBuzz問題を満たす文字列のリストが取得できれば、安心して標準出力できます。

ここでは、重要な事をふたつ行っています。それは、問題から「安心な部分や検証が困難な部分を省いていること」と「入力値を検証可能な出力値に変換するインターフェイス」を作っていることです。

最初のテストを書く

これで最初のテストコードを書くことができます。

JUnitでもCucumberでもRSpecでも自由にテストコードを書くことができるでしょう。なぜならば、テスト対象への具体的な入力値と戻り値、そして期待値があるのですから。もし、ここでテストコードを書くことで詰まるようであれば、ユニットテストについて学ぶ必要があります。

テストをグリーンにする前に

ここまで、システムを外側から見てテストコードを書いてきました。ここで実装を書けるよう出れば実装を進めます。書けるかどうかの判断は簡単です。不安に思わず、実装が書けそうであれば実装すれば良いのです。FizzBuzz問題であればここで解決する人が多いと思います。

問題はここで不安に思った場合です。

不安をリストアップする

実装に不安を感じたならば、その不安を言語化してください。

ちょっと無理もありますが、FizzBuzz問題の実装で不安と感じるのは「3と5とその公倍数の判定が不安」とか「それらの場合に正しい文字列を返せるか不安」といったところでしょう。

不安を検証可能にする

不安がリストアップされたならば、具体的な例を作り、不安を軽減した後、それらを検証可能なテストコードにします。FizzBuzz問題であれば「1を与えると1を返す」「2を与えると2を返す」「3を与えるとFizzを返す」メソッドがテストできれば不安はなくなりますね。

レッド−グリーン−リファクタリング

不安がなくなる段階まで落とし込んだならば、今まで学んだようなTDDを行ってください。恐らくは計算機クラスのような簡単なテストだったり、ちょっとだけテストダブルを使えば解決するような簡単なテストになっているはずです。

最初のテストをグリーンにする

幾つかの小さな不安、もしくはその不安の下のもっと小さな不安などをひとつひとつ解決していくことにより、最初のテストをグリーンにする準備が整うはずです。上から考えているため、無駄なコードもないでしょう。もしかしたらば、より良い設計が思いつくかもしれませんが、それでも無駄ではないと思います。

不安でない事はテストしない

このようにTDDのサイクルを繰り返していくと、FizzBuzzのメソッドでは引数にゼロが与えられたり、マイナスが与えられたりしたらどうしよう…と考えるかもしれません。

しかし、少し前に戻って再確認してください。要件にそのようなことは想定されていたでしょうか?もし、解らないならば要件や外部仕様の部分で決めることだと解るはずです。

ここで外部仕様として「1以上の整数を与える」という制約を加えてしまえば、FizzBuzzの内部メソッドではその考慮をしなければならないという不安がなくなります。もちろん、1つ上のシステム境界にとして振る舞うインターフェイスでは考慮しなければなりませんが、少なくとも内部メソッドはゼロ以下の値で呼び出されないと、「安心」できるはずです。

ほら、テストしなくても大丈夫!

ここでTDDのサイクルをやめることができます。

アウトインサイドの開発

これって「アウトインサイドの開発」ってやつでは?と思った方はJUnit実践入門かRSpec Bookを読んだ人だと思います。考え方としては受け入れテストによる振舞駆動開発を起点に、そこからユニットテストによるテスト駆動開発を行う流れであるため同じ考え方です。

しかし、重要なことは、振舞駆動開発かテスト駆動開発かではなく、受け入れテストかユニットテストかでもなく、この流れが、もっとも自然に、効率良く、不安を解消することです。

軽量テスト駆動開発

テスト駆動開発は、不安を安心に変える慎重な開発手法です。安心を手に入れる代償として大きなコストを払う必要があります。勿論、そのコストは、これまでデバッグを行いながら払ってきた分であるため、慣れることによってある程度は解決する部分かもしれません。しかし、よりテスト駆動開発生産性をあげようとしたならば、どれだけテストを省略するかが肝になります。テストは重要ですが、本当に必要なテストを見極め、不安になる部分のみに注力すれば圧倒的にテスト数を減らせることでしょう。

不安に感じない部分は省略することで、テスト駆動開発は軽量でもっと使いやすい開発技法になるのではないでしょうか?


明日は、テスト駆動開発の伝道師 id:t-wada さんのエントリーです。

祝・増刷『JUnit実践入門』 #junitbook

| 11:10 |  祝・増刷『JUnit実践入門』 #junitbookを含むブックマーク

お陰様でJUnit実践入門の増刷が決まりました!

タイトルなどに「Java」というキーワードが含まれず、一部の書店では不遇な扱いを受けていますが、それなりに売れているということでありがたく思います。増刷分は年末にあがってくる予定です。もし、書店などで注文され、入荷待ちの方がいましたらば、もうしばらくお待ちください。

また、誤植情報などがありましたらば、(可能であれば)本日中に著者宛に教えて頂ければ、増刷分には反映できると思います。ちょっとした誤字脱字でも構いませんので、見つけたならば教えてください。

報告は、こちらのブログにコメントいただくか、Twitterで @shuji_w6e宛または、 #junitbook のハッシュタグでお願いします。Facebookでも構いません。

『JUnit実践入門』正誤表(5) #junitbook

| 11:19 |  『JUnit実践入門』正誤表(5) #junitbookを含むブックマーク

誤植速報その5です。

その1,その2,その3, その4, 技評さんの公式サイトです(おって反映されます)。

P286 ソースコードエンコーディング設定(本文6行目)

誤)

POMのpropertiesセクションにproject.build.sourceEncofingタグを追加して指定します

正)

POMのpropertiesセクションにproject.build.sourceEncodingタグを追加して指定します

fとdのtypoです。

P421 テキストファイルのエンコーディング設定(本文6行目)

誤)

「テスト・ファイルのエンコード」の「その他」で「UTF-8」を選択します

正)

「テスト・ファイルのエンコード」の「その他」で「UTF-8」を選択します

テキストの「キ」が抜けています。

ご迷惑をおかけして申し訳ありません。

報告して頂いた@hakuu0さん、@tomix55さん、ありがとうございます!

(6)に続く...

*1:1から順に指定された値まで数字を出力する。ただし、3の倍数の場合はFizz、5の倍数の場合はBuzz、3と5の公倍数の場合はFizzBuzzと出力する。

nozuenozue 2012/12/18 18:32 お世話になります。
正誤表を探してこちらに辿りつきました。

p.362のテストケースの5つ目

addで同じItemオブジェクトを追加すると・・・

addで異なるItemオブジェクトを追加すると各々のgetNumで・・・

というような意味でしょうか?どこかに掲載されていたらすみません。

shuji_w6eshuji_w6e 2012/12/20 01:28 はい、誤植のようです。
おっしゃるとおり、
・addで異なるItemオブジェクトを追加すると各々のgetNumで
が正しいと思われます(テストコードと対応する)。

おって、正誤表に追加します。
ご迷惑をおかけして、申し訳ありません。