検索
連載

EclipseとJUnitによるテスティング(2) テストファーストでコードを作成する快適なXPドライビングのすすめ(5)

PC用表示 関連情報
Share
Tweet
LINE
Hatena

 前回「EclipseとJUnitによるテスティング」は「テストの意義」と「テスティングフレームワーク」に焦点を絞って解説しました。今回は実際にEclipseを使ってテストファーストでコードが作られていく様子をチュートリアル形式でご紹介します。JUnitを用いた単体テストはXP開発でなくてもシステムの品質向上に十分に役に立つプラクティスです。ぜひJUnitの持つパワーを体験してみてください

■EclipseでJUnitを使ってみよう

 EclipseにはすでにJUnitによるテスト実行環境が備わっています。そのほかにもCVSやリファクタリングと、まさにXPのための開発環境だといえます。それでは、Eclipseでテストファーストをやってみましょう。Enjoy Testing!

■EclipseでJUnitを使う準備

 まずはプロジェクトのビルドパスにjunit.jarを追加します。ビルドパスの追加にはいくつかの方法があります。ここでは2つの方法をご紹介します。どちらかの方法でjunit.jarをビルドパスに追加してください。

(1)クラスパス変数「JUNIT_LIB」を定義する方法

 jarファイルやディレクトリに対するエイリアスをクラスパス変数として定義することができます。一度定義してしまえば、どのプロジェクトからでも呼び出すことができ、また最新版のjarファイルへの変更なども一発でできて便利です。ここではjunit.jarへのエイリアスとして、クラスパス変数「JUNIT_LIB」を定義します。junit.jar自体はEclipseのインストールディレクトリ直下の「plugins」フォルダの「org.junit_3.7.0」にあります。

◎クラスパス変数「JUNIT_LIB」の定義

  1.[ウィンドウ]-[設定]

  2.[Java]-[クラスパス変数]-[新規]

    新規変数エントリダイアログが表示されます。


ALT
図1 新規変数エントリ

  3.必要事項を記入します

   名前:JUNIT_LIB

   パス:(junit.jarまでの絶対パス)


ALT
図2 クラスパス変数設定(クリックすると拡大)

  4.[OK] - [OK]

◎ビルドパスにクラスパス変数「JUNIT_LIB」を追加

  1. [プロジェクトの上で右クリック]-[プロパティ]-[Javaのビルド・パス]-[ライブラリ]-[変数の追加]新規変数クラスパス・エントリダイアログが表示されます。
  2. 「JUNIT_LIBを選択」-[OK]-[OK]これでプロジェクトのビルドパスにjunit.jarを追加することができました。

ALT
図3 JUNIT_LIBの追加

(2)プロジェクト内にjunit.jarをインポートする方法

 プロジェクトに「lib」フォルダを作り、そこに「junit.jar」をインポートします。インポートしたjarファイルをビルドパスに追加してください。配布時に「junit.jar」を含みたいときなどに便利だと思います。

■Eclipseによるテストファーストチュートリアル

 さて、ここではEclipseとJUnitを使って、テストファーストを体験していただきたいと思います。短いチュートリアルですが、単体テストやテストファーストのメリット、つまり「『テストがある』状態ならコードの変更も安心して行える」「最終的には品質向上につながる」などを実感していただければと思います。ではさっそくチュートリアルの始まりです。Enjoy Testing!

テストコードは仕様であり、ドキュメントだ!

 テストファーストで書かれるコードは仕様であり、ドキュメントです。テストコードを見れば、テスト対象のクラス・メソッドの振る舞い、使い方を知ることができます。また、テストコードはテスト対象のコードとともに、自然に成長し、更新されていきます。そのためにもテストコードにはコメントをなるべくたくさん書きましょう。また、テストコードは冗長な部分があってもいいので、分かりやすい、シンプルなメソッドの使い方を表す書き方をしましょう。引き継ぎやシステムの機能拡張のとき、本当の意味でテストコードのありがたみを知ることになります。


■テスト対象クラスの機能

 このチュートリアルで作成する機能は、文字列の分割(split)メソッドです。これは、例えば文字列“a,b,c”と区切りカンマ“,”を引数として渡すと、カンマで文字列を分割してString型の配列[“a”][“b”][“c”]を返してくれるものです。

 JDKの1.4から、Stringクラスに正規表現によるsplitメソッドが実装されていますが、JDK 1.4以前でも同じような処理を行うことができるように、ユーティリティメソッドとしてsplitを作成してみたいと思います。

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

1.テストコードの作成

 プログラミングの最初のステップはテストコードの記述です。Eclipseではテスト対象クラスから、テストクラスを作成する機能があります。次の手順でテスト対象クラスとテストクラスのひな型を作ります。

テスト対象クラスのひな型を作成する

 ここでは「StringUtil」クラスを新規作成します。

  1.[ファイル]-[新規]-[クラス]

   Javaクラスウィザードが表示されます。

  2.[必要項目を入力]-[終了]

   ・プロジェクト:(プロジェクト名入力、もしくは「ブラウズ」で選択)

   ・パッケージ:空(デフォルト・パッケージ)

   ・名前:StringUtil

   ・スーパークラス:java.lang.Object

   ・チェックボックス:すべて外す


ALT
図4 空のクラス作成(クリックすると拡大)

テストクラスを作成する

 テスト対象のStringUtilからJUnit用のテストクラスを作成します。

  1.[StringUtilの上で右クリック]-[新規]-[その他]

   新規・選択ウィザードが表示されます。


ALT
図5 [新規]-[その他](クリックすると拡大)

ALT
図6 新規・選択(クリックすると拡大)

  1.[Javaを展開]-[JUnit]-[TestCase]-[次へ]

   新規JUnit TestCase作成ウィザードが表示されます。

  2.[必須項目を入力]-[終了]

   ソースフォルダ:(プロジェクト名入力、もしくは「ブラウズ」で選択)

   パッケージ:空(デフォルト・パッケージ)

   テストケース:StringUtilTest

   テストクラス:StringUtil

   スーパークラス:junit.framework.TestCase

   チェックボックス:すべてチェック

   TestRunnerステートメントの追加:(Eclipseを使わない人のために選択しておく)


ALT
図7 新規JUnitTestCase(クリックすると拡大)

 これでテスト対象クラス、テストクラスのひな型が完成しました。では「StringUtilTest」にテスト用のコードを記述します。テストコードを記述するメソッド名は、testから始まる名前にする必要があります。この[testXXX]というメソッドを、JUnitのフレームワークがJavaリフレクションAPIを利用して呼び出すことでテストが実行されます。メソッド名はテスト対象のメソッド名を後ろに付けると分かりやすいです。ここではtestSplit()というメソッドを作成します。


*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

 テストファーストの場合、クラスやメソッドの使い方を中心にコーディングを行います。まずはsplitメソッドの使い方を考えてみましょう。文字列を指定された区切り文字列で分割するので、引数は文字列と区切り文字列の2つでしょう。StringUtil#splitメソッドはまだ存在しませんが、「あるもの」としてコーディングします。戻り値は分割された結果がString型の配列で返されるはずです。よってテストコードは次のようなものが考えられます。まずはこのテストコードを記述します。


*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

 テストコードの中で「assertEquals()」というメソッドが呼ばれています。このメソッドはTestCaseの親クラスAssertの持っている判定用メソッドで、第1引数と第2引数をObject#equals()で比較してtrueのときに判定成功となります。失敗した場合、例外が返されて、このテストメソッドのテストは終了します。このようにメソッドの戻り値やオブジェクトの状態を判定することによって、期待した振る舞いをテストしていきます。


*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

 テストコードが完成したら保存してコンパイルしてみましょう。もちろん、StringUtilにはsplitメソッドがないのでコンパイルエラーが出ます。ここではEclipseの未作成メソッドの自動生成機能を使って空のsplitメソッドを作成してみましょう。

未作成メソッドの自動生成機能

  1.[CTRL+s でテストコードを保存・コンパイル]

   ソース中にコンパイルエラーを示す電球マーカーが表示されます。

  2.[電球マーカーをクリック]-[split(..)' を StringUtil に作成]を選択

StringUtilクラスに空のsplitメソッドが作成されます。保存するとStringUtilTestのコンパイルエラーがなくなります。これでひとまずテストクラスが完成しました。


ALT
図8 電球マーカー(クリックすると拡大)

ALT
図9 メソッド自動生成(クリックすると拡大)

2.テストの実行(失敗)

 実装コードは記述していませんが、テストを実行してみます。実装コードがありませんので、テストは失敗しますが、これは「テストが必ず失敗する」ことを確認するのが目的です。これで成功した場合、テストがきちんと作成されていない可能性があります。テストの実行は次の手順で行います。

ペアプログラミングとユニットテスト

 ペアプログラミングとユニットテストを組み合わせることで、1人でテストコードを書くよりも、より良いテストコードを書くことができます。テストを書くということは、仕様を明確にして、設計を行っていきます。この作業をペアで行えば1人でやるより、仕様的に必要なもの必要でないものの切り分けがうまくいきます。また、テストを使うことで心配なのは、そのテストコードの質です。1人で書いた謎(なぞ)のテストコードより、2人で書いた確かなテストコードの方がいいのは当たり前です。また、コードの共同所有を行うことで、テストコードも「たくさんの目」に触れることになり、さらに強固なテストコードが出来上がっていくことになります。


JUnitテストの実行

  1. [パッケージ・エクスプローラ]上の[StringUtilTest]をダブルクリックしてソースビューにソースを表示する
  2. [実行]-[次を実行]-[JUnitテスト]を選択

 実行すると、StringUtilの空のsplitメソッドはnullを返す実装なので、

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

 この条件でテストは失敗し、画面上には失敗を表す「赤いバー」がのびます。


ALT
図10 テスト失敗

3.実装コードの記述

 では実装コードを記述します。java.util.StringTokenizerを使って分割処理を記述してみます。次のコードをStringUtilに追加します。


*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

4.テストの実行

 実装が済んだらもう一度テストを実行します。今度は、ちゃんと期待どおり動くように実装しているので成功を示す「緑のバー」がのびます。


ALT
図11 テスト成功

5.さらにテストコードを追加してみる


*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

6.さらにさらにテストコードを追加……実装コードの変更が発生した!

 さらに実装コードの変更を伴うテストコードを追加してみます。下記のテストコードでは、分割対象の文字列に空文字が含まれています。Splitメソッドの仕様としては、空文字も分割の結果に含まれるのを正しい動きとして、テストコードを記述してみました。このテストを実行してみてください。結果は失敗になります。StringTokenizerクラスでは区切り文字間の区切り文字が空文字の場合、結果のトークンに含まれない仕様となっているからです。


*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

 よってStringUtilの実装コードをStringTokenizerを用いない処理に大幅に変更してみます。


*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***

 再度テストを実行します。いままでのテストがすべて行われて成功するはずです。単体テストがあればこのように「変更前の状態が正しいこと」「変更が正しいこと」を確認できます。しかもこのテストはボタン1つで「いつでも・何度でも・自動的に」実行することができます。「動くものにも触れることができる」状態を保っていくためにも単体テストをきちんと作っていくことをお勧めします。

TestSuiteでテストをまとめて実行

  1.[(デフォルト・パッケージ)の上で右クリック]-[新規]-[その他]

   新規・選択ウィザードが表示されます。(普通はTestSuiteを作りたい

   パッケージの上で右クリックすることになります)

  2.[Javaを展開]-[Junit]-[TestSuite]-[次へ]

   新規 Junit TestSuite作成ウィザードが表示されます。

3.[必須項目を入力]-[終了]

   ソースフォルダ:(プロジェクト名入力、もしくは「ブラウズ」で選択)

   パッケージ:空(デフォルト・パッケージ)

   テストケース:StringUtilTest

   テスト・スイート:AllTests

   スイートに含まれるテストクラス:(スイートに含まれるテストクラスをチェック)

   チェックボックス:すべてチェック

   TestRunnerステートメントの追加:(Eclipseを使わない人のために選択しておく)

ALT
図12 JunitTestSuite(クリックすると拡大)

*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***



 今回は、テストファーストプログラミングを体験してみました。テストのパワーを感じて頂けたのではないかと思います。車の運転と同じで、「体験」のあとは「実践」することが大切です。ぜひ、開発の現場でテストファースト/ユニットテストを実践して欲しいと思います。次の段階では、プロジェクトリーダーやチームメンバーにテストの必要性を伝えていきましょう! チームで実践してこそ、テストのメリットが生きてきます。次はあなたがテストの伝道師となる番です。そのときは、ぜひ本マニュアルをご活用下さい。

 さて、次回のテーマは、リファクタリングです。リファクタリングの基本的な考え方と、Eclipseに備わる強力なリファクタリング機能を合わせてご紹介します。お楽しみに!

この記事に対するご意見をお寄せください

managemail@atmarkit.co.jp


著者紹介

▼縣俊貴(あがた としたか)

 メディアファイブ株式会社所属。XML,フレームワークを中心に開発業務に携わる。Javaのコミュニティー団体であるMobsterを主催。現在MonsterにてJavaベースのWikiシステム「MobWiki」を開発している。

▼橋本正徳(はしもと まさのり)

 メディアファイブ株式会社所属。XML、フレームワーク等の開発業務に携わる。Javaのコミュニティー団体である「Mobster」を縣と共に発起、運営。現在mobsterにてバグトラッキングシステム「mobbug」等を開発している。「日本XPユーザーグループ関西支部 九州分科会」にも参加。ちなみにこの記事自身もCVSでバージョン管理し、縣と橋本とで共同所有されて書かれている。

▼Project Mobster(ぷろじぇくと もぶすたー)

福岡県福岡市を中心にJava言語を研究追求し、その成果物をWeb上に公開していく団体です。年齢・スキル・会社などを超えてボーダーレスに活動しております。


Copyright © ITmedia, Inc. All Rights Reserved.

ページトップに戻る