Jak*_*old 41 java junit unit-testing
有没有办法在JUnit中对测试进行分组,以便我只能运行一些组?
或者是否可以注释一些测试,然后全局禁用它们?
我正在使用JUnit 4,我不能使用TestNG.
编辑: @RunWith和@SuiteClasses很棒.但是,是否可以在测试类中仅注释一些测试?或者我是否必须注释整个测试类?
Ond*_*žka 74
JUnit 4.8支持分组:
public interface SlowTests {}
public interface IntegrationTests extends SlowTests {}
public interface PerformanceTests extends SlowTests {}
Run Code Online (Sandbox Code Playgroud)
然后...
public class AccountTest {
@Test
@Category(IntegrationTests.class)
public void thisTestWillTakeSomeTime() {
...
}
@Test
@Category(IntegrationTests.class)
public void thisTestWillTakeEvenLonger() {
...
}
@Test
public void thisOneIsRealFast() {
...
}
}
Run Code Online (Sandbox Code Playgroud)
最后,
@RunWith(Categories.class)
@ExcludeCategory(SlowTests.class)
@SuiteClasses( { AccountTest.class, ClientTest.class })
public class UnitTestSuite {}
Run Code Online (Sandbox Code Playgroud)
摘自:http://weblogs.java.net/blog/johnsmart/archive/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
Yis*_*hai 10
为了处理全局禁用它们,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);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:@RunWith标签仅适用于整个班级.解决该限制的一种方法是将测试方法移动到静态内部类并注释它.这样,您就可以通过类的组织来进行注释.但是,这样做对任何@Before或@BeforeClass标记都无济于事,您将不得不在内部类中重新创建它们.它可以调用外部类的方法,但它必须有自己的方法作为钩子.
您想在测试类中对测试进行分组,还是要对测试类进行分组?我将假设后者.
这取决于您如何运行测试.如果您通过Maven运行它们,则可以准确指定要包含的测试.有关此信息,请参阅Maven surefire文档.
但更一般地说,我所做的是我有一组测试套件.JUnit 4中的测试套件类似于:
@RunWith(Suite.class)
@SuiteClasses({SomeUnitTest1.class, SomeUnitTest2.class})
public class UnitTestsSuite {
}
Run Code Online (Sandbox Code Playgroud)
所以,也许我有一个FunctionTestsSuite和一个UnitTestsSuite,然后是一个包含另外两个的AllTestsSuite.如果您在Eclipse中运行它们,您将获得一个非常好的分层视图.
这种方法的问题在于,如果你想以多种不同的方式对测试进行切片,那就太乏味了.但它仍然可能(例如,您可以根据模块切换一组套件,然后根据测试类型进行另一次切片).
在 JUnit 5 中,您可以@Tag在类或方法级别声明过滤测试;类似于 TestNG 中的测试组或 JUnit 4 中的类别
来自javadoc:
标签用于过滤针对给定测试计划执行哪些测试。例如,开发团队可以使用“快”、“慢”、“ci-server”等值来标记测试,然后提供用于当前测试计划的标签列表,这可能取决于当前的测试计划环境。
例如,您可以声明一个带有 a 的测试类,"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(){
...
}
}
Run Code Online (Sandbox Code Playgroud)
您可以将相同的逻辑应用于其他测试类。
这样测试类(以及方法)就属于特定的标签。
作为一种好的做法,您可以创建自定义组合注释@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 {
}
Run Code Online (Sandbox Code Playgroud)
并将其用作:
@Test
@Slow
void slowProcessing(){
...
}
Run Code Online (Sandbox Code Playgroud)
要在文本执行期间启用或禁用标有特定标签的测试,您可以依赖maven-surefire-plugin 文档 :
要包含标签或标签表达式,请使用
groups.要排除标签或标签表达式,请使用
excludedGroups.
只需根据您的要求在 pom.xml 中配置插件(文档示例):
@Test
@Slow
void slowProcessing(){
...
}
Run Code Online (Sandbox Code Playgroud)
有关信息,测试目标文档未更新。