2

私のクラスでは、J-Unit でテストを練習するよりも、ArrayStacks と LinkedStacks を作成しています。私たちのテストの 1 つは clear() メソッドです。私たちの教授は、スタック内の各要素を null にして、それらが null であることをテストするよりも具体的に求めました。どうすればいいですか?

public void clear() {
    // Checks if this stack is empty,
    // otherwise clears this stack.

    if(!isEmpty()){
        for(int i = 0; i < sizeIs(); i++){
            pop();
        }
        topIndex = -1;
    }
}


public class Test_clear {

/*
 * Class to test the clear method added to the Stack ADT of Lab04
 * 
 *   tests clear on an empty stack
 *     a stack with one element
 *     a stack with many (but less than full) elements
 *     and a "full" ArrayStack (not applicable to Linked Stack - comment it out)
 */

    ArrayStack stk1, stk2;

@Before

public void setUp() throws Exception {
    stk1 = new ArrayStack();  stk2 = new ArrayStack();
}

@Test  
public void test_clear_on_an_emptyStack() {

    stk1.clear();

    Assert.assertEquals(true, stk1.isEmpty());
}

@Test  
public void test_clear_on_a_stack_with_1_element() {

    stk1.push(5);

    stk1.clear();

    Assert.assertEquals(true, stk1.isEmpty())'
}

等々。しかし、 isEmpty() で assertEquals をチェックしても、配列内の要素がクリアされているかどうかはテストされません。前もって感謝します!

4

3 に答える 3

2

この種の演習は、Java の詳細を学習するという観点からは価値がありますが、これを他の問題に適用する前に注意することをお勧めします

JUnit を使用して、テスト対象のクラスのパブリック インターフェイスを実行することをお勧めします。の場合ArrayStack、いくつかのメソッドがあると仮定しましょう:

  • void push(Object o)
  • Object pop()
  • void clear()

@dkaztzel は、1 つの解決策を提案しました。パッケージのプライベート メソッドを実装して、内部スタックの内容を防御的にコピーすることです。次のように見えるとしましょう。

Object[] getStack() {
    return stack.clone();
}

pushそれを検証するためにいくつかの単体テストを実装し、pop意図したとおりに機能していると仮定すると (空のスタックと完全なスタックのエッジ ケースを含む)、次のように単体テストを作成します。

@Test
public void probablyNotAGoodTest() {
    ArrayStack arrayStack = new ArrayStack();
    arrayStack.push("Luke");

    arrayStack.clear();

    Object[] stackCopy = arrayStack.getStack();
    assertNull(stackCopy[0]);
}

これにより、要素がポップされたら、実際にインデックスの値を null に設定したことを確認するという目的が達成されます。コントラクトのテストを支援することだけを目的とした製品コードを書かなければならないとき、私はいつも少し疑いを持っています。このアプローチが間違っているとは言いませんが、慎重な検討が必要です。ここでの要件は、ポップされたオブジェクトが実際に内部スタックから削除されることを確認することなので、おそらくこれで問題ありません。

もう 1 つのアプローチは、ArrayStackインターフェイスを充実させ、特定のインデックスで特定のオブジェクトを取得するメソッドを提供することです。このメソッドは、null オブジェクトが検出された場合に例外をスローする可能性があり、それをテストできます。メソッドとテストは次のようになります (これを使用する前に、追加の検証を行ってください)。

public Object getObjectAtIndex(int i) {
    if (i >= maxSize) {
        throw new IllegalArgumentException();
    }
    if (stack[i] == null) {
        throw new NullPointerException();
    }

    return stack[i];
}

そして、テスト:

@Test(expected=NullPointerException.class) 
public void tryToGetAClearedObject() {
    ArrayStack arrayStack = new ArrayStack();
    arrayStack.push("Luke");
    arrayStack.clear();
    arrayStack.getObjectAtIndex(0);
}

幸運を!

于 2013-10-01T05:39:08.160 に答える
0

他の回答が示唆nullするように、ストレージ アレイのアウトはパブリック API によって直接検証できません。protectedストレージを直接検査できるようにするメソッドを追加するのが最も簡単です。

別の方法として、この機能の理由を検討してください。配列に保持されているすべての参照は、clearが呼び出されたときに解放する必要があります。Referenceこれは、パブリック API、 s、および GC に関するいくつかの仮定のみを使用してテストできます( Java で GC されるように、弱いおよび/またはソフト参照オブジェクトを強制する方法はありますか? )。

オブジェクトをスタックに置き、 を保持してReferenceから、次のclearようにします。

ReferenceQueue queue = new ReferenceQueue();
PhantomReference ref = addObjectToStackAndCreateReference(arrayStack, queue);

arrayStack.clear()

別のユーティリティ メソッドを使用して、そのオブジェクトを Java スタックから遠ざけます。これにより、コレクションが妨げられる可能性があります。

private static PhantomReference addObjectToStackAndCreateReference(ArrayStack arrayStack, ReferenceQueue queue)
{
    Object o = new Object();
    PhantomReference ref = new PhantomReference(o, queue);
    arrayStack.push(o);
    return ref;
}

ここで、オブジェクトへの参照が残っていないことを確認して、参照がキューに登録されていることを確認します。

System.gc();
assertSame(ref, queue.remove());

テストを簡単にするメソッドを追加することをお勧めします。ただし、これはテスト専用 API を追加せずにテストできる 1 つの方法です。

于 2013-10-05T09:06:13.537 に答える