it-swarm-ko.tech

jUnit 4.x의 스위트 전후 스위트 실행 후크

JUnit 4.4를 사용하여 테스트를 실행하는 일련의 통합 테스트를 위해 설정 및 분해를 수행하려고합니다. 분해는 안정적으로 실행되어야합니다. TestNG에 다른 문제가 있으므로 jUnit으로 다시 포팅하려고합니다. 테스트가 실행되기 전과 모든 테스트가 완료된 후 어떤 후크를 실행할 수 있습니까?

참고 : 우리는 빌드에 maven 2를 사용하고 있습니다. maven 's pre- & post-integration-test 단계이지만 테스트에 실패하면 maven이 중지되고 post-integration-test, 도움이되지 않습니다.

81
sblundy

예, 테스트 스위트에서 테스트 전후에 설정 및 해제 방법을 안정적으로 실행할 수 있습니다. 코드로 보여 드리겠습니다.

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를 설정하여 빌드가 실패한 테스트에서 계속되도록 할 수 있습니다. 이것은 지속적인 연습으로 권장되지는 않지만 모든 테스트가 통과 될 때까지 작동하도록해야합니다. 자세한 내용은 maven surefire documentation 을 참조하십시오.

111
Julie

내 동료가 다음을 제안했습니다. 사용자 정의 RunListener를 사용하고 testRunFinished () 메소드를 구현할 수 있습니다. http://junit.sourceforge.net/javadoc/org/junit/runner/notification/RunListener.html# testRunFinished (org.junit.runner.Result)

RunListener를 등록하려면 다음과 같이 surefire 플러그인을 구성하십시오. http://maven.Apache.org/surefire/maven-surefire-plugin/examples/junit.html 섹션 "사용자 정의 리스너 및 리포터 사용"

이 구성은 failsafe 플러그인에서도 선택해야합니다. 이 솔루션은 스위트, 검색 테스트 클래스 또는이 항목을 지정할 필요가 없기 때문에 훌륭합니다. Maven은 모든 테스트가 완료 될 때까지 기다릴 수 있습니다.

32
Martin Vysny
11
Tobogganski

주석을 사용하면 다음과 같이 할 수 있습니다.

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()
    {

    }

}
7
Jroc

여기, 우리

  • jUnit 4.5로 업그레이드
  • 작동하는 서비스가 필요한 각 테스트 클래스 또는 메소드에 태그를 달기 위해 주석을 작성했습니다.
  • 서비스 설정 및 해제를 구현하는 정적 메소드를 포함하는 각 주석에 대한 핸들러를 작성했습니다.
  • 정적 Runner 메소드를 테스트 실행 체인에 적절한 시점에 추가하여 테스트에서 주석을 찾도록 일반적인 Runner를 확장했습니다.
3
carym

모든 테스트가 "기술"클래스를 확장 할 수 있고 동일한 패키지에있는 경우 약간의 트릭을 수행 할 수 있습니다.

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() {}
}

이 솔루션에는 많은 단점이 있습니다.

  • 패키지의 모든 테스트를 실행해야합니다
  • "techincal"클래스를 서브 클래 싱해야합니다.
  • 서브 클래스 내에서 @BeforeClass 및 @AfterClass를 사용할 수 없습니다
  • 패키지에서 하나의 테스트 만 실행하면 청소가 수행되지 않습니다
  • ...

정보 : listClassesIn () => Java에서 주어진 클래스의 모든 서브 클래스를 어떻게 찾습니까?

2
christophe blin

"참고 : 빌드에 maven 2를 사용하고 있습니다. maven의 사전 및 사후 통합 테스트 단계를 사용해 보았지만 테스트가 실패하면 maven이 중지되고 사후 통합 테스트를 실행하지 않습니다. 도움이되지 않습니다. "

대신 failsafe-plugin을 사용해 볼 수 있습니다. 설정 또는 중간 단계 상태에 관계없이 정리가 수행되도록하는 기능이 있다고 생각합니다.

2
Binod Pant

스위트를 작성하지 않고 모든 테스트 클래스를 나열해야하는 경우 리플렉션을 사용하여 테스트 클래스 수를 동적으로 찾고 기본 클래스 @AfterClass에서 카운트 다운하여 tearDown을 한 번만 수행 할 수 있습니다.

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
        }
    }
}

정적 블록 대신 @BeforeClass를 사용하려는 경우 부울 플래그를 사용하여 첫 번째 호출에서 한 번만 반사 횟수 및 테스트 설정을 수행 할 수 있습니다. 이것이 누군가를 돕기를 바랍니다. 스위트의 모든 클래스를 열거하는 것보다 더 나은 방법을 알아내는 데 오후가 걸렸습니다.

이제 모든 테스트 클래스에 대해이 클래스를 확장하기 만하면됩니다. 우리는 이미 모든 테스트에 공통적 인 것들을 제공하는 기본 클래스를 가지고 있었으므로 이것이 우리에게 최고의 솔루션이었습니다.

영감은 다음과 같습니다. SO answer https://stackoverflow.com/a/37488620/5930242

이 클래스를 어디에서나 확장하지 않으려면 마지막 SO 대답이 원하는 것을 수행 할 수 있습니다.

0
FredBoutin

Maven-surefire-plugin은 Suite 클래스를 먼저 실행하지 않지만 스위트 및 테스트 클래스는 동일하게 취급하므로 스위트 클래스 만 활성화하고 모든 테스트를 비활성화하도록 플러그인을 아래와 같이 구성 할 수 있습니다. Suite는 모든 테스트를 실행합니다.

        <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>
0
Anurag Sharma

내가 원하는 기능을 얻는 유일한 방법은 다음과 같은 일을하는 것입니다.

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에서 이와 같은 것을 사용하므로 해당 환경 외부에서 얼마나 이식성이 있는지 잘 모르겠습니다.

0
Jroc

내가 아는 한 JUnit에는이 작업을 수행하는 메커니즘이 없지만 Suite 하위 클래스를 작성하고 후크를 제공하는 버전으로 run () 메서드를 재정의 할 수 있습니다.

0
user15299