пятница, 13 апреля 2012 г.

Какая бывает автоматизация? Часть первая.

Принесли как-то русским мужикам
на лесозаготовках японскую бензопилу.
Мужики положили под пилу здоровую сосну:
- Вжик - сказала пила
- Ого - сказали мужики и положили под пилу лом:
- Др-рр-рр- сказала пила и заглохла
- Ага!!- сказали мужики и пошли валить
лес двуручными пилами.
Вместо предисловия
Сравнительно недавно в голову залетела очередная шальная мысль о том, что написание того как не надо делать ("грешки автоматизатора") это примерно так же плохо как писать о том как надо делать ("лучшие практики"). Поэтому решил начать писать о том как оно вообще бывает.

В данном tl:dr речь пойдет об автоматизации тестирования в классическом понимании, когда мы так или иначе делаем дамп наших ручных тестов в автоматические скрипты. Про другую автоматизацию когда-нибудь потом, все равно всем хочется "чтобы как пользователь так по экранчику жмакать", а остальное начинает будоражить умы только когда данный подход перестает работать.

Есть много способов это сделать и все они хороши в той или иной степени. О том как можно делать и какие приблемы приходится решать и пойдет речь.

Как мы пишем тесты?
Способов много и ни один из них сам по себе не лучше и не хуже других. Они просто есть и в ряде случаев нам лучше подходят одни, а в ряде случаев лучше подходят другие.

Record + Playback
Древняя как автоматизация тестирования идея - записать шаги пользователя и потом проигрывать их. До сих пор эти "зайчатки разума" тлеют в разного рода коммерческих приложениях, а так же в некоторых не очень коммерческих (Selenium IDE умеет так делать).

Главные бонусы от такого подхода можно почитать в любой брошюрке к вендорскому софту для автоматизации тестирования:
  • Вообще не надо уметь программировать - тупо записал и тупо проиграл обратно
  • Очень легко создавать тесты, бессмысленные и беспощадные
На этом бонусы заканчиваются и начинаются проблемы:
  • Это не тесты, от слова "совсем". Это просто запись, которую мы можем проиграть и она может сможет проиграться, а может не сможет. Если нам понадобятся какие-то проверки (verification point'ы) или особо умное поведение, то придется допиливать
  • Они как правило записывают не все. Да, возможно у вас будет тот самый случай, когда во всем вашем проекте не будет ни единого контрола/события, которое данный конкретный инструмент не может обработать, но зачастую это не так, поскольку технологии шагают семимильными шагами вперед, а производители софта ддля record'n'replay в большинстве своем за ними не очень поспевают
  • Они отлично ломаются. Изменения в пользовательском интерфейсе как правило позволят вам часто и по-многу пользоваться возможностью легко и непринужденно создавать тесты
  • Их сложно поддерживать. У вас не будет практически ничего что вы могли бы переиспользовать в разных тестах. И если тестов будет очень много, то это + предыдущий пункт принесут вам очень много головной боли
  • Нельзя начать тестировать пока нет готового приложения. Вообще. Никак. Тупо потому что нечего записывать
Идея в общем отличная, но, как видим, совсем не годится для масштабной автоматизации и длительных проектов.

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

Отсюда появляются новые плюсы и минусы. Собственно плюсы:
  • Бесплатно. Мы можем взять любой скриптовый язык и начать фигачить тесты
  • Гибко. Нас не ограничивают возможности записывающего софта и создаваемые им структуры
  • Быстро. Не так быстро как просто record'n'replay, но все еще быстро, т.к. просто берем и пишем какой нам вздумается тестовый говнокод в меру наших способностей
И есть набор суровых, непреодолимых для ряда людей/контор препятствий:
  • Надо писать код. Хотя бы как-нибудь. Хотя бы фиговый код. Но надо
  • Они все еще хрупкие. Мы же ничего принципиально нового не придумали, так что проблема с хрупкостью никуда не делась
  • Сложно поддерживать. См. предыдущий пункт
Нормальный подход для небольших и простых задач, но все еще никуда не годится если мы планируем какие-то масштабные проекты по автоматизации.

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

От такого подхода у нас появляется волшебная шляпа и +10000 к ловкости еще одна куча бонусов:
  • Мы наконец-то можем переиспользовать код. Написание новых тестов работающих по уже описанной в тестовых библиотеках функциональности сускоряется в сотни раз
  • Легко поддерживать. Нам теперь не надо перелопачивать тысячи скриптов при изменениях тестируемого приложения, а требуется всего-то починить пару-тройку мест в тестовых библиотечках. Правда это все при условии, что мы не наделали ошибок при попытке структуризовать все наше богатство
  • Писать тестовые библиотечки просто. Не нужно иметь за плечами годы опыта программирования чтобы понять что же написано в тестах, а так же написать свои. Да и с библиотечками, как правило, ничего сложного нет. Опять же - если написать тонны говнокода то этот бонус превращается в тыкву, а мы отправляемся читать про бонусы и минусы предыдущего подхода
Из этих бонусов вытекают логичные минусы:
  • Нельзя взять и начать писать тесты. Нужно сколько-то усилий потратить на написание тестовых библиотечек и все еще нужно уметь программировать
  • Сильно новые тесты требуют расширения тестовых библиотечек. Т.е. придется думать над структурами, писать местами сложный код и так далее
  • Тестовые данные так или иначе вшиты в скрипты, так что для их правки и написания новых опять придется программировать
Метод нормально работает для простых задач. С масштабной автоматизацией возникают проблемы, если кто-то кому надо понимать что же делают тесты не умеет программировать. Да и вообще для не умеющих писать хоть какой-то код метод никуда не годится.

Data-/Keyword-Driven скрипты
Мы просто выносим непосредственно тесты в какой-то мало-мальски пригодный для не умеющего программировать пользователя вид и пишем набор скриптов или полноценный фреймворк, который умеет генерировать из этого автоматические тесты. Делается это все с простыми целями:
  • Не умеющие программировать пользователи смогут писать тесты
  • Мы можем поопилить поддержку автоматических тестов. Не умеющие программировать правят сами тесты, умеющие программировать правят и развивают все что под ними
  • Легко поддерживать и есть куча кода для переиспользования. Т.к. у нас там все же какая-то модульная структура внутри есть
Правда все становится сложнее, из-за чего возникают следующие проблемы:
  • Очень много работы. Для keyword-driven варианта, конечно, есть куча опенсорсных BDD фреймворков, но не для всех
  • Придется допиливать. Время от времени будут возникать хотелки не предусмотренные текущей реализацией и всю эту машинерию придется перепиливать. А для этого нужны будут люди способные в ней разобраться и время
В целом иногда мы можем использовать бесплатные решения. Эти подходы хороши для масштабной автоматизации, но все равно понадобятся люди способные программировать. Для простых задач городить весь этот огород как правило не имеет смысла.

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

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

  • Для некоторых графических интерфейсов это технически сложно (если вообще возможно) достучаться до них при помощи средств автоматизации. В конце-концов эих средств может не быть или они окажутся довольно плохонькими.
  • Тесты получаются хрупкими. И дело даже не в том, что нашествие дизайнеров будет приводить к тотальным изменениям интерфейсов без каких-либо серьезных правок функциональности. Дело в том, что где-то у нас будут возникать проблемы с синхронизацией, где-то сложности с отловом событий. Все это придется закостыливать, а костыли имеют свойство ломаться.
  • Они медленные. За пару секунд на каком-нибудь серверном интерфейсике можно прогнать на пару порядков больше тестов, чем на графическом интерфейсе.
Вариант сам по себе неплох, если у автоматизатора нет возможности или желания вникать в то, что происходит под графическим интерфейсом и работа с этим интерфейсом в принципе реализуема без глобальных проблем (привет автоматизации на symbian!).

Можно тестировать под графическим интерфейсом, т.к. здоровый кусок бизнес-логики именно там. Тесты будут быстрее и надежнее, но не смогут полноценно заменить собой тесты через гуй, т.к.:
  • Графические интерфейсы как правило уже привязаны к бизнес-логике и привязанны корректно, а под ними нас зачастую ждет сложное месиво в котором придется еще и разбираться.
  • Зачастую на графических интерфейсах имеется какая-то функциональность, которая никак больше недоступна.
  • У людей бывает паранойя и им хочется чтобы все было как взаправду, "чтобы как пользователь так по экранчику жмакать". В ряде случаев быстрее сделать чем спорить. Да, вариант плохой, но понять что это плохо в ряде случаев очень сложно.
Если последним пунктом вас никто не пытает, то оптимальным вариантом было бы покрытие основной функциональности под графческим интерфейсом и сравнительно небольшой (не обязательно автоматизированный) набор end-to-end тестов для морды.

К счастью мир не всегда настолько жесток и вам может посчастливиться автоматизировать тесты для приложений без морды. Например API, утилиты работающие из командной строки, серверные интерфейсы и так далее и тому подобное. Их как правило очень легко автоматизировать, т.к. они созданы для машин. В большинстве случаев ваша тестовая библиотека будет представлять из себя тестовый клиент для этих интерфейсов.

Продолжение следует...

3 комментария:

  1. Спасибо большое за статью. Хочу научиться автоматизации и очень интересно как же оно бывает. Попытки записывать ГУИ-скрипты поначалу вдохновили, потом разочаровали. Видимо придется учиться программировать на каком-то языке (каком? есть ли язык "для блондинок"?). Кажется, очень сложно разобраться в этом )

    ОтветитьУдалить
  2. Record/Playback весьма неплох - после того как несколько раз попаришься руками с временем ожидания изменения состояния продукта, начинаешь ценить запись временнЫх меток. :)

    Традиционно языком для начинающих считался питон (в начале века его сравнивали с C/C++ - да, я соглашусь, что он легче!).
    Сейчас появилось много новых интересных языков и фреймворков (а многие фреймворки, писанные под второй питон не работают нормльано в третьем), поэтому выбор снова не очевиден. Я бы посоветовал PowerShell (только для Windows, поскольку работать с *nix через коммандлайновый ssh далеко не всегда подходит).
    Альтернативы - всяческие руби, груви, и многие другие динамические языки.

    Вообще "тестирование для блондинок" хорошо реализуется через высокоуровневые тесты: внизу фреймворк, который производит минимальные действия с продуктом, выше уровнем - фреймворк, который предлагает уже читабельные методы WalkThroughFormN9WithParameters(string operatorName, string password, params getFormData("aaa", "bbb", ccc"));

    ОтветитьУдалить
    Ответы
    1. Record/Playback от проблем с ожиданиями как правило не спасает, т.к. пишет фиксированное ожидание (или не пишет вовсе, что тоже бывает). А руками оно обычно один раз пишется и потом больше не вспоминаешь, т.к. оно в недрах прародителя всех тестов лежит и не отствечивает.

      Про языки все так. Правда по мне так PowerShell в *nix это извращение.

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

      Удалить