Menu

FrontPage

Eclipseプラグイン
Eclipse小技集
リファクタリング講座
テスティングフレームワーク JUnit
MSDEについて



The 20 newest affair
2010-09-092010-09-082010-09-072010-09-062010-09-012010-08-312010-08-272010-08-242010-08-232010-08-172010-08-162010-07-302010-07-212010-07-132010-06-272010-06-182010-06-172010-06-16









はじめてのテスト ~ HelloWorldTest  Λ

プログラミングの入門書などで、はじめてのプログラム「HelloWorld」を、よく目にします。
javaだと、こんな感じです。

1 public class HelloWorld {
2 
3   public static void main(String[] args) {
4     System.out.println("Hello World.");
5   }
6 
7 }

では、はじめてのテストは、HelloWorldのテスト「HelloWorldTest」だと思うのですが、
JUnit Cookbookをチラ見しても、HelloWorldTestはありませんでした。
HelloWorldTestは、はじめてのテストとしては、不向きなのかもしれません。

以下は、少しまじめに考えて、HelloWorldのテストを「JUnit」「djUnit」を使って作成してみます。

JUnitでのHelloWorldTest  Λ


調べてみるとdWにHelloWorldTestがありました。

    AntとJUnitを用いた漸進的開発(http://www-6.ibm.com/jp/developerworks/java/010223/j_j-ant.html)

ソース例

この記事によりますと、テスト対象であるHelloWorldは、

01 public class HelloWorld {
02 
03   public static void main(String[] args) {
04     HelloWorld world = new HelloWorld();
05     System.out.println(world.sayHello());
06   }
07 
08   public String sayHello() {
09     return "Hello World.";
10   }
11 }

のようになっており、
  • "Hello World."がメソッド化
されています。

一方、HelloWorldTestのテストメソッドは、

01 import junit.framework.TestCase;
02 
03 public class HelloWorldTest extends TestCase {
04 
05   // 省略
06 
07   public void testSayHello() {
08     HelloWorld world = new HelloWorld();
09     assertNotNull(world);
10     assertEquals("Hello World.", world.sayHello());
11   }
12 }

のようになっております。

sayHelloメソッドにしたことにより、テストしやすくなっているようです。
確かにJUnitは、メソッドを実行し、その戻り値を検証するのが得意そうです。

違う議論になりそうなので、あまり触れたくありませんが、sayHelloメソッドをpublicではなく、package privateにし、HelloWorldと、HelloWorldTestのパッケージを同じにするという努力をしている方もいるようです。

問題点

ケチをつけるつもりはないのですが、今後のために、このテストの問題点を探してみます。

  • HelloWorldのmainメソッドが実行されていない
  • テストメソッドの名前が、testSayHelloとなってしまっている

以上のことから、このHelloWorldTestは、HelloWorldのテストというより、むしろ

    sayHelloのテストですYO!

djUnitでのHelloWorldTest  Λ


JUnitでテストするということは、「コンソールに文字を出力する」という、たった1行のプログラムのテストでも、ある程度工夫が必要みたいです。

我々が製造するアプリケーションは、たとえそれが、WEBアプリケーションで、フレームワークを利用して作るものだとしても、
HelloWorldよりは複雑になってしまうことが、ほとんどです。きっと、もっと工夫が必要になるはずです。

ここでdjUnitを利用し、HelloWorldのテストにチャレンジしておきます。

ソース例

テスト対象は、最初の

1 public class HelloWorld {
2 
3   public static void main(String[] args) {
4     System.out.println("Hello World.");
5   }
6 
7 }

です。

対するHelloWorldTestは、このようになります。

01 import jp.co.dgic.testing.framework.DJUnitTestCase;
02 
03 public class HelloWorldTest extends DJUnitTestCase {
04 
05   // 省略
06 
07   public void testMain() {
08     HelloWorld.main(null);
09 
10     String arg = (StringgetArgument("java.io.PrintStream""println"0);
11     assertEquals("Hello World.", arg);
12   }
13 }

HelloWorld.main()のアウトプットは、java.io.PrintStream#printlnメソッドの引数であることに注目しています。
HelloWorld.main()が実行され、System.out.printlnが実行されたならば、getArgumentメソッドで、引数を取り出すことができます。

Object DJUnitTestCase#getArgument(String クラス名, String メソッド名, int 引数のインデックス);

引数のインデックスとは、「何番目の引数をgetする」というのを0からはじまる整数で指定します。
printlnの引数は、1つですので、「0」を指定しています。

検査対象の引数が単純であれば、、下記のようにしても同様のテストができます。

01 import jp.co.dgic.testing.framework.DJUnitTestCase;
02 
03 public class HelloWorldTest extends DJUnitTestCase {
04 
05   // 省略
06 
07   public void testMain() {
08     HelloWorld.main(null);
09 
10     assertArgumentPassed("java.io.PrintStream""println"0"Hello World.");
11   }
12 }

assertArgumentPassedは、取得した引数と、予想値を、「equals」で比較し、検証します。

void DJUnitTestCase#assertArgumentPassed(String クラス名, String メソッド名, int 引数のインデックス, Object 予想値);

結論  Λ


djUnitによるテストでは、テスト対象のプログラムを、(テストのためだけに)修正することなくテストしています。
そして、デフォルトコンストラクタを除けば、HelloWorldの全ステップを実行しています。

このようなアプローチもありだと思いますし、もっと複雑なプログラムのテストへ応用できそうです。


Attached File: [Attached File All List]

Lastmodified: 2009-06-05 (金) 13:55:47 (460d)