Index: [Article Count Order] [Thread]

Date:  Sun, 24 Sep 2000 12:11:39 +0900
From:  Kaoru Hosokawa <khosokawa@....com>
Subject:  [XP-jp:00928] Re: テストのためだけのメソッド
To:  extremeprogramming-jp@....jp (extremeprogramming-jp ML)
Message-Id:  <B5F39F13.3A0C%khosokawa@....com>
In-Reply-To:  <39CC6B73.D7379A67@....jp>
Posted:  Sun, 24 Sep 2000 12:09:12 +0900
X-Mail-Count: 00928

ホソカワです。

on 00.9.23 5:18 PM, firo@....jp at firo@....jp wrote:

> 矢崎です。
> 
> omura@....jp さんwrote:
> 
>> 
>> とにかく、一番重要なのはテストをすることなので、reflectionを使うことに決めて
>> しまって、それで面倒くさくなってテストをやめたりしたら、本末転倒ですから。
>> 
> 
> reflectionを使うかどうかに限らず、確かに、テストが面倒くさく
> なるようだとテストをしなくなる可能性が高まります。そうなると、
> XPの根幹を揺るがしかねませんね。
> 
> 例えば、あるクラスについて、コンストラクタでデータを
> 与えてやるが、そのデータを取り出すためのgetメソッドが
> いらないような場合を考えます。当然そのデータは必要が
> あるからコンストラクタの引数で渡したわけだし、おそらく内部
> で保管されていて、あるメソッドで使われることでしょう。しかし、
> それをgetメソッドで取り出すニーズはない、ということです。
> 
> 例として、コンストラクタでSQL文を与えて、
> executeとメソッドで、DBからSQLでデータを取得するような
> オブジェクト、SqlHandlerなるものを考えます。
> 
> SqlHandler aSqlHandler = new SqlHandler("SELECT XX,YY, FROM ZZ_TBL");
> ResultSet rs = aSqlHandler.execute();
> 
> SqlHandlerはSQL文がないと意味がないので、これをコンストラ
> クタで与えています。しかし、それを後から取り出す必要は
> ない(とここでは考えているとします)。後必要なのは、
> コンストラクタで与えられたSQL文どおりの結果をDBから
> 取り出し、クライアントに返すということです。したがって、
> JUnitでテストする場合、コンストラクタとexecuteメソッド
> のテストになります。
> 
> 人情としてはコンストラクタの実行の後、正しくSQL文が
> 渡ったかどうかを確認したくなるところです。しかし、もし
> テストのためだけのメソッドがだめ、となると、それを確認
> するのはexecuteを実行して、その結果、つまり取得した
> ResultSetの結果を判断して、渡したSQLどおりの抽出
> 結果になったかどうかを判断する、ということになります。
> 
> これはこれで正しいかもしれませんが、テストをさっと書い
> て、さっと実行する、というリズムは狂うかもしれません。
> この例では、まだ因果関係がわかりやすいのですが、もう
> 少し複雑になると、テストを書くこと自体に頭を非常につか
> い、時間がかかり、テスト自体がまちがっていた、というこ
> とにもなりかねません。

public class SqlHandler {
    private String command;

    SqlHandler(String command) {
        this.command = command; // テストできない
    }
}

「SQL コマンドの代入が正しく行われたかどうかテストできない」ということですね。

> 
> そう考えると、少なくともget系のメソッドは、テスト用でしか
> ないとしても、作ってよい、くらいはしたほうがいいのかもし
> れませんね。

そうですね。VXPでは、このようにしませんか?

public class SqlHandler {
    private String command;

    SqlHandler(String command) {
        this.command = command;
    }

    /* testuse */ public String getCommand() {
        return command;
    }
}

「テストのためだけのメソッド」の作成を許します。ただし、そのメソッドには、必
ず、/* testuse */ とつけることとします。(これによって、このメソッドは、テス
トに使用しているもので、本来の機能ではないことを明確にしています。)このメソッ
ドは、refactoring などで、機能の一部に昇格することができます。この時は、/*
testuse */ を必ずはずすこととします。

問題は、メソッドが増えて、コードが大きくなることですが、テスト以外では使われ
ていないので、製品から見ると dead code です。世の中に dead code をはずすコン
パイラ、ツールがあるでしょうから、問題ないと思っています。

小井土さん、大村さん、「テストとクラスの分離」という観点からみてどうでしょう
か?

-- 
Kaoru Hosokawa
khosokawa@....com