Pull to refresh

Comments 17

Не думал что такие очевидные вещи ещё и объяснять надо )

Часто очевидные для разработчиков вещи не столь очевидны для тестировщиков) Благодарю за комментарий

Отказались от Cypress в пользу Playwright, скорость и стабильность значительно выше у последнего!

Пункт 7 - итоговый код гораздо менее понятен, чем просто последовательный вызов методов Cypress.

Пункт 9 - вообще какой-то лютый антипаттерн. Все запросы (queries) Cypress под капотом повторяются до успешного результата или таймаута. Непонятно, какую проблему решает тут цикл.

Остальные пункты - по сути вариации одной и той же идеи - параметризированые тесты.

в целях обеспечения их надежности и сокращения времени на их выполнение

Ни надежность, ни время выполнения в статье так и не раскрыты остались.

Пункт 7: что означает в данном контексте "просто последовательный вызов методов"? при заполнении формы состоящей из множества полей и других элементов намного проще имея например объекты с селекторами элементов и тестовых данных пройтись циклом используя внутри switch/if-else, чем прописывать последовательно методы для каждого элемента при этом повторяя одни и те же методы. это не сократит время на обработку формы, зато очевидно намного сократит код.

Пункт 9 - соглашусь, отработка случаев, касающихся ожидания появления элемента, таким способом не есть best practice. определение подходящего таймаута решает задачу гораздо проще. учитывая это, я намеренно указал в тексте, что данный способ не является лучшим решением для рассматриваемого примера.

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

Сокращение количества тестов за счет использования циклов очевидно сокращает общее время на прогон конкретного тест-сьюта (особенно с учетом уменьшения количества запуска before/after conditions). В отношении надежности соглашусь, что прямая связь неочевидна, в то же время сокращение кода при оптимизации позволяет предотвратить ошибки в случае дублирования кода в одинаковых по своей сути тестах, и ускорить обработку ошибок в случае ненадежности тестов.

В целом благодарю за замечания.

просто последовательный вызов методов

cy.get('#input1').type('some value')
cy.get('#button1').click()
cy.get('#input2').type('another value')
cy.get('#checkbox3').click()

По-моему, поддерживать такой тест гораздо проще, чем набор if/else

Сокращение количества тестов за счет использования циклов очевидно сокращает общее время

В ваших примерах количество тестов не сократилось.

for (let user of users) {
  it(`test for user ${user.name}`, () => /* ... run assertions */)
}

в этом коде все так же 3 теста, как было бы и без цикла.

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

Опять же, не совсем так. Чтобы не дублировать шаги от теста к тесту, их рекомендуется выносить в переиспользуемые команды (доступные в неймспейсе cy ) или просто обычные функции. Но в примере, приведенном в статье, это выглядит как ненужное усложение простого, в сущности, теста. Возможно, у вас был какой-то другой случай на примете, где это действительно могло иметь смысл.

я не касался в статье кастомных команд и хэлперов, смысл которых очевиден. я указывал что циклы это один из способов оптимизировать код. и что мешает например использовать цикл внутри такой функции, разделяя по кейсам различные команды:

 const fillForm = (selector, dataTest) => {
            for (let key in dataTest) {
                switch (key) {
                    case "element1":
                    ...
                    case "elementN": {
                        clickOnEl(selector[key + 'Button']);
                        clickRandomFromList(selector[key + 'List']);
                        break;
                    }
                     case "elementN+1":
                      ...
                     case "elementN+M":
                      {
                        clickOnEl(selector[key + 'Button']);
                        clickOnDropdown(selector[key + 'List']);
                        break;
                    }
                    default: {
                        inputText(selector[key], dataTest[key]);
                    }
                }
            }

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

в статье описан лишь принцип на самом простейшем примере.

оглашусь, отработка случаев, касающихся ожидания появления элемента, таким способом не есть best practice.

Нет. Это не просто "не best practice". Этот цикл принципиально не делает то, что, согласно статье, он должен бы делать. Он не увеличивает таймаут в MAX_RETRIES раз, он не проверяет наличие MAX_RETRIES последовательных спиннеров. Он делает тест менее надежным - в зависимости от логики страницы он может иногда падать из-за того, что ассерты в Cypress асинхронные.

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

Использовал циклы некоторыми описанными способами, в целом юзфул

Sign up to leave a comment.

Articles