[java] JUnit4 fail ()은 여기 있지만 pass ()는 어디에 있습니까?

fail()JUnit4 라이브러리 에는 메소드가 있습니다. 나는 그것을 좋아하지만 pass()도서관에없는 방법이 부족하다 . 왜 그래야만하지?

assertTrue(true)대신 사용할 수 있지만 여전히 비논리적으로 보입니다.

@Test
 public void testSetterForeignWord(){
  try {
   card.setForeignWord("");
   fail();
  } catch (IncorrectArgumentForSetter ex){
  }

 // assertTrue(true);
 }



답변

테스트가 예외를 throw하지 않는 한, @Test주석이 예상 예외를 지정 하지 않는 한 통과 합니다. 나는 pass()테스트를 단락시키기 위해 JUnit이 항상 통과하는 것으로 해석하는 특별한 예외를 던질 수 있다고 생각 하지만, 그것은 일반적인 테스트 디자인에 어긋날 것이다 (즉, 성공을 가정하고 단언이 실패 할 경우에만 실패한다). 를 사용하는 것이 더 낫다는 생각 pass()은 예외 생성의 오버 헤드로 인해 많은 테스트를 통과하는 속도를 상당히 늦출 것입니다. 실패한 테스트는 표준이 아니므로 오버 헤드가있는 경우 큰 문제가 아닙니다.

예제는 다음과 같이 다시 작성할 수 있습니다.

@Test(expected=IncorrectArgumentForSetter.class)
public void testSetterForeignWord("") throws Exception {
  card.setForeignWord("");
}

또한 표준 Java 예외를 사용하는 것이 좋습니다. 당신은 IncorrectArgumentForSetter아마이어야한다 IllegalArgumentException.


답변

return테스트가 완료되고 통과 될 때마다 문을 호출 하십시오.


답변

여기에있는 대부분의 답변이 상당히 구식이기 때문에이 질문에 업데이트 된 답변이 필요하다고 생각합니다.

먼저 OP의 질문에 :

나는 JUnit에 “예상 된 예외”개념을 도입하는 것이 나쁜 움직임이라는 것을 꽤 잘 받아 들였다고 생각한다. 그 예외는 어디에서나 발생할 수 있고 테스트를 통과 할 것이기 때문이다. 매우 도메인 특정 예외를 던지고 주장하는 경우 작동하지만 절대적으로 완전해야하는 코드를 작업 할 때만 이러한 종류의 예외를 던집니다. 대부분의 APIS는 단순히 IllegalArgumentException또는 IllegalStateException. 두 번의 호출이 이러한 예외를 잠재적으로 던질 수 @ExpectedException있다면, 예외를 던지는 잘못된 행이 있더라도 주석은 테스트를 녹색 막대로 표시합니다!

이 상황을 위해 나는 여기에 많은 다른 사람들이 작성했다고 확신하는 클래스를 작성했습니다 assertThrows.

public class Exceptions {
    private Exceptions(){}

    public static void assertThrows(Class<? extends Exception> expectedException, Runnable actionThatShouldThrow){
        try{
            actionThatShouldThrow.run();
            fail("expected action to throw " + expectedException.getSimpleName() + " but it did not.");
        }
        catch(Exception e){
            if ( ! expectedException.isInstance(e)) {
                throw e;
            }
        }
    }
}

이 메소드는 예외가 발생하면 단순히 반환하므로 테스트에서 추가 주장 / 확인을 수행 할 수 있습니다.

Java 8 구문을 사용하면 테스트가 정말 멋지게 보입니다. 다음은이 방법을 사용하는 모델에 대한 더 간단한 테스트 중 하나입니다.

@Test
public void when_input_lower_bound_is_greater_than_upper_bound_axis_should_throw_illegal_arg() {
    //setup
    AxisRange range = new AxisRange(0,100);

    //act
    Runnable act = () -> range.setLowerBound(200);

    //assert
    assertThrows(IllegalArgumentException.class, act);
}

이 테스트는 “act”단계가 실제로 어떤 작업도 수행하지 않기 때문에 약간 불안정하지만 의미는 여전히 상당히 명확하다고 생각합니다.

또한 예외가 발생하는지 확인하기 위해 mockito 스타일 구문을 사용하는 catch-exception 이라는 maven에 작은 라이브러리가 있습니다. 예쁘게 보이지만 동적 프록시의 팬은 아닙니다. 즉, 구문이 너무 매끄 럽기 때문에 여전히 유혹적입니다.

// given: an empty list
List myList = new ArrayList();

// when: we try to get the first element of the list
// then: catch the exception if any is thrown 
catchException(myList).get(1);

// then: we expect an IndexOutOfBoundsException
assert caughtException() instanceof IndexOutOfBoundsException;

마지막으로이 스레드에 도달하기 위해 발생한 상황에 대해 일부 조건이 충족되면 테스트 를 무시할 수 있는 방법 이 있습니다.

지금은 JNA라는 자바 네이티브 라이브러리 로딩 라이브러리를 통해 일부 DLL을 호출하고 있지만 빌드 서버는 우분투에 있습니다. 나는 JUnit 테스트로 이런 종류의 개발을 추진하는 것을 좋아합니다. 비록 지금은 “단위”와는 거리가 멀지 만요. 내가하고 싶은 것은 로컬 컴퓨터에 있으면 테스트를 실행하고 우분투에 있으면 테스트를 무시하는 것입니다. JUnit 4에는 다음과 같은 조항이 있습니다 Assume.

@Test
public void when_asking_JNA_to_load_a_dll() throws URISyntaxException {
    //this line will cause the test to be branded as "ignored" when "isCircleCI" 
    //(the machine running ubuntu is running this test) is true.
    Assume.assumeFalse(BootstrappingUtilities.isCircleCI());
    //an ignored test will typically result in some qualifier being put on the results, 
    //but will also not typically prevent a green-ton most platforms. 

    //setup
    URL url = DLLTestFixture.class.getResource("USERDLL.dll");
    String path = url.toURI().getPath();
    path = path.substring(0, path.lastIndexOf("/"));

    //act
    NativeLibrary.addSearchPath("USERDLL", path);
    Object dll = Native.loadLibrary("USERDLL", NativeCallbacks.EmptyInterface.class);

    //assert
    assertThat(dll).isNotNull();
}


답변

passJUnit에 대한 방법 도 찾고 있었기 때문에 일부 시나리오에서 적용 할 수없는 일부 테스트를 단락시킬 수있었습니다 (순수 단위 테스트가 아닌 통합 테스트가 있습니다). 너무 나쁘다.

다행히도 조건부로 테스트를 무시하는 방법이 있습니다. 실제로 assumeTrue메서드를 사용 하는 경우에 더 적합합니다 .

Assume.assumeTrue (isTestApplicable);

따라서 여기서 테스트는 isTestApplicable이 true 인 경우에만 실행되고 그렇지 않으면 테스트가 무시됩니다.


답변

테스트 코드에서 AssertionFailedException이 발생하지 않으면 단위 테스트 케이스가 통과하므로 통과 메서드가 필요하지 않습니다.

fail () 메서드는 실제로 AssertionFailedException을 throw하여 제어가 해당 지점에 도달하면 testCase를 실패합니다.


답변

이 질문은 테스트 실행 과정에 대한 약간의 오해의 결과라고 생각합니다. JUnit (및 기타 테스트 도구)에서 결과는 assert 호출이 아닌 메서드별로 계산됩니다. assertX실행 된 통과 / 실패 횟수를 추적하는 카운터가 없습니다 .

JUnit은 각 테스트 메소드를 개별적으로 실행합니다. 메서드가 성공적으로 반환되면 테스트가 “통과”로 등록 된 것입니다. 예외가 발생하면 테스트가 “실패”로 등록됩니다. 후자의 경우 두 가지 하위 사례가 가능합니다. 1) JUnit 어설 션 예외, 2) 기타 모든 종류의 예외. 상태는 첫 번째 경우 “실패”, 두 번째 경우 “오류”입니다.

에서 Assert클래스 많은 속기 방법은 주장 예외를 던지는 avaiable이다입니다. 즉, AssertJUnit의 예외에 대한 추상화 계층입니다.

예를 들어,이의 소스 코드 assertEqualsGitHub의는 :

/**
 * Asserts that two Strings are equal.
 */
static public void assertEquals(String message, String expected, String actual) {
    if (expected == null && actual == null) {
        return;
    }
    if (expected != null && expected.equals(actual)) {
        return;
    }
    String cleanMessage = message == null ? "" : message;
    throw new ComparisonFailure(cleanMessage, expected, actual);
}

보시다시피 평등의 경우 아무 일도 일어나지 않으면 예외가 발생합니다.

그래서:

assertEqual("Oh!", "Some string", "Another string!");

ComparisonFailureJUnit에 의해 포착 될 예외 를 던지고

assertEqual("Oh?", "Same string", "Same string");

아무것도하지 않습니다.

요컨대, 같은 pass()것은 아무 일도하지 않았기 때문에 의미가 없습니다.


답변