Java JUnit4.x中套件执行挂钩的前后
我正在尝试为一组集成测试执行设置和拆卸,使用JUnit4.4执行测试。拆卸需要可靠地运行。我在TestNG方面还有其他问题,所以我想把它移植回jUnit。在任何测试运行之前和所有测试完成之后,有哪些钩子可供执行Java JUnit4.x中套件执行挂钩的前后,java,testing,junit,integration-testing,Java,Testing,Junit,Integration Testing,我正在尝试为一组集成测试执行设置和拆卸,使用JUnit4.4执行测试。拆卸需要可靠地运行。我在TestNG方面还有其他问题,所以我想把它移植回jUnit。在任何测试运行之前和所有测试完成之后,有哪些钩子可供执行 注意:我们正在使用maven 2进行构建。我尝试过使用maven的pre-和post integration test阶段,但是,如果测试失败,maven会停止并不运行post integration test,这没有任何帮助。据我所知,在JUnit中没有这样做的机制,但是您可以尝试对套
注意:我们正在使用maven 2进行构建。我尝试过使用maven的
pre-
和post integration test
阶段,但是,如果测试失败,maven会停止并不运行post integration test
,这没有任何帮助。据我所知,在JUnit中没有这样做的机制,但是您可以尝试对套件进行子类化并重写run()方法的版本提供挂钩。使用注释,可以执行以下操作:
import org.junit.*;
import static org.junit.Assert.*;
import java.util.*;
class SomethingUnitTest {
@BeforeClass
public static void runBeforeClass()
{
}
@AfterClass
public static void runAfterClass()
{
}
@Before
public void setUp()
{
}
@After
public void tearDown()
{
}
@Test
public void testSomethingOrOther()
{
}
}
我认为获得您想要的功能的唯一方法是
import junit.framework.Test;
import junit.framework.TestResult;
import junit.framework.TestSuite;
public class AllTests {
public static Test suite() {
TestSuite suite = new TestSuite("TestEverything");
//$JUnit-BEGIN$
suite.addTestSuite(TestOne.class);
suite.addTestSuite(TestTwo.class);
suite.addTestSuite(TestThree.class);
//$JUnit-END$
}
public static void main(String[] args)
{
AllTests test = new AllTests();
Test testCase = test.suite();
TestResult result = new TestResult();
setUp();
testCase.run(result);
tearDown();
}
public void setUp() {}
public void tearDown() {}
}
我在eclipse中使用了类似的东西,所以我不确定它在该环境之外的可移植性如何是的,在测试套件中的任何测试之前和之后都可以可靠地运行设置和拆除方法。让我用代码演示一下:
package com.test;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({Test1.class, Test2.class})
public class TestSuite {
@BeforeClass
public static void setUp() {
System.out.println("setting up");
}
@AfterClass
public static void tearDown() {
System.out.println("tearing down");
}
}
因此,您的Test1
类看起来像:
package com.test;
import org.junit.Test;
public class Test1 {
@Test
public void test1() {
System.out.println("test1");
}
}
…您可以想象,Test2
看起来很相似。如果运行TestSuite
,您将得到:
setting up
test1
test2
tearing down
因此,您可以看到设置/拆除仅在所有测试之前和之后分别运行
问题:只有在运行测试套件,而不是作为单独的JUnit测试运行Test1和Test2时,这才有效。您提到您正在使用maven,maven surefire插件喜欢单独运行测试,而不是作为套件的一部分。在这种情况下,我建议创建每个测试类扩展的超类。然后,超类包含带注释的@BeforeClass和@AfterClass方法。虽然没有上述方法那么干净,但我认为它对你有用
至于失败测试的问题,您可以设置maven.test.error.ignore,以便在失败测试上继续构建。这不建议作为一个持续的实践,但它应该让您的功能,直到您的所有测试通过。有关更多详细信息,请参阅。此处,我们
- 升级到JUnit4.5
- 编写注释来标记每个需要工作服务的测试类或方法
- 为每个注释编写处理程序,其中包含实现服务设置和拆卸的静态方法
- 扩展了常用的运行程序以定位测试上的注释,在适当的点将静态处理程序方法添加到测试执行链中
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<configuration>
<includes>
<include>**/*Suite.java</include>
</includes>
<excludes>
<exclude>**/*Test.java</exclude>
<exclude>**/*Tests.java</exclude>
</excludes>
</configuration>
</plugin>
org.apache.maven.plugins
maven surefire插件
2.5
**/*Suite.java
**/*Test.java
**/*Tests.java
至于“注意:我们正在使用maven 2进行构建。我已经尝试使用maven的集成前和集成后测试阶段,但是,如果测试失败,maven会停止并不运行集成后测试,这没有帮助。”
您可以尝试使用故障保护插件,我认为它具有确保无论设置或中间阶段状态如何进行清理的功能如果您的所有测试都可以扩展一个“技术”类并在同一个包中,您可以做一些小技巧:
public class AbstractTest {
private static int nbTests = listClassesIn(<package>).size();
private static int curTest = 0;
@BeforeClass
public static void incCurTest() { curTest++; }
@AfterClass
public static void closeTestSuite() {
if (curTest == nbTests) { /*cleaning*/ }
}
}
public class Test1 extends AbstractTest {
@Test
public void check() {}
}
public class Test2 extends AbstractTest {
@Test
public void check() {}
}
公共类抽象测试{
私有静态int nbTests=listClassesIn().size();
私有静态int-curTest=0;
@课前
public static void incCurTest(){curTest++;}
@下课
公共静态void closeTestSuite(){
如果(curTest==nbTests){/*清洁*/}
}
}
公共类Test1扩展了AbstractTest{
@试验
公共无效检查(){}
}
公共类Test2扩展了AbstractTest{
@试验
公共无效检查(){}
}
请注意,此解决方案有很多缺点:
- 必须执行包的所有测试
- 必须子类化“techincal”类
- 不能在子类内使用@BeforeClass和@AfterClass
- 如果在包中只执行一个测试,则不会进行清理
有关信息:listClassesIn()=>您可以使用as。我的一位同事建议如下:您可以使用自定义RunListener并实现testRunFinished()方法: 要注册RunListener,只需按如下方式配置surefire插件: “使用自定义侦听器和报告器”部分 故障保护插件也应选择此配置。
这个解决方案很好,因为您不必指定套件、查找测试类或任何这些东西-它让Maven发挥了它的魔力,等待所有测试完成。如果您不想创建套件并且必须列出所有测试类,您可以使用反射动态查找测试类的数量,并在基类@AfterClass中倒计时,以便只执行一次拆卸:
public class BaseTestClass
{
private static int testClassToRun = 0;
// Counting the classes to run so that we can do the tear down only once
static {
try {
Field field = ClassLoader.class.getDeclaredField("classes");
field.setAccessible(true);
@SuppressWarnings({ "unchecked", "rawtypes" })
Vector<Class> classes = (Vector<Class>) field.get(BlockJUnit4ClassRunner.class.getClassLoader());
for (Class<?> clazz : classes) {
if (clazz.getName().endsWith("Test")) {
testClassToRun++;
}
}
} catch (Exception ignore) {
}
}
// Setup that needs to be done only once
static {
// one time set up
}
@AfterClass
public static void baseTearDown() throws Exception
{
if (--testClassToRun == 0) {
// one time clean up
}
}
}
公共类BaseTestClass
{
私有静态int testClassToRun=0;
//计算要运行的类,以便我们只进行一次拆卸
静止的{
试一试{
Field Field=ClassLoader.class.getDeclaredField(“类”);
字段。setAccessible(true);
@SuppressWarnings({“unchecked”,“rawtypes”})
Vector classes=(Vector)field.get(BlockJUnit4ClassRunner.class.getClassLoader());
对于(班级:班级){
if(clazz.getName().endsWith(“测试”)){
testClassToRun++;
}
}
}捕获(异常忽略){
}
}