programing

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

nasanasas 2020. 11. 1. 18:12
반응형

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에 "예상 된 예외"개념을 도입 한 것이 나쁜 움직임이라는 것을 꽤 잘 받아 들였다고 생각한다. 그 예외는 어디에서나 발생할 수 있고 테스트를 통과 할 것이기 때문이다. 당신 던지는 매우 도메인 특정 예외 (그리고에 주장),하지만 난 단지 내가 필요가 절대적으로 뽀얀 될 것으로 코드에서 일하고 있어요 예외 이러한 종류의를 던질 경우 작동, --most 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;

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

Right now I'm working on getting some DLLs called through a java native-library-loading-library called JNA, but our build server is in ubuntu. I like to try to drive this kind of development with JUnit tests --even though they're far from "units" at this point--. What I want to do is run the test if I'm on a local machine, but ignore the test if we're on ubuntu. JUnit 4 does have a provision for this, called 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();
}

I was looking for pass method for JUnit as well, so that I could short-circuit some tests that were not applicable in some scenarios (there are integration tests, rather than pure unit tests). So too bad it is not there.

Fortunately, there is a way to have a test ignored conditionally, which actually fits even better in my case using assumeTrue method:

Assume.assumeTrue(isTestApplicable);

So here the test will be executed only if isTestApplicable is true, otherwise test will be ignored.


There is no need for the pass method because when no AssertionFailedException is thrown from the test code the unit test case will pass.

The fail() method actually throws an AssertionFailedException to fail the testCase if control comes to that point.


I think that this question is a result of a little misunderstanding of the test execution process. In JUnit (and other testing tools) results are counted per method, not per assert call. There is not a counter, which keeps track of how many passed/failured assertX was executed.

JUnit executes each test method separately. If the method returns successfully, then the test registered as "passed". If an exception occurs, then the test registered as "failed". In the latter case two subcase are possible: 1) a JUnit assertion exception, 2) any other kind of exceptions. Status will be "failed" in the first case, and "error" in the second case.

In the Assert class many shorthand methods are avaiable for throwing assertion exceptions. In other words, Assert is an abstraction layer over JUnit's exceptions.

For example, this is the source code of assertEquals on GitHub:

/**
 * 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);
}

As you can see, in case of equality nothing happens, otherwise an excepion will be thrown.

So:

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

simply throws a ComparisonFailure exception, which will be catched by JUnit, and

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

does NOTHING.

In sum, something like pass() would not make any sense, because it did not do anything.

참고URL : https://stackoverflow.com/questions/4036144/junit4-fail-is-here-but-where-is-pass

반응형