对 JUnit 测试进行分组

发布于 2024-07-18 06:25:30 字数 229 浏览 7 评论 0 原文

有没有办法在 JUnit 中对测试进行分组,以便我只能运行某些组?

或者是否可以注释一些测试然后全局禁用它们?

我正在使用 JUnit 4,我无法使用 TestNG。

编辑: @RunWith 和 @SuiteClasses 效果很好。 但是是否可以这样注释测试类中的一些测试? 或者我必须注释整个测试类吗?

Is there any way to group tests in JUnit, so that I can run only some groups?

Or is it possible to annotate some tests and then globally disable them?

I'm using JUnit 4, I can't use TestNG.

edit: @RunWith and @SuiteClasses works great. But is it possible to annotate like this only some tests in test class? Or do I have to annotate whole test class?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

川水往事 2024-07-25 06:25:30

JUnit 4.8 支持分组:

public interface SlowTests {}
public interface IntegrationTests extends SlowTests {}
public interface PerformanceTests extends SlowTests {}

然后...

public class AccountTest {

    @Test
    @Category(IntegrationTests.class)
    public void thisTestWillTakeSomeTime() {
        ...
    }

    @Test
    @Category(IntegrationTests.class)
    public void thisTestWillTakeEvenLonger() {
        ...
    }

    @Test
    public void thisOneIsRealFast() {
        ...
    }
}

最后,

@RunWith(Categories.class)
@ExcludeCategory(SlowTests.class)
@SuiteClasses( { AccountTest.class, ClientTest.class })
public class UnitTestSuite {}

取自此处:https://community.oracle.com/blogs/johnsmart/2010/04/25/grouping-tests-using-junit-categories-0

另外,Arquillian 本身支持分组:
https ://github.com/weld/core/blob/master/tests-arquillian/src/test/java/org/jboss/weld/tests/Categories.java

JUnit 4.8 supports grouping:

public interface SlowTests {}
public interface IntegrationTests extends SlowTests {}
public interface PerformanceTests extends SlowTests {}

And then...

public class AccountTest {

    @Test
    @Category(IntegrationTests.class)
    public void thisTestWillTakeSomeTime() {
        ...
    }

    @Test
    @Category(IntegrationTests.class)
    public void thisTestWillTakeEvenLonger() {
        ...
    }

    @Test
    public void thisOneIsRealFast() {
        ...
    }
}

And lastly,

@RunWith(Categories.class)
@ExcludeCategory(SlowTests.class)
@SuiteClasses( { AccountTest.class, ClientTest.class })
public class UnitTestSuite {}

Taken from here: https://community.oracle.com/blogs/johnsmart/2010/04/25/grouping-tests-using-junit-categories-0

Also, Arquillian itself supports grouping:
https://github.com/weld/core/blob/master/tests-arquillian/src/test/java/org/jboss/weld/tests/Categories.java

空城旧梦 2024-07-25 06:25:30

您想要将测试分组到测试类中还是想要将测试类分组? 我假设是后者。

这取决于您如何运行测试。 如果您通过 Maven 运行它们,则可以准确指定您想要包含哪些测试。 请参阅Maven Surefire 文档了解这一点。

不过,更一般地说,我所做的是有一棵测试套件树。 JUnit 4 中的测试套件看起来像这样:

 @RunWith(Suite.class)
 @SuiteClasses({SomeUnitTest1.class, SomeUnitTest2.class})
 public class UnitTestsSuite {
 }

所以,也许我有一个 FunctionTestsSuite 和一个 UnitTestsSuite,然后是一个包含其他两个的 AllTestsSuite。 如果您在 Eclipse 中运行它们,您将获得一个非常漂亮的分层视图。

这种方法的问题在于,如果您想以多种不同的方式对测试进行切片,那么它会有点乏味。 但这仍然是可能的(例如,您可以拥有一组基于模块进行切片的套件,然后根据测试类型进行另一组切片)。

Do you want to group tests inside a test class or do you want to group test classes? I am going to assume the latter.

It depends on how you are running your tests. If you run them by Maven, it is possible to specify exactly what tests you want to include. See the Maven surefire documentation for this.

More generally, though, what I do is that I have a tree of test suites. A test suite in JUnit 4 looks something like:

 @RunWith(Suite.class)
 @SuiteClasses({SomeUnitTest1.class, SomeUnitTest2.class})
 public class UnitTestsSuite {
 }

So, maybe I have a FunctionTestsSuite and a UnitTestsSuite, and then an AllTestsSuite which includes the other two. If you run them in Eclipse you get a very nice hierarchical view.

The problem with this approach is that it's kind of tedious if you want to slice tests in more than one different way. But it's still possible (you can for example have one set of suites that slice based on module, then another slicing on the type of test).

染火枫林 2024-07-25 06:25:30

为了处理全局禁用它们的问题,JUnit(4.5+)有两种方法,一种是使用新方法假设。 如果将其放在测试类的@BeforeClass(或@Before)中,并且如果条件失败,它将忽略该测试。 在这种情况下,您可以放置​​系统属性或其他可以全局设置打开或关闭的东西。

另一种选择是创建一个自定义运行程序,它了解全局属性并委托给适当的运行程序。 这种方法比较脆弱(因为 JUnit4 内部运行程序不稳定,并且可以在不同版本之间进行更改),但它的优点是能够沿着类层次结构继承并在子类中重写。 如果您必须支持遗留的 JUnit38 类,这也是唯一现实的方法。

这是一些执行自定义 Runner 的代码。 关于 getAppropriateRunnerForClass 可能执行的操作,我实现它的方式是使用一个单独的注释来告诉自定义运行程序要运行什么。 唯一的选择是从 JUnit 代码中复制粘贴一些非常脆弱的内容。

private class CustomRunner implements Runner
 private Runner runner;

    public CustomRunner(Class<?> klass, RunnerBuilder builder) throws Throwable {
        if (!isRunCustomTests()) {
            runner = new IgnoredClassRunner(klass);
        } else {
            runner = getAppropriateRunnerForClass(klass, builder);
    }

    public Description getDescription() {
        return runner.getDescription();
    }

    public void run(RunNotifier notifier) {
        runner.run(notifier);
    }
}

编辑: @RunWith 标签仅适用于整个类。 解决该限制的一种方法是将测试方法移动到静态内部类中并对其进行注释。 这样您就可以利用注释来组织类。 但是,这样做对任何 @Before 或 @BeforeClass 标记没有帮助,您必须在内部类中重新创建它们。 它可以调用外部类的方法,但它必须有自己的方法作为钩子。

To handle the globally disabling them, JUnit (4.5+) has two ways One is to use the new method assumeThat. If you put that in the @BeforeClass (or the @Before) of a test class, and if the condition fails, it will ignore the test. In the condition you can put a system property or something else that can be globally set on or off.

The other alternative is to create a custom runner which understands the global property and delegates to the appropriate runner. This approach is a lot more brittle (since the JUnit4 internal runners are unstable and can be changed from release to release), but it has the advantage of being able to be inherited down a class hierarchy and be overridden in a subclass. It is also the only realistic way to do this if you have to support legacy JUnit38 classes.

Here is some code to do the custom Runner. Regarding what getAppropriateRunnerForClass might do, the way I implemented it was to have a separate annotation that tells the custom runner what to run with. The only alternative was some very brittle copy paste from the JUnit code.

private class CustomRunner implements Runner
 private Runner runner;

    public CustomRunner(Class<?> klass, RunnerBuilder builder) throws Throwable {
        if (!isRunCustomTests()) {
            runner = new IgnoredClassRunner(klass);
        } else {
            runner = getAppropriateRunnerForClass(klass, builder);
    }

    public Description getDescription() {
        return runner.getDescription();
    }

    public void run(RunNotifier notifier) {
        runner.run(notifier);
    }
}

EDIT: The @RunWith tag only works for a whole class. One way to work around that limiation is to move the test methods into a static inner class and annotate that. That way you have the advantage of the annotation with the organization of the class. But, doing that won't help with any @Before or @BeforeClass tags, you will have to recreate those in the inner class. It can call the outer class's method, but it would have to have its own method as a hook.

心如狂蝶 2024-07-25 06:25:30

在 JUnit 5 中,您可以在类或方法级别声明 @Tag 来过滤测试; 类似于 TestNG 中的测试组或 JUnit 4 中的类别

来自 javadoc

标签用于过滤给定测试执行哪些测试
计划。 例如,开发团队可能会使用以下值来标记测试
如“快”、“慢”、“ci-server”等,然后提供标签列表
用于当前的测试计划,可能取决于
当前环境。

例如,您可以声明一个带有 "slow" @Tag 的测试类,该测试类将为所有方法继承,并在需要时为某些方法覆盖它:

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

@Tag("slow") 
public class FooTest{

   // 
   @Test
   void loadManyThings(){ 
        ...
   }

   @Test
   void loadManyManyThings(){ 
        ...
   }


   @Test
   @Tag("fast")
   void loadFewThings(){ 
        ...
   }

}

您可以应用相同的方法其他测试类的逻辑。
这样测试类(以及方法)就属于特定的标签。

作为一种好的做法,您可以创建自定义组合注释,而不是在整个测试类中复制和粘贴 @Tag("fast")@Tag("slow")
例如:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.junit.jupiter.api.Tag;

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Tag("slow")
public @interface Slow {
}

并将其用作:

@Test
@Slow
void slowProcessing(){ 
    ...
}   

要在文本执行期间启用或禁用用特定标记标记的测试,您可以依赖 maven-surefire-plugin 文档

要包含标签或标签表达式,请使用

要排除标签或标签表达式,请使用excludedGroups

只需根据您的要求在 pom.xml 中配置插件(文档示例):

 <build>
     <plugins>
         ...
         <plugin>
             <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-surefire-plugin</artifactId>
             <version>2.22.0</version>
             <configuration>
                 <groups>acceptance | !feature-a</groups>
                 <excludedGroups>integration, regression</excludedGroups>
             </configuration>
         </plugin>
     </plugins> 
</build> 

有关信息 测试目标文档未更新。

In JUnit 5 you can declare @Tag for filtering tests, either at the class or method level; analogous to test groups in TestNG or Categories in JUnit 4

From the javadoc :

tags are used to filter which tests are executed for a given test
plan. For example, a development team may tag tests with values such
as "fast", "slow", "ci-server", etc. and then supply a list of tags to
be used for the current test plan, potentially dependent on the
current environment.

For example you could declare a test class with a "slow" @Tag that will be inherited for all methods and override it for some methods if required :

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

@Tag("slow") 
public class FooTest{

   // 
   @Test
   void loadManyThings(){ 
        ...
   }

   @Test
   void loadManyManyThings(){ 
        ...
   }


   @Test
   @Tag("fast")
   void loadFewThings(){ 
        ...
   }

}

You could apply the same logic for other test classes.
In this way test classes (and methods too) belongs to a specific tag.

As a good practice instead of copying and pasting @Tag("fast") and @Tag("slow") throughout the test classes, you can create custom composed annotations.
For example :

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.junit.jupiter.api.Tag;

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Tag("slow")
public @interface Slow {
}

and use it as :

@Test
@Slow
void slowProcessing(){ 
    ...
}   

To enable or disable test marked with a specific tag during the text execution you can rely on the maven-surefire-plugin documentation :

To include tags or tag expressions, use groups.

To exclude tags or tag expressions, use either excludedGroups.

Just configure in your pom.xml the plugin according to your requirement (example of the doc) :

 <build>
     <plugins>
         ...
         <plugin>
             <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-surefire-plugin</artifactId>
             <version>2.22.0</version>
             <configuration>
                 <groups>acceptance | !feature-a</groups>
                 <excludedGroups>integration, regression</excludedGroups>
             </configuration>
         </plugin>
     </plugins> 
</build> 

For information the test goal documentation is not updated.

单身情人 2024-07-25 06:25:30

尝试 JUnit 测试组。 从文档:

@TestGroup("integration")
public class MyIntegrationTest {
   @ClassRule
   public static TestGroupRule rule = new TestGroupRule();

   ...
}
  • 执行一个简单的测试组:-Dtestgroup=integration
  • 执行多个测试组:-Dtestgroup=group1,group2
  • 执行所有测试组:-Dtestgroup=all

Try JUnit Test Groups. From documentation :

@TestGroup("integration")
public class MyIntegrationTest {
   @ClassRule
   public static TestGroupRule rule = new TestGroupRule();

   ...
}
  • Execute a simple test group: -Dtestgroup=integration
  • Execute multiple test groups: -Dtestgroup=group1,group2
  • Execute all test groups: -Dtestgroup=all
童话 2024-07-25 06:25:30

您可以创建包含测试组的测试 Suite 对象。 或者,您的 IDE(如 Eclipse)可能支持运行给定包中包含的所有测试。

You can create test Suite objects that contain groups of tests. Alternatively, your IDE (like Eclipse) may have support for running all the tests contained in a given package.

江挽川 2024-07-25 06:25:30

您可以使用测试套件(http://qaautomated .blogspot.in/2016/09/junit-test-suits-and-test-execution.html)或者你可以Junit类别(http://qaautomated.blogspot.in/2016/09/junit-categories.html)用于有效地对测试用例进行分组。

You can Use Test Suite(http://qaautomated.blogspot.in/2016/09/junit-test-suits-and-test-execution.html) or you can Junit Categories(http://qaautomated.blogspot.in/2016/09/junit-categories.html) for grouping your test cases effectively.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文