10

Java で作成したカスタム アノテーションに従って JUnit4 テストを実行したいと考えています。このカスタム アノテーションの目的は、マシンのプラットフォームがアノテーションで指定されたものと一致する場合にのみテストを実行する必要があることを JUnit4 が認識できるようにすることです。

次の注釈があるとします。

public @interface Annotations {
    String OS();
    ...
}

そして、次のテスト:

public class myTests{

    @BeforeClass
    public setUp() { ... }

    @Annotations(OS="mac")
    @Test
    public myTest1() { ... }

    @Annotations(OS="windows")
    @Test
    public myTest2() { ... }

    @Annotation(OS="unix")
    @Test
    public myTest3() { ... }

}

これらのテストを Mac マシンで実行する場合、 myTest1() のみを実行し、残りは無視する必要があります。しかし、私は現在、これをどのように実装するべきかについて行き詰まっています。JUnit にカスタム アノテーションを読み取らせ、テストを実行する必要があるかどうかを確認するにはどうすればよいですか。

4

5 に答える 5

14

カテゴリを使用するか、独自のカスタム JUnit ランナーを実装できます。デフォルトの JUnit ランナーの拡張は非常に簡単で、実行するテストのリストを任意の方法で定義できます。これには、特定の注釈を持つテスト メソッドのみを探すことが含まれます。以下にコード サンプルを含めます。これらを独自の実装の基礎として使用できます。

注釈:

@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomAnnotation {
   String OS();
}

カスタム ランナー クラス:

public class MyCustomTestRunner extends BlockJUnit4ClassRunner {

   public MyCustomTestRunner(final Class<?> klass) throws InitializationError {
      super(klass);
   }

   @Override
   protected List<FrameworkMethod> computeTestMethods() {
      // First, get the base list of tests
      final List<FrameworkMethod> allMethods = getTestClass()
            .getAnnotatedMethods(Test.class);
      if (allMethods == null || allMethods.size() == 0)
         return allMethods;

      // Filter the list down
      final List<FrameworkMethod> filteredMethods = new ArrayList<FrameworkMethod>(
            allMethods.size());
      for (final FrameworkMethod method : allMethods) {
         final MyCustomAnnotation customAnnotation = method
               .getAnnotation(MyCustomAnnotation.class);
         if (customAnnotation != null) {
            // Add to accepted test methods, if matching criteria met
            // For example `if(currentOs.equals(customAnnotation.OS()))`
            filteredMethods.add(method);
         } else {
            // If test method doesnt have the custom annotation, either add it to
            // the accepted methods, or not, depending on what the 'default' behavior
            // should be
            filteredMethods.add(method);
         }
      }

      return filteredMethods;
   }
}

サンプル テスト クラス:

@RunWith(MyCustomTestRunner.class)
public class MyCustomTest {
   public MyCustomTest() {
      super();
   }

   @Test
   @MyCustomAnnotation(OS = "Mac")
   public void testCustomViaAnnotation() {
      return;
   }
}
于 2012-11-27T18:29:39.590 に答える
6

まさにこの動作を持ち、レポートで認識のためにスキップされたテストとしてそれらを持っていることで私が見つけた最良の方法は、独自のランナーを使用することです(AlexRの回答のように)が、テストを選択できるようにするrunChildメソッドをオーバーライドしますが、無視し、完全に除外しません。

使用するアノテーション

@Retention(RetentionPolicy.RUNTIME)
public @interface TargetOS {
    String family();

    String name() default "";

    String arch() default "";

    String version() default "";
}

JUnit ランナー

public class OSSensitiveRunner extends BlockJUnit4ClassRunner {
    public OSSensitiveRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
        Description description = describeChild(method);
        if (method.getAnnotation(Ignore.class) != null) {
            notifier.fireTestIgnored(description);
        } else if (method.getAnnotation(TargetOS.class) != null) {
            final TargetOS tos = method.getAnnotation(TargetOS.class);
            String name = tos.name().equals("") ? null : tos.name();
            String arch = tos.arch().equals("") ? null : tos.arch();
            String version = tos.version().equals("") ? null : tos.version();
            if (OS.isOs(tos.family(), name, arch, version)) {
                runLeaf(methodBlock(method), description, notifier);
            } else {
                notifier.fireTestIgnored(description);
            }
        } else {
            runLeaf(methodBlock(method), description, notifier);
        }
    }
}

テストでの使用

@RunWith(OSSensitiveRunner.class)
public class SeleniumDownloadHelperTest {
...

特定のメソッドを制限する

@Test
@TargetOS(family = "windows")
public void testGetFileFromUrlInternetExplorer() throws Exception {
    ...
}
于 2014-06-14T15:35:30.227 に答える
2

これまでに見つけた最良のオプションは、JUnit Ruleを使用することです。 すぐに使用できるファイルを含むGitHub へのリンクがあります

于 2015-05-26T14:29:36.787 に答える