9

私には、多数のメトリックデータ構造(つまり、クアッドツリーkdツリーのバリアント)の実装を作成するタスクがあります。私はこれらの実装のうち約4つをダウンさせましたが、現在テストしている方法は、より良い言葉がないため、良いものではありません。

ノードの内部構造をテストできるように(親、子、順序などをチェックする)、これらのツリー/トライ構造からのデータの挿入と削除をテストするクリーンな方法が必要です。これらの実装は、個別の正確性の証明と実行時分析に従っているため、ノードが正しく挿入されている(つまり、後でツリーから取得できる)だけでなく、ツリー内の非常に「正しい」位置にあることを確認する必要があります。

「ユニットテスト」はこれを行うのに間違った方法のように思えますが、それは私が間違っていなければ、構造またはシステムの外部APIをテストすることが目的であるためです。「ユニットテストでプライベートフィールドにアクセスするにはどうすればよいですか」または「非公開メソッドの戻り値をテストするにはどうすればよいですか」というユニットテスト関連の質問をたくさん見ましたが、答えは一般的に「しない」です。 t"-そして私はこの答えに同意します。

ですから、漠然としたとりとめのないことを喜んで手伝ってくれる人を残さないので、私のツリーが実装するインターフェースは次のとおりです(JavaコレクションのMapインターフェースに基づく):

public interface SpatialMap<K, V> extends Iterable<SpatialMap.Entry<K, V>>
{
// Query Operations

/**
 * Returns the number of key-value mappings in this map. If the map contains more than
 * <tt>Integer.MAX_VALUE</tt> elements, returns <tt>Integer.MAX_VALUE</tt>.
 * 
 * @return The number of key-value mappings in this map.
 */
int size();

/**
 * Returns <tt>true</tt> if this map contains no key-value mappings.
 * 
 * @return <tt>true</tt> if this map contains no key-value mappings.
 */
boolean isEmpty();

/**
 * Returns <tt>true</tt> if this map contains a mapping for the specified key.
 * 
 * @param key
 *            The key whose presence in this map is to be tested.
 * @return <tt>true</tt> if this map contains a mapping for the specified key.
 */
boolean containsKey(K key);

/**
 * Returns the value to which the specified key is mapped, or {@code null} if this map contains
 * no mapping for the key.
 * 
 * <p>A return value of {@code null} does not <i>necessarily</i> indicate that the map contains
 * no mapping for the key; it's also possible that the map explicitly maps the key to
 * {@code null}. The {@link #containsKey containsKey} operation may be used to distinguish these
 * two cases.
 * 
 * @see #put(Comparable, Comparable, Object)
 * 
 * @param key
 *            The key whose associated value is to be returned.
 * @return The value to which the specified key is mapped, or {@code null} if this map contains
 *         no mapping for the key.
 */
V get(K key);

// Modification Operations

/**
 * Associates the specified value with the specified key in this map. If the map previously
 * contained a mapping for the key, the old value is replaced.
 * 
 * @param key
 *            The key with which the specified value is to be associated.
 * @param data
 *            The value to be associated with the specified key.
 * @return The previous value associated with the key, or <tt>null</tt> if there was no mapping
 *         for the key. (A <tt>null</tt> return can also indicate that the map previously
 *         associated <tt>null</tt> with <tt>key</tt>.)
 */
V put(K key, V data);

/**
 * Removes the mapping for the specified key from this map if present.
 * 
 * @param key
 *            The key whose mapping is to be removed from the map.
 * @return The previous value associated with the key, or <tt>null</tt> if there was no mapping
 *         for the key. (A <tt>null</tt> return can also indicate that the map previously
 *         associated <tt>null</tt> with <tt>key</tt>.)
 */
V remove(K key);

// Bulk Operations

/**
 * Removes all of the mappings from this map. The map will be empty after this call returns.
 */
void clear();
}

これにより、パブリックインターフェイスから利用できない特定のデータ(子/親ポインター)が必要になるため、パブリックメソッドのみでテストすることは困難になります。また、トライ構造(PR Quadtree、PRKDTree、MXバリアントなど)にはデータから分離されたノードがあるため、「ノード」を返すパブリックメソッドの作成も抽象化されすぎて、正しいデータを取得できません。

どのような種類のテスト方法(またはJUnitで使用でき、美しい認知境界を破壊しているようには感じられない手法)を探していますか?

4

3 に答える 3

5

このような場合、構造の内部状態を実際にテストする必要がある場合があります。この場合、リフレクションを使用して内部変数にアクセスします。これを簡単にするJUnitアドオン(PrivateAccessor http://junit-addons.sourceforge.net/junitx/util/PrivateAccessor.html )がいくつかあります。

トレードオフは、内部状態が変化するとテストが失敗する可能性があるため、テストがより脆弱になることです。ただし、内部状態が正しいことを確認したい場合は、これを行う必要がある場合があります。

于 2012-07-02T01:02:11.870 に答える
4

このタイプの状況で私が使用した方法の1つは、これらの内部フィールドを保護し、テスト用のサブクラスを作成することです。そのサブクラスを通じて、ホワイトボックステストに必要な状態を公開できます。

于 2012-07-02T02:52:06.317 に答える
1

インターフェイスとその実装を単独で専用パッケージに入れ、その実装の内部状態メソッドをパッケージで保護すると、テストでそれらにアクセスでき、場合によってはそれらをテストできますが、システムの他の部分では' t。

ユニットテストの「純粋主義者」には適していませんが、クラスの内臓をシステムの他の部分に公開したくないが、それでもその内部動作についてアサーションを作成したい場合は、通常、これを実行します。 。

于 2012-07-05T15:57:41.903 に答える