Можно ли пропустить сценарий с Cucumber-JVM во время выполнения

Я хочу добавить тег @skiponchrome в сценарий, это должно пропустить сценарий при запуске теста Selenium с браузером Chrome. Причина этого заключается в том, что некоторые сценарии работают в одних средах, а не в других, это может даже не быть специфичным для тестирования браузера и может применяться в другой ситуации, например, на платформах ОС.

Пример хука:

@Before("@skiponchrome") // this works
public void beforeScenario() {
  if(currentBrowser == 'chrome') { // this works
    // Skip scenario code here
  }
}

Я знаю, что можно определить ~@skiponchrome в тегах огурца, чтобы пропустить тег, но я хотел бы пропустить тег во время выполнения. Таким образом, мне не нужно заранее думать о том, какие шаги пропустить, когда я запускаю тестовый прогон в определенной среде.

Я хотел бы создать хук, который ловит тег и пропускает сценарий, не сообщая о сбое/ошибке. Это возможно?


person Niels van Reijmersdal    schedule 16.04.2013    source источник


Ответы (7)


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

вот как я написал свою логику в файле сценариев, где у нас есть связующий код для каждого шага.

Я использовал уникальный тег '@Feature-01AXX', чтобы отметить мои сценарии, которые необходимо запускать только тогда, когда эта функция (код) доступна в приложении.

поэтому для каждого сценария сначала проверяется тег @Feature-01XX, если он присутствует, то выполняется проверка доступности функции, и только после этого сценарий будет выбран для запуска. В противном случае он будет просто пропущен, и Junit не отметит это как неудачу, вместо этого он будет отмечен как пройденный. Так что окончательный результат, если эти тесты не были запущены из-за недоступности функции, будет пройден, это круто...

@Before
public void before(final Scenario scenario) throws Exception {
    /*
        my other pre-setup tasks for each scenario.
    */

    // get all the scenario tags from the scenario head.
    final ArrayList<String> scenarioTags = new ArrayList<>();
    scenarioTags.addAll(scenario.getSourceTagNames());

    // check if the feature is enabled on the appliance, so that the tests can be run.
    if (checkForSkipScenario(scenarioTags)) {
        throw new AssumptionViolatedException("The feature 'Feature-01AXX' is not enabled on this appliance, so skipping");
    }
}

private boolean checkForSkipScenario(final ArrayList<String> scenarioTags) {
    // I use a tag "@Feature-01AXX" on the scenarios which needs to be run when the feature is enabled on the appliance/application
    if (scenarioTags.contains("@Feature-01AXX") && !isTheFeatureEnabled()) { // if feature is not enabled, then we need to skip the scenario.
        return true;
    }
    return false;
}

private boolean isTheFeatureEnabled(){
    /*
        my logic to check if the feature is available/enabled on the application.
        in my case its an REST api call, I parse the JSON and check if the feature is enabled.
        if it is enabled return 'true', else return 'false'
    */
}
person Karthic.K    schedule 30.11.2016
comment
Выглядит хорошо, хотя я не проверял это, я сделаю это принятым ответом. - person Niels van Reijmersdal; 30.11.2016
comment
Я протестировал генерацию AssumptionViolatedException в хуке @Before, и он не прошел тест, пропустив его, вызвав сбой раньше. Неудачный тест отображается в Tests in Error в сводке после теста. Как можно полностью пропустить эти тесты? Используете ли вы собственный плагин или форк Cucumber? - person George Pantazes; 20.03.2017
comment
пожалуйста, используйте org.junit.internal.AssumptionViolatedException; - person Karthic.K; 14.12.2018

Я понял, что это запоздалое обновление на уже отвеченный вопрос, но я хочу добавить еще один вариант напрямую поддерживается огурцом-jvm:

@Before //(cucumber one)
public void setup(){
    Assume.assumeTrue(weAreInPreProductionEnvironment);
}

«и сценарий будет помечен как проигнорированный (но тест будет пройден), если weAreInPreProductionEnvironment ложно».

Вам нужно будет добавить

import org.junit.Assume;

Основное отличие от принятого ответа заключается в том, что JUnit предполагает, что сбои ведут себя так же, как ожидающие

Важно Из-за исправления ошибки вам понадобится огурец -jvm версии 1.2.5, которая на момент написания этой статьи является последней. Например, вышеприведенное приведет к сбою вместо ожидания в огурце-java8-1.2.3.jar.

person MikeJRamsey56    schedule 09.12.2016
comment
Он отлично работает для шагов, поэтому шаги помечаются как ожидающие, а сборка помечается как успешная. Но подключаемый модуль Jenkins для огурцов-отчетов помечает сценарии, содержащие тесты пединга, как не пройденные. Вы знаете, как помечать такие сценарии как Successsul? - person YuraHoy; 27.01.2021

Я действительно предпочитаю четко указывать, какие тесты выполняются, определяя отдельные конфигурации запуска для каждой среды. Мне также нравится сводить количество используемых тегов к минимуму, чтобы количество конфигураций оставалось управляемым.

Я не думаю, что можно добиться того, чего вы хотите, только с помощью тегов. Вам нужно будет написать собственный тестовый бегун jUnit для использования вместо @RunWith(Cucumber.class). Взгляните на реализацию Cucumber, чтобы увидеть, как все работает. Вам нужно будет изменить RuntimeOptions, созданные RuntimeOptionsFactory, чтобы включить/исключить теги в зависимости от браузера или других условий выполнения.

В качестве альтернативы вы можете подумать о написании небольшого сценария, который вызывает ваш набор тестов, создавая список тегов для динамического включения/исключения в зависимости от среды, в которой вы работаете. Я бы посчитал это более удобным и чистым решением.

person Chris Bushell    schedule 23.04.2013

На самом деле это очень просто. Если вы покопаетесь в исходном коде Cucumber-JVM и JUnit 4, вы обнаружите, что JUnit делает пропуск во время выполнения очень простым (просто недокументированным).

Взгляните на следующий исходный код для JUnit 4 ParentRunner, который Cucumber-JVM FeatureRunner (который используется в Cucumber, бегун Cucumber по умолчанию):

@Override
public void run(final RunNotifier notifier) {
    EachTestNotifier testNotifier = new EachTestNotifier(notifier,
            getDescription());
    try {
        Statement statement = classBlock(notifier);
        statement.evaluate();
    } catch (AssumptionViolatedException e) {
        testNotifier.fireTestIgnored();
    } catch (StoppedByUserException e) {
        throw e;
    } catch (Throwable e) {
        testNotifier.addFailure(e);
    }
}

Вот как JUnit решает, какой результат показывать. В случае успеха он покажет проход, но в JUnit возможно @Ignore, так что же происходит в этом случае? Ну, AssumptionViolatedException выбрасывается RunNotifier (или в данном случае Cucumber FeatureRunner).

Таким образом, ваш пример становится:

@Before("@skiponchrome") // this works
public void beforeScenario() {
  if(currentBrowser == 'chrome') { // this works
    throw new AssumptionViolatedException("Not supported on Chrome")
  }
}

Если вы раньше использовали ванильный JUnit 4, вы помните, что @Ignore принимает необязательное сообщение, которое отображается, когда бегун игнорирует тест. AssumptionViolatedException несет сообщение, поэтому вы должны увидеть его в выводе теста после того, как тест будет пропущен таким образом, без необходимости писать свой собственный бегун.

person Mike Holler    schedule 20.11.2015
comment
Как я могу перезаписать метод run? Я просмотрел структуру проекта Cucumber, но не смог найти способ переопределить ее из кода моего фреймворка. Можете ли вы дать какой-то указатель? - person cbaldan; 08.04.2016
comment
Вам не нужно. Это исходный код метода run в том виде, в каком он есть; это уже есть. Все, что вам нужно, находится во втором блоке кода. - person Mike Holler; 08.04.2016
comment
Я использую огурец-java 1.2.4, и он сообщает AssumptionViolationExceptions как сбои. Однако на чистом JUnit это работает. - person cbaldan; 08.04.2016
comment
@cbaidanyou может скопировать из репозитория maven и использовать его после настройки. - person Rahal Kanishka; 06.09.2017

Я реализовал настроенный бегун junit, как показано ниже. Идея состоит в том, чтобы добавлять теги во время выполнения.

Итак, скажем, для сценария нам нужны новые пользователи, мы помечаем сценарии как «@requires_new_user». Затем, если мы запустим наш тест в среде (скажем, в производственной среде, которая не позволяет вам легко зарегистрировать нового пользователя), мы обнаружим, что не можем получить нового пользователя. Затем к параметрам огурца будет добавлено «не @requires_new_user», чтобы пропустить сценарий.

Это самое чистое решение, которое я могу себе представить сейчас.

public class WebuiCucumberRunner extends ParentRunner<FeatureRunner> {
    private final JUnitReporter jUnitReporter;
    private final List<FeatureRunner> children = new ArrayList<FeatureRunner>();
    private final Runtime runtime;
    private final Formatter formatter;

    /**
     * Constructor called by JUnit.
     *
     * @param clazz the class with the @RunWith annotation.
     * @throws java.io.IOException                         if there is a problem
     * @throws org.junit.runners.model.InitializationError if there is another problem
     */
    public WebuiCucumberRunner(Class clazz) throws InitializationError, IOException {
        super(clazz);
        ClassLoader classLoader = clazz.getClassLoader();
        Assertions.assertNoCucumberAnnotatedMethods(clazz);

        RuntimeOptionsFactory runtimeOptionsFactory = new RuntimeOptionsFactory(clazz);
        RuntimeOptions runtimeOptions = runtimeOptionsFactory.create();

        addTagFiltersAsPerTestRuntimeEnvironment(runtimeOptions);

        ResourceLoader resourceLoader = new MultiLoader(classLoader);
        runtime = createRuntime(resourceLoader, classLoader, runtimeOptions);
        formatter = runtimeOptions.formatter(classLoader);
        final JUnitOptions junitOptions = new JUnitOptions(runtimeOptions.getJunitOptions());
        final List<CucumberFeature> cucumberFeatures = runtimeOptions.cucumberFeatures(resourceLoader, runtime.getEventBus());
        jUnitReporter = new JUnitReporter(runtime.getEventBus(), runtimeOptions.isStrict(), junitOptions);
        addChildren(cucumberFeatures);
    }

    private void addTagFiltersAsPerTestRuntimeEnvironment(RuntimeOptions runtimeOptions) 
    {
        String channel = Configuration.TENANT_NAME.getValue().toLowerCase();
        runtimeOptions.getTagFilters().add("@" + channel);

        if (!TestEnvironment.getEnvironment().isNewUserAvailable()) {
            runtimeOptions.getTagFilters().add("not @requires_new_user");
        }

    }
...
}

Или вы можете расширить официальный тестовый бегун Cucumber Junit cucumber и переопределить метод

    /**
     * Create the Runtime. Can be overridden to customize the runtime or backend.
     *
     * @param resourceLoader used to load resources
     * @param classLoader    used to load classes
     * @param runtimeOptions configuration
     * @return a new runtime
     * @throws InitializationError if a JUnit error occurred
     * @throws IOException         if a class or resource could not be loaded
     * @deprecated Neither the runtime nor the backend or any of the classes involved in their construction are part of
     * the public API. As such they should not be  exposed. The recommended way to observe the cucumber process is to
     * listen to events by using a plugin. For example the JSONFormatter.
     */
    @Deprecated
    protected Runtime createRuntime(ResourceLoader resourceLoader, ClassLoader classLoader,
                                    RuntimeOptions runtimeOptions) throws InitializationError, IOException {
        ClassFinder classFinder = new ResourceLoaderClassFinder(resourceLoader, classLoader);
        return new Runtime(resourceLoader, classFinder, classLoader, runtimeOptions);
    }

Здесь вы можете манипулировать runtimeOptions по своему усмотрению. Но метод помечен как устаревший, поэтому используйте его с осторожностью.

person Wenzhong Hu    schedule 05.03.2019

Если вы используете Maven, вы можете прочитать использование профиля браузера, а затем установить там соответствующие теги ~ exclude?

Если вы не спрашиваете, как запустить это из командной строки, в этом случае вы помечаете сценарий @skipchrome, а затем, когда запускаете огурец, устанавливаете параметры огурца на tags = {"~@skipchrome"}

person theawesome    schedule 16.04.2013

Если вы хотите просто временно пропустить сценарий (например, при написании сценариев), вы можете закомментировать его (ctrl+/ в Eclipse или Intellij).

person Mate Mrše    schedule 20.02.2019