JUnit4에서 특정 순서로 테스트 메소드를 실행하는 방법은 무엇입니까?
@Test
특정 순서 로 주석이 달린 테스트 방법을 실행하고 싶습니다 .
예를 들면 다음과 같습니다.
public class MyTest {
@Test public void test1(){}
@Test public void test2(){}
}
나는 실행할 수 있도록하려는 test1()
전에 test2()
내가 실행할 때마다 MyTest
,하지만 난 같은 주석을 찾을 수 없습니다 @Test(order=xx)
.
JUnit의 작성자가 주문 기능을 원하지 않는다면 왜 JUnit에 대해 매우 중요한 기능이라고 생각 합니까?
JUnit 작성자가 주문 기능을 원하지 않으면 JUnit에 대해 매우 중요한 기능이라고 생각합니다. 왜 그렇습니까?
JUnit을 사용 하여이 작업을 수행하는 명확한 방법이 있는지 확실하지 않습니다 .JUnit은 모든 테스트를 임의의 순서로 수행 할 수 있다고 가정합니다. FAQ에서 :
테스트 픽스처는 어떻게 사용합니까?
(...) 테스트 메소드 호출의 순서가 보장되지 않으므로 testOneItemCollection ()이 testEmptyCollection () 전에 실행될 수 있습니다. (...)
왜 그래야만하지? 글쎄, 나는 테스트 순서에 의존 하는 것이 저자들이 홍보하고 싶지 않은 관행 이라고 믿는다 . 시험은 독립적이어야한다, 그들은 결합해서는 안되며이 위반 됩니다 유지하기 위해 더 열심히 일을 개별적으로 (분명히) 등의 테스트를 수행 할 수있는 능력을 깰 것이다
즉,이 방향으로 가고 싶다면 TestNG를 사용하는 것이 좋습니다 .TestNG는 기본적으로 임의의 순서로 테스트 메소드를 실행하는 것을 지원하므로 메소드 지정과 같은 것은 메소드 그룹에 따라 다릅니다. Cedric Beust는 testng에서 테스트 실행 순서 에 따라 이를 수행하는 방법을 설명합니다 .
Junit의 기존 인스턴스를 제거 하고 빌드 경로에서 JUnit 4.11 이상을 다운로드 하면 다음 코드는 이름 순서대로 테스트 메소드를 오름차순으로 정렬하여 실행합니다.
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SampleTest {
@Test
public void testAcreate() {
System.out.println("first");
}
@Test
public void testBupdate() {
System.out.println("second");
}
@Test
public void testCdelete() {
System.out.println("third");
}
}
주문이 중요한 경우 직접 주문해야합니다.
@Test public void test1() { ... }
@Test public void test2() { test1(); ... }
특히 필요한 경우 테스트 할 순서 순열의 일부 또는 전부를 나열해야합니다.
예를 들어
void test1();
void test2();
void test3();
@Test
public void testOrder1() { test1(); test3(); }
@Test(expected = Exception.class)
public void testOrder2() { test2(); test3(); test1(); }
@Test(expected = NullPointerException.class)
public void testOrder3() { test3(); test1(); test2(); }
또는 모든 순열에 대한 전체 테스트 :
@Test
public void testAllOrders() {
for (Object[] sample: permute(1, 2, 3)) {
for (Object index: sample) {
switch (((Integer) index).intValue()) {
case 1: test1(); break;
case 2: test2(); break;
case 3: test3(); break;
}
}
}
}
여기에 permute()
가능한 모든 순열을 배열 컬렉션으로 반복하는 간단한 함수가 있습니다.
TestNG로 마이그레이션하는 것이 가장 좋은 방법이지만 jUnit에 대한 명확한 해결책은 없습니다. jUnit에 대해 찾은 가장 읽기 쉬운 솔루션 / 형식 은 다음과 같습니다 .
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SampleTest {
@Test
void stage1_prepareAndTest(){};
@Test
void stage2_checkSomething(){};
@Test
void stage2_checkSomethingElse(){};
@Test
void stage3_thisDependsOnStage2(){};
@Test
void callTimeDoesntMatter(){}
}
이것은 stage2 메소드가 stage1 메소드 이후와 stage3 메소드 이전에 호출되도록합니다.
Junit에서 일할 때 직면 한 주요 문제 중 하나이며 다음과 같은 솔루션을 찾았습니다.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
public class OrderedRunner extends BlockJUnit4ClassRunner {
public OrderedRunner(Class<?> clazz) throws InitializationError {
super(clazz);
}
@Override
protected List<FrameworkMethod> computeTestMethods() {
List<FrameworkMethod> list = super.computeTestMethods();
List<FrameworkMethod> copy = new ArrayList<FrameworkMethod>(list);
Collections.sort(copy, new Comparator<FrameworkMethod>() {
@Override
public int compare(FrameworkMethod f1, FrameworkMethod f2) {
Order o1 = f1.getAnnotation(Order.class);
Order o2 = f2.getAnnotation(Order.class);
if (o1 == null || o2 == null) {
return -1;
}
return o1.order() - o2.order();
}
});
return copy;
}
}
또한 아래와 같은 인터페이스를 만듭니다.
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD})
public @interface Order {
public int order();
}
이제 아래와 같이 몇 가지 테스트 사례를 작성한 클래스 A가 있다고 가정하십시오.
(@runWith=OrderRunner.class)
Class A{
@Test
@Order(order = 1)
void method(){
//do something
}
}
따라서 "method ()"라는 메소드에서 실행이 시작됩니다. 감사!
https://github.com/junit-team/junit/pull/386 (아직 출시되지 않은) 변경 사항은을 소개합니다 @SortMethodsWith
. https://github.com/junit-team/junit/pull/293 적어도 주문 없이는 주문을 예측 가능하게 만들었습니다 (Java 7에서는 상당히 임의적 일 수 있음).
JUnit은 현재 클래스 어노테이션을 사용하여 테스트 메소드 실행 순서를 허용합니다.
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FixMethodOrder(MethodSorters.JVM)
@FixMethodOrder(MethodSorters.DEFAULT)
기본적으로 테스트 방법은 알파벳 순서로 실행됩니다. 따라서 특정 방법 순서를 설정하려면 다음과 같이 이름을 지정할 수 있습니다.
a_TestWorkUnit_WithCertainState_ShouldDoSomething b_TestWorkUnit_WithCertainState_ShouldDoSomething c_TestWorkUnit_WithCertainState_ShouldDoSomething
여기에서 예제 를 찾을 수 있습니다 .
JUnit 보고서를보십시오. JUnit은 이미 패키지별로 구성되어 있습니다. 각 패키지는 TestSuite 클래스를 갖거나 가질 수 있으며 각 클래스는 여러 개의 TestCase를 실행합니다. 각 TestCase는 형식의 여러 테스트 메소드를 가질 수 있으며 public void test*()
, 각 메소드 는 실제로 이들이 속하는 TestCase 클래스의 인스턴스가됩니다. 각 테스트 방법 (TestCase 인스턴스)에는 이름과 합격 / 불합격 기준이 있습니다.
경영진이 필요로하는 것은 개별 TestStep 항목 의 개념으로 , 각각 고유 한 합격 / 불합격 기준을보고합니다. 테스트 단계가 실패해도 후속 테스트 단계가 실행되지 않아야합니다.
과거에는 테스트 개발자가 TestCase 클래스를 테스트중인 제품의 일부에 해당하는 패키지로 구성하고 각 테스트에 대한 TestCase 클래스를 만들고 각 테스트 방법을 테스트에서 별도의 "단계"로 만들었습니다. JUnit 출력에서 자체 통과 / 실패 기준으로 완료하십시오. 각 TestCase는 독립형 "테스트"이지만 TestCase 내의 개별 메소드 또는 테스트 "단계"는 특정 순서로 발생해야합니다.
TestCase 방법은 TestCase의 단계였으며 테스트 디자이너는 테스트 단계마다 별도의 합격 / 불합격 기준을 받았습니다. 이제 테스트 단계가 혼란스럽고 테스트는 물론 실패합니다.
예를 들면 다음과 같습니다.
Class testStateChanges extends TestCase
public void testCreateObjectPlacesTheObjectInStateA()
public void testTransitionToStateBAndValidateStateB()
public void testTransitionToStateCAndValidateStateC()
public void testTryToDeleteObjectinStateCAndValidateObjectStillExists()
public void testTransitionToStateAAndValidateStateA()
public void testDeleteObjectInStateAAndObjectDoesNotExist()
public void cleanupIfAnythingWentWrong()
각 테스트 방법은 자체적 인 합격 / 불합격 기준을 주장하고보고합니다. 주문을 위해 이것을 "하나의 큰 테스트 방법"으로 축소하면 JUnit 요약 보고서에서 각 "단계"의 합격 / 불합격 기준 세분성이 손실됩니다. ... 내 매니저들을 화나게합니다. 그들은 현재 다른 대안을 요구하고 있습니다.
스크램블 된 테스트 방법 순서를 가진 JUnit이 위에서 예시되고 관리자가 요구 한대로 각 순차적 테스트 단계의 개별 통과 / 실패 기준을 어떻게 지원하는지 설명 할 수 있습니까?
문서에 관계없이 JUnit 프레임 워크에서 심각한 회귀가 발생하여 많은 테스트 개발자가 어려움을 겪고 있다고 생각합니다.
테스트 케이스가 스위트로 실행될 때 원하는 것은 완벽하게 합리적입니다.
불행히도 지금은 완벽한 솔루션을 제공 할 시간이 없지만 수업을 살펴보십시오.
org.junit.runners.Suite
특정 순서로 테스트 케이스 (모든 테스트 클래스에서)를 호출 할 수 있습니다.
기능, 통합 또는 시스템 테스트를 작성하는 데 사용될 수 있습니다.
이렇게하면 단위 테스트가 특정 순서없이 (권장대로) 실행되는지 여부에 관계없이 테스트를 그대로두고 더 큰 그림의 일부로 테스트를 재사용 할 수 있습니다.
우리는 단위, 통합 및 시스템 테스트, 때로는 데이터 구동, 커밋 구동, 때로는 스위트로 실행하기 위해 동일한 코드를 재사용 / 상속합니다.
동의하지 않습니다. '파일 업로드'를 테스트 한 다음 '파일 업로드에 의해 삽입 된 데이터'를 테스트하려면 왜 서로 독립적이지 않겠습니까? 완벽하게 합리적 나는 골리앗 테스트 케이스에두기보다는 개별적으로 실행할 수 있다고 생각합니다.
내 솔루션을 참조하십시오 : "Junit and java 7"
이 기사에서는 "소스 코드에서와 같이"순서대로 junit 테스트를 실행하는 방법을 설명합니다. 테스트 메소드가 클래스 파일에 표시되도록 테스트가 실행됩니다.
http://intellijava.blogspot.com/2012/05/junit-and-java-7.html
그러나 Pascal Thivent가 말했듯이 이것은 좋은 연습이 아닙니다.
JUnit 5 업데이트 및 내 의견
JUnit 작성자가 주문 기능을 원하지 않으면 JUnit에 대해 매우 중요한 기능이라고 생각합니다. 왜 그렇습니까?
기본적으로 단위 테스트 라이브러리는 소스 파일에서 발생하는 순서대로 테스트를 실행하지 않습니다.
JUnit 4로서의 JUnit 5는 그런 식으로 작동합니다. 왜 ? 순서가 중요하다면 일부 테스트가 서로 결합되어 단위 테스트에 바람직하지 않기 때문 입니다.
따라서 @Nested
JUnit 5에서 도입 한 기능은 동일한 기본 접근 방식을 따릅니다.
그러나 통합 테스트의 경우 테스트 방법이 다른 테스트 방법에서 예상 한 방식으로 응용 프로그램의 상태를 변경할 수 있으므로 테스트 방법의 순서가 중요 할 수 있습니다. 예를 들어 e-shop 체크 아웃 처리를위한 통합 테스트를 작성할 때 가장 먼저 실행되는 테스트 방법은 클라이언트를 등록하는 것이고, 두 번째는 바스켓에 항목을 추가하고 마지막은 체크 아웃을 수행하는 것입니다. 테스트 러너가 해당 순서를 준수하지 않으면 테스트 시나리오에 결함이있어 실패합니다.
따라서 JUnit 5 (5.4 버전)에서는 테스트 클래스에 주석을 달고 순서가 중요한 메소드 @TestMethodOrder(OrderAnnotation.class)
의 순서를 지정하여 실행 순서를 설정할 수 @Order(numericOrderValue)
있습니다.
예를 들면 다음과 같습니다.
@TestMethodOrder(OrderAnnotation.class)
class FooTest {
@Order(3)
@Test
void checkoutOrder() {
System.out.println("checkoutOrder");
}
@Order(2)
@Test
void addItemsInBasket() {
System.out.println("addItemsInBasket");
}
@Order(1)
@Test
void createUserAndLogin() {
System.out.println("createUserAndLogin");
}
}
출력 :
createUserAndLogin
addItemsInBasket
주문하기
그건 그렇고, 지정 @TestMethodOrder(OrderAnnotation.class)
이 필요하지 않은 것처럼 보입니다 (적어도 테스트 한 5.4.0 버전에서는).
참고 사항
질문에 대해 : JUnit 5가 통합 테스트를 작성하는 가장 좋은 선택입니까? 나는 그것이 고려해야 할 첫 번째 도구라고 생각하지는 않지만 (오이와 공동은 종종 통합 테스트를 위해 더 구체적인 가치와 기능을 가져올 수 있습니다) 일부 통합 테스트 사례에서는 JUnit 프레임 워크로 충분합니다. 이 기능이 존재한다는 것은 좋은 소식입니다.
몇 가지 답변을 읽었으며 모범 사례는 아니지만 테스트를 주문하는 가장 쉬운 방법에 동의합니다. JUnit이 기본적으로 테스트를 실행하는 방법은 알파벳 이름 오름차순입니다.
따라서 원하는 알파벳 순서로 테스트 이름을 지정하십시오. 또한 테스트 이름은 단어 test로 시작해야합니다. 숫자 만 조심하세요
test12는 test2 전에 실행됩니다
그래서:
testA_MyFirstTest 테스트 C_Third 테스트 테스트 B_ATestThatRunsSecond
https://github.com/TransparentMarket/junit를 확인 하십시오 . 지정된 순서대로 테스트를 실행합니다 (컴파일 된 클래스 파일 내에 정의 됨). 또한 하위 패키지로 정의 된 테스트를 먼저 실행하는 AllTests 제품군이 있습니다. AllTests 구현을 사용하면 속성을 필터링하여 솔루션을 확장 할 수 있습니다 (우리는 @Fast 주석을 사용했지만 아직 게시되지 않았습니다).
다음은 원하는 동작을 생성 할 수있는 JUnit의 확장입니다. https://github.com/aafuks/aaf-junit
나는 이것이 JUnit 철학의 저자에 위배된다는 것을 알고 있지만, 엄격한 단위 테스트 (Java로 실습 된)가 아닌 환경에서 JUnit을 사용하면 매우 도움이 될 수 있습니다.
나는 내 테스트가 순서대로 실행되지 않았다고 생각하면서 끝났지 만 진실은 엉망이 내 비동기 작업에 있다는 것입니다. 동시성 작업시 테스트 간에도 동시성 검사를 수행해야합니다. 필자의 경우 작업과 테스트는 세마포어를 공유하므로 실행중인 작업이 잠금을 해제 할 때까지 다음 테스트가 중단됩니다.
이것이이 질문과 완전히 관련이 없지만 올바른 문제를 타겟팅하는 데 도움이 될 수 있음을 알고 있습니다.
다음 코드 중 하나를 사용할 수 있습니다.
@FixMethodOrder(MethodSorters.JVM)OR `@FixMethodOrder(MethodSorters.DEFAULT)` OR `@FixMethodOrder(MethodSorters.NAME_ASCENDING)` before your test class like this:
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class BookTest { ...}
JUnit 5.4에서는 다음 순서를 지정할 수 있습니다.
@Test
@Order(2)
public void sendEmailTestGmail() throws MessagingException {
수업에 주석을 달기 만하면됩니다.
@TestMethodOrder(OrderAnnotation.class)
https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-execution-order
나는 이것을 내 프로젝트에서 사용하고 있으며 매우 잘 작동합니다!
참고 URL : https://stackoverflow.com/questions/3693626/how-to-run-test-methods-in-specific-order-in-junit4
'Programing' 카테고리의 다른 글
C # if / then 지시어 대 디버그 대 릴리스 (0) | 2020.02.23 |
---|---|
파일의 절대 경로를 인쇄하는 bash / fish 명령 (0) | 2020.02.23 |
개미 경고 :“ 'includeantruntime'이 설정되지 않았습니다.” (0) | 2020.02.23 |
Ruby에서 include와 extend의 차이점은 무엇입니까? (0) | 2020.02.23 |
GCC -fPIC 옵션 (0) | 2020.02.23 |