ホソカワです。ちょっと教えてください。
on 2000/04/21 6:19 PM, firo at firo@....jp wrote:
> 矢崎です。
>
> Junitの使い方をまとめました。先刻ご承知の方も
> 多かろうとは思いますが、ご勘弁を。
>
> #なお、JUnitを使う方法にはいろいろバリエーション
> があって、以下はそのうちの1つのやり方です。例え
> ば以下はsuiteメソッドは書いていません。そうしたバ
> リエーションについても後日投稿したいと思います。
>
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ◇以下のクラスのテストを行うとする。(TestTarget.java)
>
> public class TestTarget {
>
> int number;
> String name;
>
> public TestTarget(){
> name = "";
> }
>
> public void setNumber(int number){
> this.number = number;
> }
>
> public int getNumber(){
> return this.number;
> }
>
> public void setName(String name){
> this.name = name;
> }
>
> public String getName(){
> return this.name;
> }
> }
>
>
例えば、Employee見たいな名前と社員番号を持っているクラスですね。
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 1.TestCaseのサブクラスを作る(ConcreteTestCase.java)。
>
> import junit.framework.*; //1
>
> public class ConcreteTestCase extends TestCase{ //1
> } //1
>
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 2.String型の引数を1つだけ持つ、コンストラクタを作る。
> 引数として受け取った文字列は、このクラスのインスタン
> スの名前になる。
>
> このコンストラクタの中身は、受け取った文字列を引数
> としてスーパクラスのコンストラクタを呼ぶように書く。
>
> import junit.framework.*;
>
> public class ConcreteTestCase extends TestCase{
>
> public ConcreteTestCase(String name){ //2
> super(name); //2
> } //2
>
> }
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 3.必要ならばsetUpメソッドをオーバライドする。原則的に
> はオーバライドすることになるでしょう。何をするかというと、
> ユニットテストをする対象のオブジェクトをnewする。
> newしたオブジェクトを入れておくためのインスタンス変数
> も定義する。
>
> import junit.framework.*;
>
> public class ConcreteTestCase extends TestCase{
>
> /*以下の変数は任意。型はテストしたいクラス。数も自由*/
> TestTarget aTestTarget; //3
>
> public ConcreteTestCase(String name){
> super(name);
> }
>
> /*setUpはリターンはvoid。引数はなしじゃないとだめ。*/
> public void setUp(){ //3
> aTestTarget = new TestTarget(); //3
> } //3
>
> }
>
例えば、setUp()でファイルをオープンしようとして、エラーになった場合、例外で
戻るのでしょうか?どこへ戻るのでしょうか?
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 4.必要ならばtearDownメソッドをオーバライドする。tearDown
> メソッドは後片付けをするメソッドで、変数に残っているオ
> ブジェクトを消す。しかしJavaにはガベージコレクション機
> 能があるので、何しなくてもよい(ゆえにオーバライドしな
> くてよい)。
>
> import junit.framework.*;
>
> public class ConcreteTestCase extends TestCase{
>
> TestTarget aTestTarget;
>
> public ConcreteTestCase(String name){
> super(name);
> }
>
> public void setUp(){
> aTestTarget = new TestTarget();
> }
>
> /*tearDownはリターンはvoid。引数はなしじゃないとだめ*/
> public void tearDown(){ //4
> aTestTarget = null; //4
> //一応nullにしておく //4
> } //4
>
> }
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 5.Testメソッドを作る。シグニチャは以下のルールに従わなけれ
> ばならない。
>
> 1)リターンはvoid。
> 2)引数はなし。
> 3)メソッド名は"test"から始める
> 4)publicでなければならない。
>
> それと、メソッド数はいくつでもよい。定義しただけテストが実行さ
> れる。メソッドの実行順序は不定。(ゆえに、この作業で、新しいイ
> ンスタンス変数を定義する必要はないと思われる。定義してもい
> いけど)
> #ローカル変数は、必要なら定義する。
>
> import junit.framework.*;
>
> public class ConcreteTestCase extends TestCase{
>
> TestTarget aTestTarget;
>
> public ConcreteTestCase(String name){
> super(name);
> }
>
> public void setUp(){
> aTestTarget = new TestTarget();
> }
>
> public void tearDown(){
> aTestTarget = null;
> }
>
> public void testXXX(){ //5
> //5
> } //5
>
> public void testYYY(){ //5
> //5
> } //5
>
> public void testZZZ(){ //5
> //5
> } //5
>
> }
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 6.各Testメソッドの中身は以下のように作る。
>
> 1)テストのTargetのオブジェクトの、テストしたいメソッドを
> 呼び出す。
> 2)そのメソッドのリターン値か、あるいはそのメソッドの結果
> を取得できる別のメソッドを実行し、結果を取得する。
> 3)その結果を判断するassert関連メソッドを呼び出す。
> ※assert関連メソッドは14種類ある。
> ※14種類のassert関連メソッドで対応できない場合は、
> 独自のassert関連メソッドを作らなければならない。
>
assertメソッドをリストしていただけますか?
>
> public void testXXX(){
>
> int wkInt;
> String unitName;
>
> aTestTarget.setNumber(0);
> aTestTarget.setNumber(1000);
> wkInt = aTestTarget.getNumber();
> assertEquals(wkInt,1000);
>
> aTestTarget.setName("TARO");
> assertEquals("TARO",aTestTarget.getName());
>
> }
>
>
テストもシンプルにするべきですから、numberのテストとnameのテストを別々にする
のでしょうね。なぜ、ここでこだわっているのかというと、テストメソッドにコメン
トはつけないのかな?と思っただけです。コメントがあれば、中身を読まなくてすむ
のですが、コメントを付ける暇があるのならrefactoringするのでしょうね。
> 上のメソッドでは、最初のassertEqualsでエラーがあった場合、
> そこから先のチェックは行わない。別のメソッドの実行は行う。
>
一つ目のエラーでとまった方がいいような気もしますが、エラーが起きても次のtest
メソッドを呼ぶようですね。一つ目のエラーでオブジェクトがエラー状態になる可能
性があるので、後半のテストは全滅という可能性もありますよね。testごとに新規に
オブジェクトをnewしたほうがいいのかな?しなくてもいいのかな?
> 他のメソッドの例
>
> public void testYYY(){
>
> int wkInt;
> String unitName;
>
> aTestTarget.setNumber(0);
> aTestTarget.setNumber(1000);
> assert(0 != aTestTarget.getNumber());
>
> aTestTarget.setName("TARO");
> assert(! "HANAKO".equals(aTestTarget.getName()));
>
> }
>
> public void testZZZ(){
> assertNotNull(aTestTarget.getName());
> }
>
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 7.ConcreteTestCase完成。
>
> import junit.framework.*;
>
> public class ConcreteTestCase extends TestCase{
>
> TestTarget aTestTarget;
>
> public ConcreteTestCase(String name){
> super(name);
> }
>
> public void setUp(){
> aTestTarget = new TestTarget();
> }
>
> public void tearDown(){
> aTestTarget = null;
> }
>
> public void testXXX(){
>
> int wkInt;
> String unitName;
>
> aTestTarget.setNumber(0);
> aTestTarget.setNumber(1000);
> wkInt = aTestTarget.getNumber();
> assertEquals(wkInt,1000);
>
> aTestTarget.setName("TARO");
> assertEquals("TARO",aTestTarget.getName());
>
> }
>
> public void testYYY(){
>
> int wkInt;
> String unitName;
>
> aTestTarget.setNumber(0);
> aTestTarget.setNumber(1000);
> assert(0 != aTestTarget.getNumber());
>
> aTestTarget.setName("TARO");
> assert(! "HANAKO".equals(aTestTarget.getName()));
>
> }
>
> public void testZZZ(){
> assertNotNull(aTestTarget.getName());
> }
>
> }
>
>
それで、実際にtestXXX(), testYYY(), testZZZ()をコールするのはだれなのでしょ
うか?どのようなメカニズムで呼ばれるのでしょうか?
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 8.コンパイルし通ったら、実行
>
>> java junit.ui.TestRunner ConcreteTestCase
>
> 9.テストが増えるごとに、上の5.6.を行う。
>
> #もし、間違いあったら教えてください。
--
Kaoru Hosokawa
khosokawa@....com