Пропуск интеграционных тестов при весенней загрузке при доступности VPN DNS - PullRequest
0 голосов
/ 25 июня 2019

У меня есть служба Springboot средней тяжести, для загрузки в «счастливом» потоке требуется 10-15 секунд, и (1-2) минуты для сбоя в потоке повторных попыток / отработки отказа. Это нормально для моих бизнес-потоков, и я ожидаю, что здоровый сервис будет вести себя хорошо.

У меня есть интеграционные тесты (которые запускают некоторые сквозные потоки в моем сервисе), которые могут проверять фактическое состояние интеграции только тогда, когда тестовый компьютер (или компьютер разработчика) подключен к определенной VPN.

Я хочу автоматически пропустить интеграционные тесты, если я не подключен к VPN.

рассмотрите следующий код

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Server.class}, // auto scans a bunch of components
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) // slow loading context
public class IntegrationTest {
    @BeforeClass
    public static void beforeClass() {
        Assume.assumeTrue(DnsTool.vpnConnected()); // fast failing test
    }

    @Test
    public void testIntegration() {
        // some test logic
    }
}

Когда предположения проходят, мои тесты запускаются, и все хорошо. Когда предположения не выполняются, мои тесты пропускаются, но только после попытки загрузить мой дорогой контекст.

Как мне избежать длительного времени работы моего набора тестов?

То, что я пытался:

  • Подклассы SpringJUnit4ClassRunner и переопределение isTestMethodIgnored.
  • Добавление TestExecutionListener и исключение предположения в beforeTestClass

Это не произвело никакого впечатления на Spring, и контекст был загружен любым способом.

Вещи, которые я не пробовал:

  • Lazy init поставляется с 2.2.X следующим стабильным выпуском весны, я думаю.

Lazy init потенциально устраняет мою проблему, но я чувствую, что должно быть какое-то простое исправление весеннего теста / junit, которое мне не хватает.

Заранее спасибо за помощь.

1 Ответ

1 голос
/ 26 июня 2019

Для меня это звучит как то, что вы не должны делать на тестах вообще.Тесты (по крайней мере, IMHO) должны проверять бизнес-кейсы и предполагать, что среда настроена и готова.

Возможно, стоит делегировать эту функциональность инструменту сборки и CI.

Пример:

Определите профиль в maven (или любой другой инструмент для сборки, который вы используете), который будет запускать интеграционные тесты, требующие VPN.Определите профиль, который будет выполнять все остальные интеграционные тесты.Активируйте профиль, если доступно какое-либо системное свойство.

В инструменте CI (например, Jenkins) в составе CI даже до запуска maven запустите сценарий, который будет проверять VPN-соединение.На основании результатов установите системные свойства и запустите maven с этими свойствами.Необходимые профили будут загружены, и будут запущены все тесты / только тесты, не требующие VPN.

Обновление

Если вам нужно, чтобы он работал из Spring(и, похоже, вы предпочитаете этот способ), Spring имеет специальную аннотацию под названием @IfProfileValue

По умолчанию она сопоставляется со свойствами системы, и если значение не совпадает, тест игнорируется.

Это выглядит примерно так (и обратите внимание, что вы также можете поместить эту аннотацию на класс, тогда она будет работать для всех методов тестирования в классе):

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTestClass {


    @IfProfileValue(name = "os.name", values = {"Linux"})
    @Test
    public void testMe() {
     // will run only in linux, otherwise
     // won't even try to load an 
     // application context
    ....
    }
  }

Это относится к случаю, когда выразрешить VPN-подключение извне и запустить тесты со свойством.Однако, если вы хотите реализовать проверку VPN-подключения в Java, этой аннотации недостаточно, потому что она может работать только со свойствами системы Java, поэтому для работы с пользовательской логикой необходимо реализовать org.springframework.test.annotation.ProfileValueSource:

public class VPNConnectivityProfileValueSource implements ProfileValueSource {

  private String vpnEnabled = "true";
  public VPNConnectivityProfileValueSource () {
     // no spring context is available here
     ClassPathResource resource = new ClassPathResource("vpn-config.properties");

     if (resource.exists()) {
          // read the VPN address, 
          //   
          //this.testProps = PropertiesLoaderUtils.loadProperties(resource);
          // invoke your utility, check the connectivity, etc. 
          this.vpnEnabled = ...
     }

}

  @Override
  public String get(String key) {
    // this is important method, 
    if(key.equals("vpn.enabled") {
       return this.vpnEnabled;  
    } 
    else return System.getProperty(key);
  }
}

Последнее, что нужно сделать, чтобы тест знал о ProfileValueSource: для этого есть еще одна специальная аннотация, которую вы помещаете в тест: @ProfileValueSourceConfiguration(VPNConnectivityProfileValueSource.class)

В целом тест может выглядеть так:

@RunWith(SpringRunner.class)
@SpringBootTest
@ProfileValueSourceConfiguration(VPNConnectivityProfileValueSource.class)
@IfProfileValue(name = "vpn.enabled", value = "true")
public class MyTestClass {

   @Test
   public void testMe() {
     ....
   }
}

Все упомянутые классы / аннотации находятся в пакете org.springframework.test.annotation

...