web-dev-qa-db-ja.com

JUnit:統合テストと単体テストの分割

私は多くのJunitテストを継承しましたが、これらのテスト(ほとんどの場合は機能していません)は、実際のユニットテストと統合テスト(外部システム、dbなどが必要)が混在しています。

それで、私はそれらを実際に分離する方法を考えようとしています。それでユニットテストをニースで素早く実行し、その後統合テストを実行できます。

オプションは..

  1. それらを別々のディレクトリに分割します。

  2. (v3から)Junit4に移動し、クラスに注釈を付けてそれらを分離します。

  3. ファイルの命名規則を使用して、クラス(AdapterATestおよびAdapterAIntergrationTest)が何であるかを伝えます。

3には、Eclipseに「選択したプロジェクト/パッケージまたはフォルダーですべてのテストを実行する」オプションがあるという問題があります。したがって、統合テストを実行するだけでは非常に困難になります。

2:開発者が単体テストクラスで統合テストの作成を開始するリスクがあり、面倒になります。

1:最も近い解決策のように思えますが、私の腸は、より良い解決策があるはずだと言います。

それが私の質問です、統合テストと適切な単体テストをどのように分解するのですか?

122
jeff porter

私は現在、組織のポリシー(およびJunit 3のレガシー)のために個別のディレクトリを使用していますが、私は自分でアノテーションに移行したいと考えています。

開発者がユニットテストクラスに統合テストを配置することについて、あまり心配する必要はありません。必要に応じてコーディング標準にルールを追加してください。

注釈や物理的にクラスを分離する以外に、他にどのようなソリューションがあるのか​​を知りたいと思っています。

10

JUnitカテゴリとMavenを使用して、非常に簡単に分割できます。

これは、ユニットテストと統合テストによって、以下に非常に簡単に示されています。

マーカーインターフェイスの定義

このインターフェイスは、統合テストとして実行するすべてのテストをマークするために使用されます。

_public interface IntegrationTest {}
_

テストクラスにマークを付けます

テストクラスの上部にカテゴリアノテーションを追加します。新しいインターフェースの名前を取ります。

_import org.junit.experimental.categories.Category;
@Category(IntegrationTest.class)
public class ExampleIntegrationTest{
  @Test
  public void longRunningServiceTest() throws Exception {
  }
}
_

Mavenユニットテストの構成

統合テストを無視するように、maven surefireプラグインに設定を追加するだけです。

_<plugin>
  <groupId>org.Apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.11</version>
  <dependencies>
   <dependency>
     <groupId>org.Apache.maven.surefire</groupId>
     <artifactId>surefire-junit47</artifactId>
     <version>2.12</version>
   </dependency>
  </dependencies>
  <configuration>
    <includes>
      <include>**/*.class</include>
    </includes>
    <excludedGroups>com.test.annotation.type.IntegrationTest</excludedGroups>
  </configuration>
</plugin>
_

Mvn cleanテストを実行すると、マークされていない単体テストのみが実行されます。

Maven統合テストの構成

統合テストのみを実行するには、これを使用します:

_<plugin>
  <groupId>org.Apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.11</version>
  <dependencies>
   <dependency>
     <groupId>org.Apache.maven.surefire</groupId>
     <artifactId>surefire-junit47</artifactId>
     <version>2.12</version>
   </dependency>
  </dependencies>
  <configuration>
    <groups>com.test.annotation.type.IntegrationTest</groups>
  </configuration>
</plugin>
_

これをID ITのプロファイルでラップすると、_mvn clean install_を使用して高速テストのみを実行できます。統合/低速テストのみを実行するには、_mvn clean install -P IT_を使用します。

しかし、ほとんどの場合、デフォルトで高速テストを実行し、allテストを_-P IT_で実行します。その場合は、トリックを使用する必要があります。

_<profiles>
    <profile>
        <id>IT</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.Apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                        <excludedGroups>Java.io.Serializable</excludedGroups> <!-- An empty element doesn't overwrite, so I'm using an interface here which no one will ever use -->
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>
_

ご覧のとおり、_Java.io.Serializable_アノテーションが付けられたテストは除外しています。これは、プロファイルがSurefireプラグインのデフォルト構成を継承するため必要です。したがって、_<excludedGroups/>_または_<excludedGroups></excludedGroups>_と言っても、値_com.test.annotation.type.IntegrationTest_が使用されます。

また、noneはクラスパス上のインターフェイスである必要があるため使用できません(Mavenはこれをチェックします)。

ノート:

  • _surefire-junit47_への依存性は、MavenがJUnit 4ランナーに自動的に切り替わらない場合にのみ必要です。 groupsまたはexcludedGroups要素を使用すると、スイッチがトリガーされます。 こちらを参照
  • 上記のコードのほとんどは、Maven Failsafeプラグインのドキュメントから取られました。 「JUnitカテゴリの使用」セクションを参照してください このページ
  • テスト中に、@RunWith()注釈を使用してスイートまたはSpringベースのテストを実行する場合でも、これが機能することがわかりました。
139
John Dobie

Maven Surefireプラグインを使用して単体テストを実行し、Maven Failsafeプラグインを使用して統合テストを実行します。単体テストは**/Test*.Java **/*Test.Java **/*TestCase.Java命名規則、統合テスト-**/IT*.Java **/*IT.Java **/*ITCase.Java。したがって、実際にはオプション3です。

いくつかのプロジェクトでは、TestNGを使用し、統合/単体テスト用に異なるテストグループを定義していますが、これはおそらくあなたには適していません。

38
lexicore

私はそれを持っているだけのためにJunit4に移動します:)

それらを異なるテストスイートに分けることができます。 Junit3でそれらがどのように構成されているかはわかりませんが、テストスイートを構築し、それらの1つにすべての実際のユニットテストを配置し、統合テストに2番目のスイートを使用するだけでJunit4で簡単にできるはずです。

次に、Eclipseで両方のスイートの実行構成を定義すると、単一のスイートを簡単に実行できます。これらのスイートは自動化されたプロセスから起動することもできます。ソースが変更されるたびに単体テストを実行し、統合テスト(非常に大きい場合)を1日1回または1時間に1回のみ実行できます。

12
Janusz

IfProfileValue spring注釈を使用すると、Mavenプラグインまたは構成が必要なく、これを実現できますwithout

IfProfileValueを使用して統合テストクラスまたはメソッドに注釈を付けます

import org.springframework.test.annotation.IfProfileValue;

@IfProfileValue(name="test-groups", value="integration")
public class ExampleIntegrationTest{
    @Test
    public void longRunningServiceTest() throws Exception {
    }
} 

単体テストのみを使用して実行するには:

mvn clean test

統合テストと単体テストを使用して実行するには:

mvn clean test -Dtest-groups=integration

また、IDE内の「すべてのテストを実行」は、単体テストのみを実行します。追加-Dtest-groups=integration to VM統合と単体テストの両方を実行する引数。

8
Mit Mehta

正しい答えはありません。あなたが説明したように、それを実行するいくつかの方法があります。私は、ファイルの命名スキームと、異なるディレクトリへの分割の両方を行いました。

別のディレクトリに物事を分割することはあなたにとってより良いかもしれないように聞こえます、そしてそれは私には少しはっきりしているように思えるので、私はそれに傾いたでしょう。

それは私にとってよりきめ細かいと思われるので、私は注釈をしようとは思わない。これら2種類のテストを同じファイルに混在させたいですか?しません.

6
ndp