unit-testing - 無駄 - 単体テスト どこまで



並行性ユニットテストを実行するには? (9)

TestNGはJavaの並行性テストをサポートしています。 この記事では、その使用方法と、testngサイトにあるドキュメントについて説明します。

同じテストを同時に実行できるかどうかはわかりませんが

junitを使って並行性テストを実行するには?

私にクラスがあるとしましょう

public class MessageBoard
{
    public synchronized void postMessage(String message)
    {
        ....
    }

    public void updateMessage(Long id, String message)
    {
        ....
    }
}

私はこのpostMessageへの複数のアクセスを同時にテストすることにしました。 これに関するアドバイスは? 私はすべての私のセッター関数(または作成/更新/削除操作を含む任意のメソッド)に対してこのような並行性テストを実行したいと思います。


Answer #1

並行しているバグが存在していることを証明することはできません

しかし、いくつかの同時スレッドを生成し、@Test注釈付きメソッドを呼び出す特殊なテストランナーを書くことができます。


Answer #2

.NETには、ユニットテストの並行処理専用に設計されたTypeMock RacerMicrosoft CHESSなどのツールがあります。 これらのツールは、デッドロックのようなマルチスレッドバグを見つけるだけでなく、エラーを再現する一連のスレッドインターリーブを提供します。

私は、Javaの世界に似たものがあると思います。


Answer #3

あなたの例では、postMessage()メソッドは同期されているので、実際には単一のVM内で同時実行エフェクトは見られませんが、同期バージョンのパフォーマンスを評価できる場合があります。

異なるVMで複数のテストプログラムを同時に実行する必要があります。 あなたは使うことができます

テストフレームワークを手に入れることができない場合は、自分でVMを起動することができます。 プロセスビルダのものは、パスとそれ以外のものを持つ痛みですが、ここでは一般的なスケッチです:

Process running[] = new Process[5];
for (int i = 0; i < 5; i++) {
 ProcessBuilder b = new ProcessBuilder("java -cp " + getCP() + " MyTestRunner");
 running[i] = b.start();
}

for(int i = 0; i < 5; i++) {
 running[i].waitFor();
}

私は通常、単純なスレッドテストでこれをやっています。他の人が投稿したように、テストは正しさの証拠ではありませんが、実際は愚かなバグを振り払います。 これは、さまざまな状況下で長い時間テストするのに役立ちます。時には、並行性のバグがテストで明らかになるまでに時間がかかることがあります。

public void testMesageBoard() {
 final MessageBoard b = new MessageBoard();

 int n = 5;
 Thread T[] = new Thread[n];
 for (int i = 0; i < n; i++) {
  T[i] = new Thread(new Runnable() {
   public void run() {
    for (int j = 0; j < maxIterations; j++) {
      Thread.sleep( random.nextInt(50) );
      b.postMessage(generateMessage(j));
      verifyContent(j); // put some assertions here
    }
   }
  });

  PerfTimer.start();
  for (Thread t : T) {
   t.start();
  }

  for (Thread t : T) {
   t.join();
  }
  PerfTimer.stop();
  log("took: " + PerfTimer.elapsed());
 }
}**strong text**

Answer #4

並行性バグのテストは不可能です。 入出力ペアを検証するだけでなく、テスト中に発生する可能性のある状況で状態を検証する必要があります。 残念ながら、JUnitはこれを行うための装備がありません。


Answer #5

MultithreadedTCの使用をお勧めします。 - 並行性マスター自身Bill Pugh (そしてNat Ayewah )によって書かれています。 概要からの引用:

MultithreadedTCは、並行アプリケーションをテストするためのフレームワークです。 これは、複数のスレッドで一連のアクティビティを詳細に制御するために使用されるメトロノームを備えています。

このフレームワークにより、別々のテストで各スレッドのインターリーブを確定的にテストすることができます


Answer #6

同時に実行すると予期しない結果につながる可能性があります。 たとえば、私が発見したことは、テストスイートが200個のテストを通過したときに1つずつ実行されても、同時実行に失敗したため、それを掘り下げてスレッドセーフティの問題ではなく、悪いことだと私は問題を解決することができます。

MycilaはJUnit ConcurrentJunitRunnerで動作し、ConcurrentSuiteは非常に面白いです。 この記事は最新のGAリリースと比較して少し古いと思われます。私の例では、更新された使用法を示します。

以下のようなテストクラスに注釈を付けると、並行処理レベルが6のテストメソッドを同時に実行します。

import com.mycila.junit.concurrent.ConcurrentJunitRunner;
import com.mycila.junit.concurrent.Concurrency;

@RunWith(ConcurrentJunitRunner.class)
@Concurrency(6)
public final class ATest {
...

また、すべてのテストクラスを同時に実行することもできます。

import com.mycila.junit.concurrent.ConcurrentSuiteRunner;

@RunWith(ConcurrentSuiteRunner.class)
@Suite.SuiteClasses({ATest.class, ATest2.class, ATest3.class})
public class MySuite {
}

Mavenの依存関係は次のとおりです。

<dependency>
    <groupId>com.mycila</groupId>
    <artifactId>mycila-junit</artifactId>
    <version>1.4.ga</version>
</dependency> 

私は現在、このパッケージと同時に複数のメソッドを実行する方法を調査中です。 私の自家製の解決策の下で、誰かが事例を持っていると私に知らせることができます。

@Test
public final void runConcurrentMethod() throws InterruptedException {
    ExecutorService exec = Executors.newFixedThreadPool(16);
    for (int i = 0; i < 10000; i++) {
        exec.execute(new Runnable() {
             @Override
             public void run() {
                 concurrentMethod();
             }
        });
    }
    exec.shutdown();
    exec.awaitTermination(50, TimeUnit.SECONDS);
}

private void concurrentMethod() {
    //do and assert something
}

他の人が指摘しているように、並行性のバグが表示されるかどうかは決して確かではありませんが、例えば10個の同時実行性、つまり数十万回の実行では統計はあなたの側にあります。


Answer #7

HavaRunnerを試すこともできます。 デフォルトでは、テストは並行して実行されます。


Answer #8

IMUnitをチェックすることができます 。 これはJUnitと互換性があります。





junit