Как сделать разовую проверку условия с использованием аннотаций jUnit 5?

Теги: #<Tag:0x00007f737d1bf998>

Здравствуйте, гуру тестирования! Есть у меня проект со стеком Gradle - jUnit 5 - RestAssured для тестирования некоторых API. Хочу реализовать проверку доступности сервиса с этими API перед запуском всех тестов или хотя бы каждого отдельного класса с тестами и, если сервис недоступен скипать выполнение тестов.

На данный момент смог реализовать в следующем виде:

кастомная аннтотация jUnit:
public class SkipTestExtension implements ExecutionCondition {

    @Override
    public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
        // check the service availability
        boolean result = isServiceAvailable();

        if (result) {
            return ConditionEvaluationResult.enabled("The service is available");
        } else {
            return ConditionEvaluationResult.disabled("The service is unavailable -> skip the test!");
        }
    }

    // This is a custom annotation for the skip test condition when service is unavailable
    @Target({ ElementType.TYPE, ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    @ExtendWith(SkipTestExtension.class)
    public @interface SkipWhenServiceIsUnavailable {
    }
}
какой-нибудь из тестовых классов:
@SkipWhenServiceIsUnavailable
public class Auth_tests {

    @Test
    public void createToken_code200_test() {
        // some code
    }


    @Test
    public void createToken_invalidCreds_test() {
        // some code
    }

но в этом случае проверка условия доступности сервиса (isServiceAvailable()) выполняется каждый раз для каждого теста, а мне бы хотелось делать эту проверку один раз.
Переделал аннтоацию с boolean аргументом, определяющим делать skip тесту или нет:

Сводка
public class SkipTestExtension2 implements ExecutionCondition {

    @Override
    public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
        final var optional = findAnnotation(context.getElement(), SkipWhenServiceIsUnavailable2.class);
        if (optional.isPresent()) {
            final SkipWhenServiceIsUnavailable2 annotation = optional.get();
            final boolean status = annotation.status();

            if (status) {        
                return ConditionEvaluationResult.enabled("The service is available");
            } else {
                return ConditionEvaluationResult.disabled("The service is unavailable -> skip the test!");
            }
        }
        return ConditionEvaluationResult.enabled("No argument specified, continue...");
    }

    // This is a custom annotation for the skip test condition when service is unavailable
    @Target({ ElementType.TYPE, ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    @ExtendWith(SkipTestExtension.class)
    public @interface SkipWhenServiceIsUnavailable2 {
          boolean status();
    }
}
и в тест классах аннотирую сами тесты:
public class Auth_tests {

    @SkipWhenServiceIsUnavailable2(status = true)
    @Test
    public void createToken_code200_test() {
        // some code
    }

    @SkipWhenServiceIsUnavailable2(status = false)
    @Test
    public void createToken_invalidCreds_test() {
        // some code
    }

но передать как аргумент в аннотацию метод или статическую переменную, например из супер класса, не получится даже если она final, потому что “Attribute value must be constant”. Можно ли как-то обойти это ограничение или вообще реализовать задачу по-другому?

Попробуй так

public class ResourcesTests implements BeforeAllCallback{

    @Override
    public void beforeAll(ExtensionContext context) {
       if( ! isServiceAvailable()) return;
    }
}

Затем

@ExtendWith(ResourcesTests.class)
public class Auth_tests {

    @Test
    public void createToken_code200_test() {
        // some code
    }

    @Test
    public void createToken_invalidCreds_test() {
        // some code
    }
}

Либо используете @BeforeAll

public class Auth_tests {

   @BeforeAll
    static void setUp(){ if( ! isServiceAvailable()) return; }
    
   @Test
    public void createToken_code200_test() {
        // some code
    }

    @Test
    public void createToken_invalidCreds_test() {
        // some code
    }
}

@pbezpal, спасибо! Но при таком решении тесты будут фэйлиться (скажем если в setUp() есть еще что-то нужно по конфигурации) или вообще не запускать т.к. isServiceAvailable() вернул false. А я хочу чтобы тесты именно скипались и это было видно в репорте. В TestNG на такой случай есть SkipException но вот в jUnit 5 я такого не вижу.

Потому что в JUnit 5 нет такой фичи. Можно как то извернуться и вызывать у тестовых методов @Disable, но я такого не делал.

Если вы используете Allure, то можно присвоить стату skip в отчёте данному тесту.

Оказывается все можно сделать намного проще, просто добавил в testBase класс assumeTrue на метод isServiceAvailable():

testBase класс:
public class SetUp {
   
    @BeforeAll
    public static void setUp() {
        // this will skip the tests execution if the service is not available
        Assumptions.assumeTrue(isServiceAvailable(), "The service is not available! Skip all the tests");

        baseURI = "https://something.com";
        basePath = "/something/";
        RestAssured.port = 8080;
        config = config()
                .encoderConfig(EncoderConfig
                        .encoderConfig()
                        .defaultContentCharset("UTF-8"));     
                );
        ***
    }

и теперь все тест классы, которые наследуют setUp класс будут скипать тесты если isServiceAvailable() вернул false, чего собственно и хотелось. Спасибо за внимание!!

1 симпатия

Прекрасно)