Java 分组 JUnit 测试

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/817135/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 19:48:39  来源:igfitidea点击:

Grouping JUnit tests

javaunit-testingjunit

提问by Jakub Arnold

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

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

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

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

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

我正在使用JUnit 4,我不能使用 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?

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

采纳答案by waxwing

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 documentationfor this.

这取决于您如何运行测试。如果您通过 Maven 运行它们,则可以准确指定要包含的测试。请参阅Maven surefire 文档

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

不过,更一般地说,我所做的是我有一个测试套件树。JUnit 4 中的测试套件如下所示:

 @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.

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

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).

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

回答by Kevin

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

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

回答by Yishai

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.

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

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.

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

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.

这是一些用于执行自定义 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);
    }
}

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.

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

回答by Ondra ?i?ka

JUnit 4.8 supports grouping:

JUnit 4.8 支持分组:

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

取自此处: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

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

回答by Bit-Man

Try JUnit Test Groups. From documentation :

试试JUnit 测试组。从文档:

@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
  • 执行一个简单的测试组:-Dtestgroup=integration
  • 执行多个测试组:-Dtestgroup=group1,group2
  • 执行所有测试组:-Dtestgroup=all

回答by anuja jain

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.

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

回答by davidxxx

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

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

From the javadoc:

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.

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

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

例如,您可以声明一个测试类,该类"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(){ 
        ...
   }

}

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 :

作为一个很好的做法,而不是复制和粘贴@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 {
}

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:

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

To include tags or tag expressions, use groups.

To exclude tags or tag expressions, use either excludedGroups.

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

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

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

只需根据您的要求(文档示例)在 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> 

For information the test goal documentationis not updated.

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