В наше время в мире 1С многие ИТ-отделы крупных компаний внедряют автотесты. Пытаются это делать и небольшие компании. Увы, не у всех получается прийти к заветной цели – чтобы автотесты именно минимизировали ошибки, а не множили проблемы. К сожалению, пока нигде не описан простой и понятный рецепт «Как внедрить автотесты на предприятии без проблем», поэтому большинству приходится учиться на собственном опыте.
Начинается эта история у большинства стандартно: сейчас научим несколько сотрудников писать тесты на Vaness’е, потом напишем фичи (от «feature» – расширение сценариев автотестов) вообще на все процессы – как на собственные, так и на типовые - и наступит на предприятии счастье: все функциональные блоки будут автоматически проверяться, ошибки в рабочую базу отныне не попадут и т.д.
Но на практике многих ожидают сюрпризы:
Бывает и так, что после двухлетней разработки 150 тестов компания понимает, что от их «внедрения» проблем стало больше, чем было. И вот только теперь команда поняла, какая должна была быть правильная структура автотестов, и теперь требуется всё переписать заново.
А можно ли заранее учесть чужой опыт и пойти сразу верным путем?
На текущий момент нет стандартов написания автотестов и заведения для них тестовых данных, описанных где-нибудь на ИТС. К тому же всё индивидуально от клиента к клиенту: разная специфика проверяемых бизнес-процессов, заведения тестовых данных, особенностей процесса разработки т.д. Но тем не менее выделить общие «грабли», на которые наступают довольно многие, можно.
В данной статье мы попытаемся поднять на поверхность подводную часть айсберга по важнейшему вопросу, с которым сталкиваются все, кто начинает внедрять автотесты: а насколько большим должен быть сценарий автотеста?
Для ответа на данный вопрос выделим два типа автотестов:
Такие сценарии подготавливают все необходимое (НСИ, остатки и т.д.) сами для себя. Случается, что после выполнения они даже приводят тестовую базу в исходное состояние, избавляясь от «мусора». Такие тесты запускаются произвольное количество раз подряд на любой копии базы без предварительной подготовки. Но при этом:
Некоторые компании используют один из двух вариантов в чистом виде, кто-то ищет золотую середину. Ну а мы считаем, что главное – это уметь взвесить «за» и «против» обоих подходов применительно к вашим условиям и целям, знать о существовании подводных камней на каждом из выбранных путей. В данной статье попытаемся пролить свет на этот не очень прозрачный выбор, рассмотрев плюсы и минусы каждого из двух типов автотестов «в чистом виде», т.е. в крайностях: самые длинные и самые короткие.
Прежде чем сравнивать два перечисленных типа автотестов, стоит кратко определить для каких целей мы собираемся их внедрять и каким образом использовать. Вообще это тема отдельной статьи, поэтому здесь лишь зафиксируем тезисы без объяснения того, как мы к этому подошли. В противном случае, без целеполагания, сравнение типов автотестов будет непрозрачным.
Проверка небольшого числа основных наиболее критичных для бизнеса процессов, ошибки в которых не должны быть пропущены в рабочий контур ни при каких обстоятельствах. Это могут быть процессы, которые:
Разово перед релизом в прод. Запуск вручную пользователем всех сценариев в один поток на подходящей тестовой базе, на которую накатили релизную конфигурацию.
1. Автоматизированный прогон тестов. Из-за их большого количества прогон может осуществляться в несколько потоков. Способы управления потоками могут быть разные:
2. Прогон автотестов на различных вариантах тестовых баз (на эталонной базе, на файловой базе разработчика, на копии серверной базы и т.д.) с автоматизированным накатом проверяемой функциональности (из ветки GIT, по указанному пути к конфигурациям/расширениям, с извлечением конфигураций из указанных баз, где выполнялась разработка и т.д.).
Для сравнения двух типов автотестов давайте обозначим тестируемый сценарий. Пусть наш автотест будет проверять оформление продажи простого товара «Мяч» за 1500 руб. (без особых сложностей в учете типа маркировки и т.д.)
Под независимыми автотестами подразумеваем самодостаточные автотресты, которые сами подготавливают для себя все необходимые данные и вследствие этого могут запускаться произвольное количество раз на любой копии базы. Здесь не нужно думать о том, как вычистить «мусор» из базы после прогона теста, практически не нужно заботиться о том, какие данные в базе уже заведены. Зачастую такие тесты даже сами для себя устанавливают необходимые значения констант. Фиксируем главный жирный плюс – это универсальные тесты, которые можно запускать произвольное количество раз на любых копиях баз.
Рассмотрим тестовый сценарий, на который будем ссылаться в дальнейшем в этой статье.
1. Подготовительные шаги:
2. Основные шаги:
a. оформить продажу:
На практике подготовительных действий для осуществления продажи может понадобиться намного больше ввиду длинной цепочки закупки или производства, наличия маркировки, взаимодействия с ЕГАИС, необходимости создания характеристик и серий, согласования заказа и т.д. В данном случае мы сознательно упрощаем этот процесс, поскольку детали в нашем случае не так важны. В реальных же процессах подготовительных шагов может быть 20, а шагов непосредственно сценария, который требуется протестировать всего два. Таким образом, подготовительные действия в независимых автотестах вполне могут занимать 70–90% от общего объема сценария.
1. Создание номенклатуры:
3. Оформление Заказа клиента:
4. Оформление и проверка продажи (основная часть сценария):
Конечно же, это лишь часть примеров тех ошибок, которые могут возникнуть по проверяемому процессу на реальных данных, на практике их может быть намного больше. Совершенно безобидные изменения в одном функциональном блоке зачастую приводят к неожиданным ошибкам в других блоках. Но из приведенного примера следует важный промежуточный вывод: ввиду того, что подготовительные действия в тестовом сценарии занимают 75% от общего объема сценария, то шанс , что наш автотест «упадет» на подготовительных действиях, а не на самой продаже, которую требовалось проверить, в 3 раза выше.
Может показаться, что это даже и хорошо, что автотест по проверке продажи дополнительно проверяет еще и формирование номенклатуры, закупки и заказа. Больше спектр выявляемых ошибок – меньше шансы «пронести» ошибку в рабочую базу, не так ли? Но далеко не всегда требуется просто «не пропустить ошибку», зачастую нужно распределить большое число ошибок по функциональным блокам, чтобы понять общий масштаб проблем тестируемой конфигурации. И не обязательно выполнять проверку формирования номенклатуры, закупки и заказа именно в составе автотеста по продаже. Это можно сделать отдельными сценариями, и ошибка все равно не попадет в прод.
Рассмотрим пример: есть 50 основательных независимых автотестов, которые для разных типов товаров/контрагентов проверяют работу основных функциональных блоков предприятия: склад, закупка, производство, продажа, казначейство. И все они выполняют шаги от А до Я, как рассмотренный выше автотест по продаже, т.е. сами для себя готовят НСИ, остатки и прочее и только потом выполняют основное проверяемое действие.
Допустим, мы собираемся перейти на новый LTS релиз от вендора, понимаем, что ошибок будет много. Команда подготовила черновую конфигурацию нового релиза: перенесли и адаптировали все доработки, победили ошибки основных и отложенных обработчиков обновления. Теперь нужно выявить неочевидные ошибки в самых важных для предприятия процессах, чтобы на самые «проблемные» блоки выделить больше ресурсов разработчиков и тестировщиков для исправления. Обновление серьезное, разнообразных ошибок, предположим, будет никак не меньше 100. Как же хорошо, что на все функциональные блоки есть такие крутые автотесты. Сейчас запустим на любой копии с загруженной конфигурацией чернового релиза и раскидаем ресурсы команды по функциональным блокам для исправления! Звучит хорошо.
Запускаем автотесты. Да, запускаем их на любой копии базы – действительно удобно, ведь они независимые и сами для себя готовят все данные. Но дальше, скорее всего, нас будет ждать разочарование:
В результате цель «быстро увидеть все типы ошибок и распределить ресурсы на их исправление по функциональным блокам» не достигается, потому что независимые автотесты слишком восприимчивы к любым ошибкам и чаще всего «падают» не там, где ожидалось. Исправление превращается в длинную череду итераций: исправили очередную ошибку и снова запустили все тесты (которые выполняются не за 10 минут). А затем продвинулись к следующей «общей» ошибке.
Как же избежать такой проблемы? Если проанализировать лишь общую ошибку создания номенклатуры, то ее можно было бы решить созданием отдельного автотеста, который проверяет именно создание номенклатуры по всем возможным вариантам. А остальные автотесты могут не создавать себе каждый раз новую номенклатуру, а находить и использовать уже имеющуюся в базе. В этом случае упал бы именно этот тест, который проверяет создание номенклатуры, и это было бы информативно, потому что как раз этот момент и проверялся. Ну и таким же образом все «общие» действия могут быть вынесены в отдельные сценарии, чтобы каждый сценарий падал именно там, где его падение и ожидалось. Конечно, здесь появляется много различных проблем с подготовкой данных и перезапуском тестов, об их решении поговорим при обзоре второго типа автотестов – зависимых от данных.
Функциональные возможности Vaness’ы непрерывно растут, добавляются новые конструкции языка описания сценариев. Конечно, замечательно, если пишущие автотесты специалисты знают и владеют всеми этими фичами, следят за обновлениями. В этом случае они способны писать большие и сложные автотесты, которые, условно, могут воспроизвести любые действия пользователя в базе. Но насколько это оправдано делать без веской необходимости?
Очевидно, что большие и сложные автотесты пишутся дольше, чем маленькие. Независимым автотестам приходится создавать элементы НСИ, заказы и прочие подготовительные объекты, «запоминать» их в переменные и затем на их основании уже выполнять основные шаги автотеста. Тест получается длинный, разнообразных шагов много, все это требует максимальных компетенций от разработчика автотестов.
Зачастую в компаниях нет отдельных сотрудников, которые занимаются исключительно разработкой автотестов. Сценарии могут писать «по совместительству» консультанты или программисты. И это даже порой удобно: консультанты хорошо понимают предметную область, а программисты – применимость автотестов к проверке разрабатываемой функциональности и процессу разработки. Но такие специалисты обычно не очень глубоко погружены в нюансы работы Vaness’ы, им сложно выделять достаточно времени на написание длинных и сложных автотестов. Вот внести несложные правки в простые уже написанные тесты – это они смогут.
Ну а если специалисты по автотестам и имеются, то сколько их в штате: достаточно ли для того, чтобы непрерывно поддерживать эти длинные и сложные автотесты? Если 75% от объема автотестов, это подготовительные действия, то:
Аллюр (отчет о выполнении автотеста) – это не только информация о том, пройден автотест или нет. Это еще и способ быстро найти и воспроизвести ошибку, исправить ее. Аллюром могут пользоваться консультанты и программисты, которые с помощью автотестов отлаживают новую функциональность. Если структура автотеста лаконичная и понятная, сценарий отражает шаги процесса и в нем нет ничего лишнего и отвлекающего, все служебные действия вынесены в библиотечные экспортные сценарии, то в таком случае, пройдясь взглядом по аллюру, можно быстро понять, где ошибка и как ее воспроизвести. Может быть даже в той же базе, в которой выполнялся автотест.
Если тест сложный и длинный, в нем много различных служебных и подготовительных действий, то в этом случае анализировать его, скорее всего, будут именно те специалисты, которые его разрабатывали, потому что «сложно и ничего непонятно», а все остальные будут пользоваться им только для понимания «прошел автотест или нет».
Если автотестов много (50 и больше), то выполняться последовательно они могут довольно долго. Если наша цель разово проверить конфигурацию перед накатом на рабочую базу, то в таком случае, может быть, они успеют пройти за ночь перед релизом, и с утра мы увидим зеленый аллюр.
Но если у нас разнообразный набор devops-инструментов, который позволяет запускать автотесты в автоматическом режиме на различных базах и конфигурациях, в том числе и для того, чтобы разработчик после очередной разработки смог сам себя проверить, то в этом случае нам хотелось бы, чтобы все тесты были выполнены максимально быстро. На помощь, конечно, придет многопоточность и параллельный запуск автотестов. Сейчас не будем углубляться в данный аспект, поскольку это тема отдельной статьи. Просто представим, что с devops у нас полный порядок, используется «инфраструктура как код» и мы можем опционально настроить запуск всех 50 автотестов в 50 потоках, чтобы как можно быстрее получить результат их выполнения.
В этом случае общая длительность прохождения всех тестов будет равна длительности выполнения самого тяжелого сценария. А если у нас все сценарии тяжелые и 75% их объема относятся к подготовительным этапам, то делаем простой вывод – все наши автотесты будут выполняться в 4 раза дольше из-за того, что они включают в себя подготовительные этапы.
Давайте разовьем тему нанотехнологий и автоматического многопоточного запуска большого числа автотестов в условиях передового devops-окружения. Этим активно пользуются и разработчики, и консультанты в том числе. Удобно же: если разработал новую функциональность, то зачем тратить время на ручное тестирование? Пусть сначала машина проверит, что не сломалась старая функциональность. Закончил разработку, запустил все автотесты, ушел на обед, посмотрел аллюр-отчет, и отправился со своим кодом либо в релиз, либо на исправление ошибок. И вот если мы до такого эволюционировали – а это по-настоящему удобно и это не фантазии автора, это применяется на практике – то мы столкнемся с финансовой составляющей этого удобства.
Допустим, при включенной настройке максимально быстрого прохождения автотестов, алгоритм развернет на каждый из 50 сценариев свою отдельную виртуальную машину и запустит на ней ровно один предназначенный для нее сценарий. А в конце просто «соберет» результаты выполнения всех сценариев с каждой виртуальной машины в общий аллюр-отчет. Мы столкнемся с проблемами в том случае, если в команде много специалистов, запускающих полный пакет автотестов (в условиях сжатых сроков разработки) в таком супер-параллельном режиме, когда каждый разработчик запускает все автотесты не один раз в день. В этом случае мы можем заплатить за тысячи часов работы машин, исполняющих автотесты (пусть даже и не виртуальных, при наличии большого парка физических машин). Это стоит денег. А теперь вспомним, что у нас 75% от общего объема сценариев занимает подготовка данных. Получается, все наши автотесты могли бы работать в 4 раза быстрее, и мы могли бы сократить затраты на железо в 4 раза? Да, получается так. >
Обозначим гипотезу: любой длинный сценарный автотест можно разбить на много маленьких сценариев без потери качества выполняемой проверки.
Ключевое отличие в том, что здесь каждый автотест использует заранее подготовленные для него данные в эталонной базе, а не создает их сам. Каждый сценарий проверяет ровно то, что должен проверять. О плюсах и минусах такого типа автотестов поговорим ниже , а сейчас обсудим главное – будет ли результат проверки четырех отдельных сценариев с различными данными равен результату проверки одного длинного сценария, включающего в себе те же самые шаги, но где каждый последующий шаг использует результат предыдущего?
В жизни ведь так и происходит: один и тот же пользователь не выполняет все четыре шага – этим занимаются различные отделы. Отдел, который оформляет продажу, просто использует товарные остатки в базе, которые являются результатом работы отдела закупки; а те, в свою очередь, используют номенклатуру, которую подготовил отдел НСИ. В реальных процессах это также разные сценарии, выполняющиеся под разными пользователями.
Наверняка есть такие случаи, при которых четыре отдельных сценария, использующих разные входные данные, пропустят ошибку, которую бы не пропустил единый «сквозной» сценарий. Но, наверное, они крайне редки, если никак не приходят на ум сходу. И, условно, будем считать, что озвученная гипотеза – это теорема. Еще раз: в подавляющем большинстве случаев любой длинный сценарный автотест, выполняющий несколько шагов, можно разбить на отдельные маленькие сценарии без потери общего качества выполняемой проверки. И от этого даже будет много плюсов!
Поскольку мы рассматриваем крайности, то наши «зависимые» от данных автотесты должны быть максимально облегчены. Не будем их загружать шагами по приборке мусора за собой (удаление созданных элементов НСИ, документов и т.д.). Давайте просто вообще не будем решать эту задачу «повторного запуска автотестов». У нас есть небольшая легковесная эталонная база, которая хранится в виде DT файла, она разворачивается за пару минут на нужную базу, на ней прогоняются автотесты, и… А какая нам дальше разница что там тест оставил после себя? Если требуется разобрать ошибки по аллюр-отчету – мы её сохраним и изучим, а если ошибок нет – мы же просто можем перезалить в эту же базу DT заново и снова запустить автотесты! Эталонные базы – это легковесные базы, которые быстро разворачиваются и нужны только для однократного прогона автотестов; для повторного прогона сценариев они перезаливаются.
Только необходимые: чем проще и короче сценарий – тем лучше.
Представим, что совместно с продажей нам не надо проверять предшествующие ей создание номенклатуры, оформление закупки и заказа. Почему? Ну, допустим, потому что в определенной компании эти блоки полностью типовые и с ними проблем не бывает, а вот блок продаж «перепилен» вдоль и поперек, и там проблем хоть отбавляй. В этом случае с любого ракурса будет намного проще один раз в эталонной базе создать номенклатуру, закупку и заказ, а сценарий автотеста будет состоять из примитивнейших действий: найти конкретный «Заказ клиента №456», создать на основании РТУ, провести, проверить движения. Просто, быстро, эффективно. При использовании эталонных баз всегда проще проектировать автотесты таким образом, чтобы они по максимуму использовали заранее подготовленные для них данные, не выполняя лишних действий в сценарии.
При этом лучше всего, если для каждого сценария будут подготовлены «личные» данные: НСИ, остатки и т.д. Потому что гарантированно возникнет ситуация, когда бизнес-процесс поменялся, и для адаптации определенного сценария автотеста нам придется изменить в эталонной базе реквизиты номенклатуры, заказа или чего-то еще. И при этом другие сценарии не должны пострадать.
А если нам все-таки надо проверять и создание номенклатуры, и закупку, и оформление заказа? В этом случае это просто должны быть отдельные сценарии. И чтобы ни сейчас, ни в будущем нам не решать задачу последовательности их выполнения – каждый сценарий должен быть независим друг от друга: свои НСИ, свои остатки и т.д. В таком случае эти сценарии можно запускать хоть последовательно, хоть параллельно, хоть одновременно в одной тестовой базе, хоть «поднять» под каждый сценарий свою базу – неважно, результат будет одинаковым. Поэтому чем более они обособленные, тем с меньшим количеством проблем мы столкнемся в будущем.
Если какой-то сценарий можно разбить на подчиненные сценарии, потому что там могут быть свои особенности и ошибки – надо этим пользоваться. Например, проверяемая продажа. Должен ли сценарий создавать РТУ на основании Заказа клиента и проводить? Казалось бы, действие не сложное. Но давайте подумаем, какие тут могут быть вложенные сценарии:
Давайте еще раз вернемся к рассмотренному выше примеру:: мы выполняем большое обновление на новый релиз вендора, готов черновой релиз, ожидаем увидеть 100+ ошибок, имеем 50 написанных автотестов по всем важным функциональным блокам, хотим быстро понять «масштаб бедствия». Отличие на этот раз в том, что все 50 автотестов атомарные, выполняющие строго минимальные набор действий: что проверяем – то и делаем, не больше. Все НСИ, остатки товаров, взаиморасчетов и т.д. – всё заранее заготовлено в эталонной базе, мы на нее накатили черновой релиз, прошли основные и отложенные обработчики обновления, все заранее заготовленные тестовые данные в базе обновились естественным и типовым образом.
Обратите внимание, еще один плюс: если при масштабном обновлении изменилась структура реквизитов НСИ и прочих вспомогательных для теста данных, то в случае с использованием эталонных баз, все элементы справочников и т.д. автоматически обновятся естественным образом; а в случае с длинными автотестами, которые готовят данные сами для себя, придется адаптировать текст сценария…
И в этот раз итоговый аллюр, в котором сценарии разбиты по функциональным блокам, будет информативным. Допустим, из общего числа тестов у нас 10 по блоку продаж, из которых упало 8, а по другим блокам упало либо по одному тесту, либо не упало вовсе – и теперь мы сможем сразу же большую часть команды отправить на ручное тестирование/исправление блока продаж. Почему? Потому что, если у нас упал самый базовый автотест создания номенклатуры, то это будет отдельно упавший один сценарий, все остальные сценарии используют уже созданную для них в эталонной базе номенклатуру. Таким образом, автотесты становятся максимально устойчивыми к влиянию на них ошибок в смежных функциональных блоках, в подавляющем большинстве случаев падают в тех местах, которые они и призваны были проверить. Общий аллюр становится максимально информативным.
Когда автотест выполняет минимум действий, его способен понять даже пользователь. Ну что тут сложного: и я ищу РТУ с номером 956 в списке РТУ, и я открываю найденный документ, и я нажимаю кнопку «провести и закрыть» - и вот тут у нас ошибка при проведении. В этом случае аллюр становится удобным инструментом, позволяющим быстро понять на каком шаге автотеста у нас ошибка.
Более того, если мы используем эталонные базы, то консультант или программист могут тут же взять использовавшуюся для прогона автотестов базу и воспроизвести ошибку именно с того места, на котором «споткнулся» автотест. Время поиска, воспроизведения и, соответственно, исправления ошибки уменьшается.
Собственно, в атомарных коротких автотестах просматривается только одна проблема – необходимо подготавливать и вести эталонные базы. Как мы разобрали выше, с одной стороны, это даже и не проблема: завести тестовые данные в базе существенно проще и быстрее, чем написать сценарий, который эти тестовые данные будет готовить сам и который необходимо будет поддерживать.
Но все-таки кое-какие ограничения и обязательства использование эталонных баз на нас накладывает:Если мы пишем автотесты, которые не просто что-то там проверяют, а именно являются отражением реальных эталонных процессов предприятия, то эталонная база в таком случае может являться не только базой для прогона автотестов – на ней можно начинать разработку новых задач программистам, ведь в ней есть все необходимые заведенные НСИ и остатки. Кроме того, она лёгкая и быстро разворачивается. Если разрабатывается совсем новая функциональность, то консультант может сначала добавить нужные данные в эталонную базу, а затем программист начнет работу над задачей.
И тут уже можно автоматизировать кто во что горазд:Мы рассмотрели две крайности:
Вероятно, истина где-то посередине, гибриды вполне имеют место быть. Либо можно использовать для разных целей и функциональных блоков оба типа автотестов на одном предприятии.
Попытаемся все-таки вывести какой-то субъективный рецепт: если вы по каким-то причинам не можете себе позволить вести эталонные базы или вам важно выполнять тестирование каждого процесса от А до Я – видимо, придется все же работать с длинными независимыми автотестами. В подавляющем же большинстве случаев короткие атомарные автотесты в связке с эталонными базами позволяют эффективно и без лишней головной боли использовать сценарные автотесты.