JUnit 4.4를 사용하여 테스트를 실행하는 일련의 통합 테스트를 위해 설정 및 분해를 수행하려고합니다. 분해는 안정적으로 실행되어야합니다. TestNG에 다른 문제가 있으므로 jUnit으로 다시 포팅하려고합니다. 테스트가 실행되기 전과 모든 테스트가 완료된 후 어떤 후크를 실행할 수 있습니까?
참고 : 우리는 빌드에 maven 2를 사용하고 있습니다. maven 's pre-
& post-integration-test
단계이지만 테스트에 실패하면 maven이 중지되고 post-integration-test
, 도움이되지 않습니다.
예, 테스트 스위트에서 테스트 전후에 설정 및 해제 방법을 안정적으로 실행할 수 있습니다. 코드로 보여 드리겠습니다.
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 을 참조하십시오.
내 동료가 다음을 제안했습니다. 사용자 정의 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은 모든 테스트가 완료 될 때까지 기다릴 수 있습니다.
JUnit 4.9+에서 @ ClassRule 어노테이션을 사용할 수 있습니다다른 질문에 대한 답변에서 설명합니다 .
주석을 사용하면 다음과 같이 할 수 있습니다.
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()
{
}
}
여기, 우리
모든 테스트가 "기술"클래스를 확장 할 수 있고 동일한 패키지에있는 경우 약간의 트릭을 수행 할 수 있습니다.
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() {}
}
이 솔루션에는 많은 단점이 있습니다.
정보 : listClassesIn () => Java에서 주어진 클래스의 모든 서브 클래스를 어떻게 찾습니까?
"참고 : 빌드에 maven 2를 사용하고 있습니다. maven의 사전 및 사후 통합 테스트 단계를 사용해 보았지만 테스트가 실패하면 maven이 중지되고 사후 통합 테스트를 실행하지 않습니다. 도움이되지 않습니다. "
대신 failsafe-plugin을 사용해 볼 수 있습니다. 설정 또는 중간 단계 상태에 관계없이 정리가 수행되도록하는 기능이 있다고 생각합니다.
스위트를 작성하지 않고 모든 테스트 클래스를 나열해야하는 경우 리플렉션을 사용하여 테스트 클래스 수를 동적으로 찾고 기본 클래스 @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 대답이 원하는 것을 수행 할 수 있습니다.
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>
내가 원하는 기능을 얻는 유일한 방법은 다음과 같은 일을하는 것입니다.
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에서 이와 같은 것을 사용하므로 해당 환경 외부에서 얼마나 이식성이 있는지 잘 모르겠습니다.
내가 아는 한 JUnit에는이 작업을 수행하는 메커니즘이 없지만 Suite 하위 클래스를 작성하고 후크를 제공하는 버전으로 run () 메서드를 재정의 할 수 있습니다.