Pull to refresh

Comments 23

+ в карму за уровень бизнес-логики ) Этого мало кто делает, а пользы от этого уровня немеренно.
А что будете делать когда в игру встепит и iOS?
Благодарю)
На самом деле, хотел все реализовать на Appium, тогда тесты и часть бизнес-логики можно было бы переиспользовать для iOS. Но не получилось договорится со всеми заинтересованными сторонами… Решил пока попробовать так, это лучше, чем месяцами спорить про инструменты.
А когда дойдем до iOS, будем дальше думать.
Интересно, как бы вы это делали (переиспользование для iOS). А как раз щас это делаю.
Месяцами спорить — это, конечно, не выход. Но когда зайдёт iOS, то дальше думать будет просто долго. У меня первые 24 теста спортировались с андроида на яблоко меньше чем за пол дня с минимальными усилиями и работают одинаково. С UIAutomator-om так быстро не получится.
Уровень с тестами был бы одинаковый, различия только в бизнес-логике (возможно, частично) и page object. Создаем свой класс для каждой платформы — TestApplicationAndroid и TestApplicationIOs, если есть общие методы, то выделяем их в родительский класс. Тесты запускаем с параметром (название платформы) и добавляем логику в setUp() — какой класс использовать для переменной myApp.

А как вы портировали тесты на iOS?
Я делаю через dependency injection. Уровень бизнес-логики (сервисы) получает готовый объект пейджи и от платформы зависит какая именно пейджа попадёт в конструктор сервиса. Таким образом уровень сервисов тоже не меняется, пока имплементация бизнес логики одинаковая для обоих платформ. + структура получается понятной и прозрачной. Выходит гибко и расширяемо.
Есть ассемблер сервисов, который знает из каких частей собирать каждый конкретный сервис. Все классы с пейджами и сервисами собираются в один объект динамически и передаются в этот ассемблер. В случае с айосью я беру из объекта с классами дженерик классы и классы специфические для платформы и мёржу их. Таким образом, если есть разница в локаторах, к примеру, то нужно в папке ios создать класс, унаследоваться от дженерик класса и описать разницу. Всё. Дополнительно собирать или что-то куда-то передавать уже не надо.
Если интересно, то здесь есть демо проект на TypeScript. Пока, правда без доков. В обозримом будущем планирую добавить.
«Данный подход хорош тем, что мы не делаем ничего лишнего — фреймворк построен на столько, на сколько это нужно для работы тестов. Можно сказать, что это концепция MVP в тестировании»
Можно сказать, что это TDD)
Я бы сказал BDD. Имея уровень бизнес-логики мы не грарантируем, что будем писать тесты до кода приложения, но это даёт нам возможность абстрагироваться в тестах от имплементации и использовать более высокоуровневые методы.
Вот не знаю я. Я переодически размышлял над тем, чтобы впилить поведенческий уровень. Имея такой уровень можно действительно описывать тесты более высокоуровнево.
Но я вижу одну сложность.

У нас получается вместо одного интерефейса — два. Интерфейс самого PgO и интерфейс бизнес компоненты которая инкапсулирует поведенческие сценарии. Мы получаем необходимость поддерживать больше кода. И когда в PgO интерфейс ясен — он является производной элементов управления страницы, то для поведенческого уровня необходимо по каким-то лишь создателю известным критериям придумывать, какие поведенческие цепочки собрать вместе. В итоге то, что этот тест на самом деле делает скрывается от читателя теста за абстрактыми вызовами сценарных методов. Что значит «залогиниться на сайте»? Что значит «удалить пользователя»?

Все «как сделать» скрываются и подменяются на «что сделать».

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

А теперь представьте, у меня в тесте было бы написано что-то вроде:
«залогинься на странице»
«добавь в корзину два предмета»
«выйди из системы»
«залогинься на странице»
«проверь что корзина не пуста»

Допустим баг в том что, корзина как пуста, после выхода ничего не сохранилось.

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

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

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

Все дело в том, что натуральный язык как ни крути неоднозначен. А человек еще и работает в контексте своего ограниченного понимания и своего видения. Ну и невнимательность присущая всем в большей мере или меньшей.

И вот в итоге мне трудно найти доводы в пользу слоя бизнес-логики на человекопонятном сценарном языке. Какая практическая польза от этого? Его приходится расшифровывать. А зачем когда можно все читать в оригинале, так сказать.

Какие аргументы вы ложите на другую чашу весов, чтобы можно было оправдать введение такого слоя?
Все «как сделать» скрываются и подменяются на «что сделать».

В этом и вся фишка.
Я переодически размышлял

Попробуйте разок сделать и посмотреть на сколько это удобно вам. Я вообще не представляю, как без этого ) На столько упрощает жизнь, чтоб я б даже не поверил, если б мне раньше сказали )
А теперь представьте, у меня в тесте было бы написано что-то вроде:
«залогинься на странице»

А теперь представьте, что у вас каждый из 873-ёх тестов выполняет логин и логика логина поменялась. Что будете делать? В этом как раз вся изюминка, что вы меняете 1 метод логина и не запариваетесь. А тесты меняются только когда меняется high level бизнес логика. Я когда первый раз воспользовался таким подходом, то диву давался на сколько мало изменений нужно делать, чтоб всё снова заработало.
А на счёт абстракций, то у меня 4 уровня — Page elements, page objects, page actions и services. Так вот это очень удобно, когда вся сложная логика реализована внизу, а сверху и мануальщики писать могут. Я, кстати, проводил эксперимент. Посадил мануальщика, который знает JS на уровне могу объявить переменную. Дал ему пустой тест и сказал — у тебя есть слово service, вперёд. Парень написал тест.
Если бы тест был написан на голых PgO то из теста читалось бы напрямую

1. Если перейти внутрь метода сервиса, то там английским по дракуле написано, чего он делает.
2. Ещё удобней — логгируйте всё, что делаете. Я в тесте даже не знаю каким юзером я буду логиниться, а от этого многое зависит и всё от того, что я не хочу их хардкодить. У меня есть объект с описанием юзеров (что у кого есть) и юзер сервис, которому я в тесте говорю — выбери мне юзера блондинку с третим размером. А в логах я вижу какая блондинка мне попалась, какие у неё креды и все действия, которые она делала пошагово со всеми данными.
В говорите, что товары, которые нужно положить в корзину, прописаны хардкодом в методе? Это по определению плохо. Вместо «добавь в корзину два предмета» нужно сделать «добавь в корзину предмет»(«название предмета»). И в тесте явно указывать название: myApp.addProductToCart("Яндекс.Станция");
С первой половиной полностью согласен, со второй не полностью )
Тесты не должны знать про тест дату. К примеру нужно добавить товар дороже, чем 1000. 1000 для нас — сумма при которой доставка бесплатно.
Плохо:
addExpensiveProduct() — внутри метода зашит продукт
Лучше:
addProduct(teslaModelS) — дженерик метод не знает про данные, данные передаются в тесте
Хорошо:
addProduct(helper.findProduct.costsMore(testData.freeDeliveryCost)) — ни тесты, ни метод не знает про дату. Если сумма для бесплатной доставки меняется — она меняется в одном месте.
Если не секрет, какое у Вас приблизительно количество PageObject классов? И наверное мне еще интересно сколько у вас пользовательских сценариев?
Просто у нас нетипичное приложение которое пишется на заказ (т.е требования составляем не мы), это не веб, не десктоп и не мобайл. Мне не с чем сравнивать, чтобы понять как у нас обстоят дела. У меня их около 80 штук. Из них составлено около 170 тестовых последовательностей. Сценариев у нас нет. Вот и вопрос, стоит заморачиваться и определять сценарии и писать обертки? Исходя из того, что эта работа — разработка сценариев и написание оберток — это время которое не будет потрачено на написание новых проверок, анализ найденных ошибок в приложении, заведение багрепортов и пр.
Я меньше месяца работаю над этим проектом. У меня Android и iOS, generic пейджей 14, platform specific по 2, тестов 25.
у нас нетипичное приложение которое пишется на заказ (т.е требования составляем не мы)

А бывает по-другому ;) Я 1 раз только работал на продуктовом проекте. Всё остальное — аутсорс, аутстаф, где нетипичное приложение и требования не у нас.
Тут суть не в обёртках, а в том, чтоб было гибко и расширяемо. Как именно это делать — дело каждого. Если ваше решение отвечает SOLIDам и вы спите спокойно по ночам — то это то, ради чего стоит ходить на работу )
А бывает по-другому?
У нас даже интерпретатор питона самописный, потому, что у него отпечаток по памяти меньше. К нему и библиотеки никакие не прикрутить — нет полной совместимости синтаксиса. И «фреймворк» вокруг него умеет в основном только найти виджет в дереве и нажать на него, все остальное нужно писать самому. Так что с одной стороны нам нужно больше абстракций, с другой стороны «при таких делах» не знаешь стоит ли заморачиваться. У меня каждый десятый багрепорт/таск не на продукт а на тест-фреймворк. Коммьюнити нет, каждый подрядчик сам за себя. Фреймворк пишут два человека у которых он предпоследним приоритетом, потому что есть более важный для заказчика проект.
Может от этого ощущения неясности у меня и не доходят руки написать красивые абстракции — когда знаешь, что как красиво не городи — баги во фреймворке и продукте не дадут тебе почувствовать удовлетворенности от проделанной работы. Будет только ощущение потраченного времени и набранного опыта по написанию абстракций.
Хех, могу только посочувствовать, это, конечно, дичь ) Одно могу сказать — чем лучше ваш код — тем легче адаптироваться к изменениям в коде говно-фреймворка.
Да, это сильный аргумент. Спасибо.
Недавно последил за тем, что я делаю и почему. У нас в приложении встречаются проблемы которые для человека невоспроизводимы, но автомат на них падает. Трудно даже сказать что это именно, события нажатия, анимации, системные вызовы попадают в какой-то тайминг и получается что скрипт по сути правильный но он не работает. Нужно найти тот метод который работает нестабильно и заменить его на что-то другое, или костыль. Начинаешь воспроизводить скрипт построчно через консоль (дебаггера нет, у нас самопальный интепретатор питона как я говорил): создаешь экземпляры пейджей и запускаешь метод за методом, постепенно локализуя ту точку вызова в которой скрипт работает ненадежно. И получается, что для дебаггинга мне проще все вызовы явно вытащить в тело теста чем прятать их в абстракциях. Так что я думаю мой подход обусловлен именно этим.
Мне обычно хватает логов, чтобы понять где проблема. Если по логам не понятно — это значит, что логов не хватает.
Но я как-бы не агитирую за какой-либо подход ибо не варил на вашей кухне.
Вы используете UI Automator. На Ваш взгляд он имеет значимые преимущества над Espresso?
UI Automator имеет больше возможностей взаимодействия с ОС, например, может включить wi-fi. Espresso взаимодействует только с одним приложением, но немного удобнее и проще. Прочитайте сравнения, их полно, и выбирайте из ваших потребностей.
Добрый день. Только постигаю азы автоматизации. А как быть если не у всех необходимых элементов есть уникальные id? Например, в приложении есть таб-бар для навигации и у всех его элементов одна и та же id, потому что элементы возвращает бекенд. Как в этом случае к ним обращаться? Пример: monosnap.com/file/T8DPOCdTqJxajAKRA5ec901nTci1ps
Ответ до боли прост — это локаторы надо добавить. Либо самому либо просить девелоперов. Второй вариант гораздо хуже, ибо они не отстреливают, что именно и куда надо, сильно не хотят этим заниматься и всё время забывают и откладывают )
Sign up to leave a comment.

Articles