Поддерживаемость автоматизированных тестов
@ Ср, 25 июня 2008, 11:52В очередной раз, наталкиваясь на различные публикации по автоматизированному тестированию, наталкиваюсь на мнение людей, что как только упоминается какое-нибудь heavy-weight big vendor средство автотестирования (кстати как правило стараются не называть конкретное средство ), то к нему сразу же привязывается "диагноз" что ли - unmaintainable scripts. Но если упоминается что-нибудь писанное на коленке или представляющее собой некоторую библиотеку, то такой проблемы изначально якобы нет. Я, конечно, склоняюсь к идее, что лучше взять что-то мелкое, но оно будет успешно выполнять поставленные задачи, чем взять что-то здоровое и громоздкое, а потом думать, куда бы его прикрутить.
Тем не менее, подобное сопоставление возможности поддержки тестов и используемого средства мягко говоря некорректно. Кривые руки даже под линейку чертят криво. Соответственно, чтобы сделать тесты поддерживаемыми (а для автоматического тестирования это очень критично), нужно следовать одному основному принципу: одно изменение на один функционал. То есть, если у нас в тестируемом приложении поменялась одна функция (в любом проявлении, как на уровне реализации кода, так и на уровне интерфейса), то тесты обновляются путем внесения изменений в одном месте, именно там, где этот измененный функционал оказывает влияние. Опять же, модель идеальная, но есть вполне конкретные подходы, с помощью которых можно стремиться к этому.
- Корректное оформление кода. С этого все начинается. Чтобы код можно было легко поддерживать, нужно, чтоб его можно было легко читать. Практически для всех основных языков программирования имеются в наличии специальные соглашения по оформлению кода. На худой конец можно разработать свои, если используется что-то нестандартное (например, в SilkTest-e свой встроенный язык с некоторыми специфическими для этой системы элементами). Эти стандарты надо выработать и контролировать их соблюдение (в т.ч. автоматическими способами). Во-первых, так вырабатывается единый стиль, а во-вторых, так можно выявить и по возможности нейтрализовать "паразитов" - сотрудников, которые целенаправленно создают сложно читаемый код, который со временем только эти люди и в состоянии будут править (так подобные люди делают себя незаменимыми). Это плохое явление и с ним надо бороться
- Декомпозиция используемых компонентов. Зачастую при разработке тестов можно поймать себя на мысли, что приходится часто копировать некоторый блок кода. В тестировании это достаточно частое явление хотя бы в силу того, что для тестирования разных компонент все равно есть некоторый общий или схожий набор действий. Соответственно, если мы вот так накопируем код во многих местах и через некоторое время надо будет подкорректировать его, то сделать это придется во всех местах, где этот код встречается. Чтобы избежать подобного, можно этот код вынести в некоторый отдельный модуль (функция или метод), задать варьируемые параметры и в коде уже только вызывать нужный модуль. Сделать это можно практически всегда. Главное, не переусердствовать. Вынос в отдельный модуль в общем случае имеет смысл если некоторый блок кода встречается хотя бы дважды. При этом надо бы подумать над тем, как локализовать этот модуль. Есть модули, специфичные для конкретных тестов (test-specific), есть модули, специфичные для конкретного приложения (application-specific), есть модули, специфичные для конкретной платформы или технологии (platform-specific), а есть общие модули, которые не привязаны ни к чему. Можно выработать определенные критерии, по которым модуль относится к тому или иному классу. Подобная декомпозиция дает несколько преимуществ:
- При изменении работы приложения достаточно изменить тело соответствующих модулей, чтобы во всех местах их вызова выполнялись действия, адаптированные под внесенные изменения.
- Часть функций может быть объединена в библиотеку и переноситься из проекта в проект, что резко снижает затраты на разработку каждого следующего проекта. Чем обширней эта библиотека, тем лучший эффект мы получим. Это важно и весьма огорчает то, что значительная часть проектов по автоматизации, которые мне доводилось наблюдать, в принципе не предусматривала возможность переноса некоторого готового кода на другой проект. Зачастую это связано с тем, что в подобных проектах результат нужен здесь и сейчас, а что будет дальше - это уже не столь важно. Тем не менее, об этом надо задумываться заранее.
- Отдельная проблема с тестированием на уровне GUI - описания окон. При изменениях в приложении зачастую меняется и GUI, соответственно, тесты, которые работают на этом уровне тоже нуждаются в модификации. Наиболее универсальным подходом для оптимизации внесения корректировок при изменении GUI можно назвать абстрагирование логической структуры окон от физической. Принцип простой - формирование описания окон, исходя из того, как вы его воспринимаете визуально, как визуально можете сгруппировать объекты, а не как реально эти объекты выстроены в иерархию. Как пример, в тех же веб-приложениях таблицы зачастую используются для форматирования текста, но визуально при этом они как таблицы не воспринимаются. Например, вы видите форму для ввода логина/пароля и визуально воспринимаете только поля ввода, а также кнопки. И вам все равно, что они все выравнены с помощью таблицы. В данном случае таблица в себе функционала не несет. Соответственно, нам надо описать структуру объектов так, чтоб было главное окно, а его дочерними элементами были поля ввода логина/пароля и кнопки.
В некоторых средствах есть встроенные возможности подобной организации, в некоторых средствах над этим надо серьезно поработать. Наиболее трудно будет при работе со средствами, которые не поддерживают ООП, так как окна соответствуют объектам и в той же процедурной форме иерархию описать трудно. Но если поддерживается ООП, то классы-обертки будут весьма полезны
По мере возможностей постараюсь каждый из пунктов осветить на практических примерах с использованием конкретных средств. Это полезно и другим, чтобы они смогли увидеть, что можно сделать имеющимися средствами. Это полезно и мне, так как на целый ряд вопросов я уже устал отвечать, затягивая одну и ту же песню снова и снова. Так что реальные примеры всегда будут полезны
P.S.: в описании специально не привязываюсь к конкретным средствам, так как подходы, озвученные здесь, являются общими даже не только для автоматизации тестирования, но и для программирования в целом.
P.P.S: надо будет как-то перевести этот пост на английский и пустить в народ, а то видать у многих использование heavy-weight big vendor tool прочно ассоциируется с record-n-play без возможности пойти другим путем. Пора бы как-то проталкивать идеи, а то слишком много развелось специалистов, которые всерьез думают, что если они научились записывать действия, то они стали крутыми автоматизаторами (как минимум денег они наверняка запросят в надлежащем количестве)
