Пропуск теста в Cypress условно - PullRequest
0 голосов
/ 05 февраля 2019

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

Я читал об условном тестировании вCypress docs https://docs.cypress.io/guides/core-concepts/conditional-testing.html, а также документация mochajs об этом https://mochajs.org/.

Мое намерение состоит в том, чтобы проверить, отображается ли ошибка на веб-сайте, и пропустить тест, если это так.В противном случае продолжите с утверждениями.

Фрагмент кода от mochajs, который я пытаюсь взять на тест в Cypress:

it('should only test in the correct environment', function() {
  if (/* check test environment */) {
    // make assertions
  } else {
    this.skip();
  }
});

Итак, что я получил в Cypress:

it('shows the list', function() {
    if (queryFailed()) {
      this.skip();
    } else {
      cy.get('.list')
        .should('be.visible')
    }

Обратите внимание, что я изменил функцию стрелки в моем it() на function(), чтобы я мог использовать this.

queryFailed() - это функциякоторый проверяет, успешно ли выполнен запрос.

function queryFailed() {
  cy.get('.spin')
    .then($container => {
      const htmlLoaded = $container[0].innerHTML;

      if (htmlLoaded.indexOf('List') !== -1) {
        return false;
      }

      if (htmlLoaded.indexOf('error') !== -1) {
        return true;
      }

      cy.wait(1000);
      queryFailed();
    });
}

Вкратце, если содержимое элемента div, который я жду, имеет «ошибку», то я знаю, что запрос не выполнен, поэтому я возвращаю true, в противном случаеЯ возвращаю false.

Что я вижу в своих тестах после отладки, так это то, что хотя условие работает хорошо, асинхронная природа JS выполняет код в операторе else одновременно с * 1030.*.Таким образом, окончательный вывод выглядит так, как будто условия вообще отсутствуют, поскольку все проверено.

Есть ли лучший способ справиться с этой асинхронной функцией JS?

Ответы [ 3 ]

0 голосов
/ 05 февраля 2019

Я думаю, что вы почти у цели, но вместо синхронного шаблона if () {...} else {...} вам нужен шаблон асинхронного обратного вызова.

it('shows the list', function() {

  const whenFailed = function() {
    this.skip()
  }

  const whenSucceeded = function() {
    cy.get('.list').should('be.visible')
  }

  queryFailed(whenFailed, whenSucceeded);
}

function queryFailed(whenFailed, whenSucceeded) {
  cy.get('.spin')
    .then($container => {
      const htmlLoaded = $container[0].innerHTML;

      if (htmlLoaded.indexOf('List') !== -1) {
        whenSucceeded();
        return;
      }

      if (htmlLoaded.indexOf('error') !== -1) {
        whenFailed();
        return;
      }

      cy.wait(1000);
      queryFailed(whenFailed, whenSucceeded);
    });
}

Однако я отмечаю рекурсивный вызов queryFailed(),похоже, что вы вручную повторяете содержимое вращающегося контейнера.

Cypress имеет встроенные повторные попытки, поэтому все, что вам нужно сделать, это выбрать максимальное время, которое ваш результат может занять (скажем, 20 секунд), иона завершит выполнение команды, как только будет получен желаемый контент, или провалит тест полностью, если это не произойдет в течение 20 секунд.

Кроме того, вы должны контролировать успех / неудачу любого вращателяожидает (например, получение списка через XHR).Таким образом, вы должны разделить тест на два - один для успеха и один для отказа.

context('when the list loading succeeds' function() {

  it('shows the list', function() {
    // Mock XHR success here
    cy.contains('.spin', 'List', { timeout: 20000 });
    cy.get('.list').should('be.visible');
  })

  it('does not show an error message', function() {
    ...
  })

})

context('when the list loading fails' function() {

  it('does not show the list', function() {
    // Mock XHR failure here
    cy.contains('.spin', 'error', { timeout: 20000 });
    cy.get('.list').should('not.be.visible');
  })

  it('shows an error message', function() {
    ...
  })

})

Это немного грубо, так как я не знаю точного ожидаемого HTML-кода или того, что ожидает спиннер,но вы можете видеть, что этот шаблон намного аккуратнее и проверяет все пути контролируемым образом.

0 голосов
/ 24 мая 2019

Я использую адаптированную версию ответа @ NoriSte, в которой все еще регистрируются тесты, но с пропуском:

const maybeDescribe = Cypress.env('SOME_ENV_VAR') ? describe : describe.skip

maybeDescribe('Test suite', function() { /* ... */ })

, а затем аналогичным образом в CI, где я хочу пропустить тесты:

export CYPRESS_SOME_ENV_VAR=
$(npm bin)/cypress run

Мой управляемый источником cypress.json определил SOME_ENV_VAR, поэтому при локальном запуске тесты не пропускаются.

0 голосов
/ 05 февраля 2019

Спасибо за подробное описание!Я предоставляю вам решение для вашего самого первого вопроса

Я пытаюсь выяснить, могу ли я условно пропустить проверку it () в моем наборе тестов и разобраться с его асинхронной природой какхорошо.

Используйте переменную окружения, я сообщу вам о моем решении (фактически использующемся в моем конвейере).

if (!Cypress.env("SKIP_E2E_TESTS")) {
  it(...);
}

и в моем файле package.json у меня естьскрипт, который выглядит следующим образом:

"test": "CYPRESS_SKIP_E2E_TESTS=true npm-run-all --parallel --silent test:unit test:cypress",

Моя цель была такой же, как ваша, я хотел бы отключить некоторые тесты при некоторых обстоятельствах (конвейер CI в моем случае).

Итаквесь тест в состояние вместо условного теста.

Дайте мне знать, если вам нужна дополнительная помощь ?

...