Right now do !

[JAVA] JUnit5 - 조건에 따라 테스트 수행

by 지금당장해

프롤로그

테스트를 작성하고 관리하던 중 특정 PC에서만 동작하는 테스트가 발생 했다. 원칙적으로는 모든 환경에서 테스트가 가능해야 하지만 진짜 그렇게 하려면 엄청난 노력을 해야 한다. 예를 들어 JNDI로 DB pool을 테스트 하기 위해 리얼 DB를 접속해서 쿼리를 해보는거 까지 진행되는 테스트 시나리오의 테스트 코드가 있다고 가정 했을때 이 테스트를 내 개발환경이 아닌 다른 머신에서도 동작하게 하기 위해서는 DBMS가 모두 접근 할 수 있는 위치에 있거나 테스트 수행전에 관련 설치를 해야 하는데 현실적으로 쉽지 않다. 특히나 현재 우리팀이 사용하고 있는 GitHub Actions를 통한 빌드를 하는 경우 더더욱 힘든 일이다.

본론

트레이드 오프(현실과의 타협)

이런 테스트 코드를 남겨둔체 소스를 서버로 푸쉬하고 그게 뭐가 되었던 CI 를 통해 빌드를 하면 대박에 이런류의 테스트 때문에 빌드는 실패한다. (이걸 요즘 젊은 개발자들은 빌드가 깨졌다고 하던가?) 그렇다고 테스트를 아애 않할 수는 없고 …

첨에 대안으로 JUnit5를 사용하는 필자는 @Disable 을 사용했다. 이런 특정 시스템에서만 수행이 가능한 테스트들을 하나의 클래스에 모아놓고 내 개발환경에서만 이를 잠깐 지우고 회귀 테스트를 하고 다시 @Disable을 넣어 서버로 푸쉬하는 짓을 했다. 까먹으면 슬랙에 메시지가 온다. 빌드가 실패 했다고 …. 아~ 짜증이 난다. 뭔 방법이 있을 터인데 …. 오늘은 이걸 해결한다.

조건에 따라 @Disable 을 하는 것을 현실적인 목표로

일단 제약은 있다. 모든 시스템에서 모든 테스트를 다 돌리는 것은 포기 했다. 나중에 여유가 생겨 우리 빌드 머신을 따로 두는 날까지 잠깐 포기하는거다. 그저 수동으로 @Disable을 썼다 지웠다 하는 짓거리만이라도 자동화 하자. 구글링을 했다. JUnit4를 쓰던 시절에 @RunWith를 통해서 뭔가 개발자가 커스텀한 전후 처리를 집어 넣을 수 있는 메커니즘이 있었다는 것을 기억하고 있던 터라 거기부터 찾았다. JUnit5에서는 @ExtendWith 라는 애노테이션으로 변경되었다. 그리고 여기에 여러 형태의 인터페이스를 지정할 수 있는데 오늘 필자가 소개할 인터페이스는 ExecutionCondition 이다. 느낌 빡온다. 실행 조건을 만들어 내는 것이 골자다. 단 하나의 구현 의무가 존재하는데 evaluateExecutionCondition 라는 함수다. 실행 할 수 있는 조건인지 확인해서 이 함수에서 enable 인지 disable인지 반환하면 해당 테스트의 수행이 결정되는 메커니즘이다. 당연히 이 클래스의 적용은 해당 테스트 클래스에 애노테이션으로 지정하므로써 이루어진다.

 

ExecutionCondition 의 구현예

필자가 예로 든 Case(구현 Class)는 HTTP 모듈의 SSL 테스트를 할 수 있는 컴퓨터인지를 특정 프로퍼티 파일에 지정하고 이를 읽어 등록된 컴퓨터라면 enable을 그렇지 않은 컴퓨터라면 disable을 리턴하는 기능을 가지고 있다.

public class SslEnvironmentExtension implements ExecutionCondition {

    @Override
    public ConditionEvaluationResult evaluateExecutionCondition(
        ExtensionContext context) {

        Properties props = new Properties();
        try {
            InputStream is = SslEnvironmentExtension.class.
                getResourceAsStream("ssl-environment.properties");
            props.load(is);
        } catch (Exception e) {
            return ConditionEvaluationResult.disabled("Can not load ssl-environment.properties in" +
                " in test resources");
        }

        String env = props.getProperty("com.potalab.wafull.connector.test.ssl.enable.computers");
        env = env.replaceAll("\\s", "");

        List<String> computers = Arrays.asList(env.split(","));

        if(computers.contains(getComputerName())) {
           return ConditionEvaluationResult.enabled("This computer has been identified as an " +
               "environment capable of SSL domain testing. We will proceed with the related test.");
        }

        return ConditionEvaluationResult.disabled("This test must be a domain computer subject " +
            "to the SSL certificate However, this computer does not have a list of computers. " +
            "Please check the list set in the ssl-environment.properties file.");

    }

    private String getComputerName() {
        Map<String, String> env = System.getenv();
        if (env.containsKey("COMPUTERNAME")) {
            return env.get("COMPUTERNAME");
        } else {
            return env.getOrDefault("HOSTNAME", "Unknown Computer");
        }

    }
}

이 코드에서는 테스트 환경이 갖추어진 PC목록을 관리하기 위해서 ssl-environment.properties 라고 하는 프로퍼티 파일을 사용하고 있으며 이는 test 리소스로 관리되어야 한다. 참고로 내용은 다음과 같다.

 

 

com.potalab.wafull.connector.test.ssl.enable.computers=WIN-DESKTOP-HONG

에필로그

이번 글에서는 @ExtendWith를 테스트의 실행 컨디션을 지정하는 목적으로 사용했다. 그러나 이것이 전부는 아니다. 필자도 당장 필요한 기능을 구현한 것이고 @ExtendWith에 대한 자세한 사항은 참고자료등을 통해서 천천히 정리 해볼 필요가 있을것 같다.

참고자료

https://www.baeldung.com/junit-5-extensions

 

블로그의 정보

지금 당장 해!!!

지금당장해

활동하기