Как стать автором
Обновить

Комментарии 56

50/50 — юнит тесты своими силами, функциональные зааутсорсить
Аутсорсим написание unit автотестов. Аутсорсеры пишут тесты по спецификации, инфраструктуру для тестирования писали сами и гоняем тесты сами. Все имеющиеся проблемы обусловлены самим аутсорсом, никаких специфических для автотестов проблем нет.

На счет оплаты. Думаю она всегда будет гибкой, т.к. зависит от объемов, квалификации кадров, которые вам предоставят, и прочего.
Но ведь для написания юнит-тестов иногда нужно вносить изменения в сам код. Это аутсорсерам позволяется?
Может я неправильно понимаю модульное тестирование, но зачем для написания unit-тестов изменять сам код? Добавлять дополнительные методы, которые можно дернуть из теста? По-моему лучше такого избегать, но вообще разработчики контактируют с тестерами и могут подсказать какой-то незадокументированный финт. Сами тестеры, конечно, не могут вносить исправления в код. Вообще у нас есть некоторая специфика, т.к. мы предоставляем API для внешних разработчиков, поэтому потребность тестра часто может оказаться и функциональным недостатком API и тогда он уже реализуется как новая фича.
Потому что тесты приносят больше пользы, когда пишутся до кода и одна из составляющих этой пользы — улучшение дизайна
Ну так например в open source часто присылают PR c тестом, который фейлится.
Разработчики подтягивают тест, фиксят, вливают. Я думаю тут также можно
Аутсорс или нет — многое зависит от динамики проекта. Даже если передать автотесты некоторой внешней команде, то возникнут проблемы взаимодействия в случае динамичного проекта, когда часто меняются требования, переписывается код, много еще не устоявшегося функционала, или же просто проблемы с процессами на проекте.

В случае же если всё идеально, когда код вполне пригоден для разработки автотестов, существуют договоренности и правила его изменения, то, наверное, да, можно и в аутсорсинг. Ребята будут работать только по требованию и реагировать на изменения кода\требований.
Хотя не знаю, бывают ли такие идеальные ситуации.
Идея реально может сыграть для функционального тестирования какого-то внешнего API по принципу черного ящика. Если этот API зафиксирован во времени и его поведение не меняется.

Юнит-тесты — в первую очередь инструмент для разработчика, а в TDD — так вообще инструмент не столько для тестирования, сколько для проработки интерфейсов внутренних сущностей. У меня в работе часто бывает, что вроде бы минорное изменение несколько изменяет модель, и небольшие изменения веером расходятся в 3-4 сущности, для которых надо соответствующим образом обновить тесты. Если разработчик не работает с тестами — то у него связаны руки для внутреннего рефакторинга. Если работает и правит соответствующие тесты — то непонятно, зачем тогда аутсорс.

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

Про функциональное тестирование именно GUI на frontend'е не могу сказать чего-то принципиального, я работаю с backend'ом. Но в любом случае тут важным фактором опять же будет изменчивость интерфейса. Сколько будет стоить поменять какую-то структурную единицу приложения, включая переписывание теста? Как часто могут происходить (из вашего опыта) такие изменения? Спустя какое время после того, как разработчик напишет интерфейс, на этот интерфейс будет написан тест? Кстати, как разработчик будет проверять, что все хорошо и он ничего не сломал? 10-20 раз руками после каждого патча кода? Не быстрее ли ему написать тест, и эти 10-20 раз прогонятся в автоматическом режиме?

Этот пост написан сторонником TDD.
Поддерживаю. Мне тоже кажется странным аутсорсить юнит-тесты. Изменил код, измени сразу тесты, или в обратной последовательности. Может пока у удаленной команды руки дойдут до ваших тестов, они уже поменяются. Честно говоря, вообще не представляю себе такую модель.

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

Флоу при функциональном тестировании франтэнда обычно такое: свежая функциональность тестируется вручную и после нескольких итераций правок, когда функционал готов и оттестирован на него пишется функциональный тест, который может запускаться по каким-то триггерам, по коммиту, по расписанию, вручную etc.
Хм, простите )
Не понял до конца идею. Что получает на входе тестеры? Бизнес-сценарии на человеческом языке и сами переписывают их на язык тест-фрейма? Или уже написанные на этом языке тест-кейсы? На чём они гоняют тесты? У себя, то есть нужно задеплоить проект им? Или нужно задеплоить проект у себя и предоставить им доступ, плюс какое-то API для инициализации тестов (грубо — очистка базы и заполнения фикстурами)?

По моему опыту приемочных/функциональных тестов для веб-приложений (Селениум и т. п.) самое сложное — это начальное внедрение: а) разворачивание тестового окружения и б) определения того что нужно тестировать (в смысле что считать ожидаемым результатом) — то ли внешний вид (побайтовое сравнение с эталонными скриншотами и/или полными текстами страниц), то ли DOM-структуру (наличие/отсутствие элементов с каким-то CSS/XPath селектором и их значения), то ли тупо наличие/отсутствия каких-то строк. Дальше поддержка довольна тривиальна, если резких изменений не происходит.
Мне это видилось таким образом: на входе тестеры получают человекопонятные тесткейсы (пример: открыть страницу такую-то, найти товар такой-то положить в корзину, перейти в корзину и убедиться что он там) с описанием пошаговых действий и ожидаемым результатом. Гоняют тесты у себя (на своих серверах, в облаках). Деплоить у себя проект это имхо слишком, просто доступ до него, возможно по впн-у и, если нужно, то доступ к БД или API. Заказчик теоретически может поднять Selenium Grid и на своей стороне, но это какая-то полумера что ли, зачем?

Допускаю что у кого-то процесс поддержки проходит гладко, но в моем опыте гладко не было никогда. Банально такой собирательный пример: был один энтузиаст что-то делал-делал, потом уволился, пришел другой и, посмотрев на доставшееся наследие, прослезился. Пришел другой с предложением переписать этот говнокод под какой-нибудь фреймвок типа thucydides, но в процессе получил более интересное предложение и перебрался в Москву. Как-то так.
Я думаю, писать настолько подробные тесикейзы на естественном языке немногим труднее, чем писать на формальном.
А что значит на формальном? Нужно в общем написать так, чтобы это было понятно человеку не знакомому с тестируемой системой.
На формальном — это значит вместо «Открыть страницу такую-то» писать ОткрытьСтраницу(ТакуюТо) на языке программирования.

Если я правильно уловил, то ваша мысль такая — «Если можно так подробно описать последовательность действий, то можно самому и все это запрограммировать»?
Да.
Ну, насколько незнакомы? :) Можно обеспечить хорошую читаемость, например Cucumber, в который завернуть Capybara.

Cucumber — по сути генератор тестов на основе простого лексического парсера, можно написать очень понятные обработчики прям на естественном языке. На одной конфе товарищи утверждали, что в такой связке им тест на баг добавил заказчик, который просто нашел косяк в работе сайта. :) Нормально знакомый с IT, но все же.
С идеей вроде понятно, а вот с поддержкой не знаю, возможно вы и правы — как себя ведут тесты после того как я ушёл — не знаю. Но на селениум-тесты я быстро забил, возможно не умею их готовить. Тестировал чисто http-код по селекторам и подстрокам.
Идея аутсорса инфраструктуры для разработки витает в воздухе уже давно. Это и CI, и тестирование, и даже такие тривиальные вещи, как контроль версий с функционалом для code review (github). Но главная проблема в том, что в большинстве случаев всё CI'ное требует огромной дисциплины при создании и развитии того, что будет тестироваться.

Так что я с некоторым скепсисом смотрю на идеи аутсорса — порядка в головах аутсорсом не наведёшь.
Это конечно так, но функциональные тесты-то нужны в любом случае. Пусть не не в CI, а хотя бы on demand. Нажал на кнопочку, посмотрел что все тесты зелененькие и успокоил немного нервы что ничего не сломалось. Уже неплохо я считаю. А когда из 100 тестов зелененьких 70% при том что весь функционал 100% рабочий, начинаешь задумываться зачем вообще нужны такие тесты. Т.е. основная идея в том, что в теории, если некая внешняя команда занимается исключительно написанием функциональных тестов в промышленных масштабах, то они уже наступили на все грабли и научились их избегать. А грабель на этом поприще хватает.
Для того, чтобы описать «что такое зелёненькое» нужно, чтобы одна программа понимала, что делает другая. Для этого надо научить общаться _ДВЕ_ программы. А это баги (с обоих сторон), плюс «учить понимать» не улучшает функционал, так что на это забивают с огромной скоростью.

А дальше всё просто: аврал, надо срочно что-то сделать. Человек делает. Код работает, тесты ругаются. Так как аврал, на тесты забивают. А дальше надо либо править тесты, либо код, либо их обоих, но тут уже следующий аврал.

Бороться с этим можно только если есть человек, который точно готов тратить своё время на зелёненькие лампочки, да желательно ещё имеющий полномочия напрягать остальных. Ну или фантастическая самодисциплина коллектива, которая опять же обычно держится на нескольких энтузиастах (такое легко разваливается).
Все действительно так. На обновление тест-кейсов забивается повсеместно, особенно при наличии авто-тестов. Меняется функционал — на ходу меняется код тестов, а тестовые сценарии как лежали в стороне так и лежат. В итоге имеем безнадежно устаревшие артефакты в виде тест-кейсов и набор авто-тестов которые что-то тестируют, но непонятно что. Проблемы начинаются когда тест падет при попытке нажать на кнопку, которой нет. И вот сиди и думай то ли это баг, то ли ее и не должно быть.

Похоже при аутсорсном подходе дисциплина даже должна повыситься, у нее нет другого выхода. Например упали тесты из-за изменения какой-то функциональности (добавили шаг при покупке товара). Местный QA, назовем его тест дизайнер, видит это дело и оперативно правит тест-кейсы в соответствии с изменениями, потому что это единственная его задача, авралы на него не распространяются, поскольку в написании кода он не задействован. Далее изменения передаются удаленщикам и они делают свою часть работы. Профит. + 100% свежие и актуальные тест-кейсы и зеленые тесты. А важность актуальных тест-кейсов сложно переоценить, и и заказчику можно в случае чего показать и быстро ввести в курс дела новых сотрудников.
Тесты должны быть написаны понятно — чтобы не гадать зачем они нужны.

«Проблемы начинаются когда тест падет при попытке нажать на кнопку, которой нет»
не может ли это контролироваться статической проверкой при каждой модификации кода?
Нет, не может. Я плохо возможно мысль выразил. Изменения могут быть абсолютно любые, ну, скажем, есть в автотесте шаг экспорта продуктов. Там последовательно запускаются какие-то процессы по имени. Потом кто-то решил что название процесса не совсем отражает его суть и переименовал его. Тест упал потому-что процесс с таким именем не нашелся. С понятностью теста проблем нет, но как реагировать на это не понятно.
Почему тест зависит от имени процесса? Имя процесса — это часть UI? Почему имя процесса нельзя статически контролировать?
Да, в данном примере часть UI. Модифицируется не из кода, а из админки.
Тогда конфигурация админки должна тоже создаваться тестом под себя.
Во всём этом есть простая проблема: в тесты инвестируются ресурсы людей, и инвестируются они безусловно, а вот отдача является вероятностью от множества факторов. И выделение такого размера инвестиций, причём в каждом моменте, это постоянное жервтвование локальной эффективностью ради возможного тактического превосходства (которое не становится при этом стратегическим — ибо что тесты есть, что тестов нет, на рынке программе это не поможет напрямую).

Математика за рациональностью тестов очень и очень сложная, и не факт, что её коэфиценты так просто узнать.

Потому что каждый тест звучит так «либо мы пишем фичу, либо тесты». Тесты — повышение стабильности, фича — захват новой доли рынка.
Хорошо сказано. Но в данном обсуждении хотелось бы выяснить наиболее эффективный способ их создания (функциональных авто-тестов), а то они нужны принять за факт.
Потому что каждый тест звучит так «либо мы пишем фичу, либо тесты». Тесты — повышение стабильности, фича — захват новой доли рынка.

Если ресурсов достаточно, то можно писать и то, и другое. Приемочные тесты пишут QA, а не разработчики.
Если ресурсов достаточно, то можно написать две фичи.

Про «писать» я имел в виду не написание тестов как таковых, а адаптацию тестируемого ПО к тестам.

Тесты — это очень сложная и дорогая вещь, на самом деле. А вот насколько они помогают — вопрос отрытый.
Надо начинать с тех, которые точно помогают.
Обычная красивая сказка про тесты звучит так: «тесты позволяют не допускать ошибки и позволять свободный рефакторинг».

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

Например: пусть у нас… ну, допустим, компонента, которая из sql'я рисует отчёт по обороту за месяц того, что прошло через этот sql.

Программисты пишут тесты, которые проверяют всякие corner случаи, типа " месяц 28 дней, а иногда 29, а ещё високосные секунды", «не полный список транзакций», «обрабатывается случай отрицательных операций» и т.д.

А потом менеджер проекта приходит и говорит «мы тут неправильно считаем что такое товар — товар это не всё, а только то, что называется „товар“ и надо бегом исправлять».

А потом он приходит и говорит «не, всё равно херня получается, а сроки мы уже сорвали, у нас надо считать товаром то, что имеет в себе „товар“ только в первой части названия, до примечаний в скобочках, а не в любом месте строки».

А потом он прибегает со словами «всё нахер сломалось», и выясняется, что отчёт собирает из нескольких sql'ей, некоторые из которых работают в 1251, но про это молчат как партизаны.

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

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

Компилятор тоже не ловит все ошибки, а только ошибки компиляции.
Именно там, где светло. Тесты прежде всего защищают от регрессивных ошибок в основной функциональности, в основных известных сценариях. На крайние случаи, високосные секунды, переполнения целого и т. п. тесты можно в начале не писать, только когда придёт баг-репорт :) Но единожды пофиксив баг, получив зеленым новый тест, заведенный для бага, тесты дают гарантию, что он не сломается опять из-за какой-то новой фичи, фикса другого бага или рефакторинга. Остальные функции тестов вторичны.
А вместе с этой гарантией получим обременение по сопровождению теста вместе с изменением ТЗ, которое, внезапно, меняется.

Получится так, что вместо десяти фич придётся переписывать двадцать. И не факт, что из написанных десяти тестов все десять за свой короткий срок жизни пригодились.

Я в этом посте занял позицию противника тестов, но на самом деле я просто не знаю — тесты хорошо, писать тесты плохо.

Убедите меня.
Так тесты по сути и являются формализованным ТЗ. Они пригодились хотя бы для того, чтобы понять что тот или иной пункт ТЗ выполнен (так как его понял тот, кто читал ТЗ и это понимание четко зафиксировано в файле теста). По идее писать тесты (если что, я о приемочных прежде всего) должен аналитик (ну или тот, кто выполняет его роль совместно с другими), тот кто непосредственно общается с заказчиком и преобразует его хотелки в понятные программистом требования, а то и сам заказчик. А что может быть понятнее программисту чем «при таких-то условиях после таких-то действий эта булева операция должна вернуть true»?
В этом случае тест просто повторит работу программы. Обычно тесты едва-едва трогают функционал в малом количестве точек, да и «формализованное ТЗ» — фикция. Полностью формализованное ТЗ — и есть сама программа.
Нет, тест не повторяет программу. Он описывает что должна программа делать, а программа описывает как она это собирается делать.
Пример теста для веб-приложения на мощном тест-фреймворке:
0. Начальное состояние приложения такое-то, в частности есть активный пользователь с логином user и паролем password.
1. Обращаемся к странице /login
2. Должна появиться форма с полями "Имя" и "Пароль" и кнопкой "Войти" (степень детализации определяется соглашениями и инструментами, это может быть проверка на наличие (CSS или XPath селекторы)  в html инпутов, подстрок, совпадение скриншота с эталонным и т. п.)
3. Пользователь вводит имя user и password и жмёт кнопку "Войти"
4. Должен произойти редирект на /
5. Должна появиться надпись "Привет,  user".

Чем не простое формализованное ТЗ? Но является ли оно программой? Нет, это именно задание, а программа — его реализация.

Что-то покрытия, то в методиках разработки типа TDD не может быть малого количества точек пересечения. Причина появления любой значимой строки кода — не сработавший без неё тест.
Конечно, это ТЗ совершенно не соответствует ожиданиям заказчика.

Форма с полями должна умещаться на экран 800х480, а не требовать 2560х1440. Шрифт в поле ввода должен быть больше 5ого кегля, а в поле пароль — меньше 92. Цвет тона должен отличаться от цвета фона. Цвет тона должен отличаться от цвета фона больше, чем на 60 по яркости. Поле ввода должно быть достаточно большим, чтобы там было видно хотя бы 75% вводимого символа по высоте. И хотя хотя бы 6 символов по ширине. Имя пользователя может состоять не только из одиночного символа «а». И не только из testuser, которым тестирует приложение. Пароль должен проверяться, а не просто разрешать ввод чего угодно. Нет, в пароле может быть больше 3 символов. Нет, пароль может содержать в себе цифры. И буквы. Хотя бы. Нет, пароль должен быть от той учётой записи, от которой логин. Нет, пароль должен быть актуальным на момент ввода. Нет, показывать неправильные буквы в пароле неправильно.

Кнопка «войти»…

Короче, лениво перечислять. Слишком всего много, и на любой тест найдётся такая херня, которая его пройдёт, но не будет соответствовать задумке стейкхолдеров.
Ну так опишем это в терминах тест-фреймворка, если проверку типа «с полями должна умещаться на экран 800х480» не представляется возможным забить в автотест, до добавим этот кейс в список ручного предрелизного тестирования но опять же в четко формализованном виде. А вот требования к паролю легко формализуются.

Да, на любой тест найдётся такая херня, которая не будет соответствовать задумке. Но это лишь означает, что задумка в требованиях не изложена. Или изложена, но не формализована понятным программисту языком. В любом случае, если мы не хотим краснеть перед заказчиком (и обанкротиться из-за неустоек и штрафов), то перед каждым релизом должны прогонять всего его требования, даже те, что были изложены в аське пару лет назад. Если подавляющее большинство из них можно автоматизировать, то почему это не сделать? Или будем надеяться на авось: авось фикс этого бага ни на что не повлияет, а этот рефакторинг формы ввода не затроент подсистему отчётов?
Единственный метод описать ТЗ полностью — это описать алгоритм. Что есть банальная его реализация. Таким образом, полное формализованное ТЗ — это и есть программа, с поведением которой мы можем сравнивать другую программу. Если сходится — значит алгоритм сработал правильно. Если нет — неправильно.

А вот не выполняя алгоритм описать что он делает в общем случае-то и невозможно (задача останова).
Значит у нас разные понимания что такое ТЗ. Вы не путаете техническое задание с техническим проектом? Согласно ГОСТу, техническое задание является исходным документом для разработки и испытания изделия, содержит требования а технический проект — документ, в котором, в том числе, описываются выбранные (и обосновывается выбор) архитектура, структуры данных, алгоритмы и т. п. — этап непосредственно предшествующей собственно разработке. Ну а потом приемочные испытания на соответствие программы требованиям ТЗ.
Я подозреваю, amarao намекает на то, что описать в ТЗ все требования очень трудно и совершенно бесполезно. Ну я не представляю себе бизнеса, который готов тратить месяц аналитика на описывание всех требований к простейшей формочке. Никогда не надо забывать, что мы решаем задачи не ради их решения, а ради задач бизнеса. И решение этих задач построено не только на бизнес-процессах, но и на таких вещах как «здравый смысл», «опыт решения предыдущих задач», «знание принятых в команде и компании умолчаний» или «понимание предметной области» (да, я настаиваю на том, что понимание предметной области — полезное свойство программиста, которое позволяет ему просить заметно больших денег, демонстрируя гораздо лучшую автономность и производительность). Ничего этого у аутсорсеров нет.

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

Что не отменяет возможности эффективности такого аутсорса.
Да про аутсорс речи пока нет вообще. Говорим о том нужны ли тесты в принципе.
>>>Получится так, что вместо десяти фич придётся переписывать двадцать.

вы про какие тесты — модульные, интеграцционные или приемочные?

Если про последние, то они должны проверять работу в общих чертах и их не надо менять на каждый чих

>>> И не факт, что из написанных десяти тестов все десять за свой короткий срок жизни пригодились.

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

Ну собственно никто не мешает ему делать то же самое без аутсорса, а передавать тестокодерам — их аврал обічніх кодеров не касается.
Функциональные тесты нужны, но их должно быть мало.

Эта команда будет работать с некоторым лагом относительно функционала и вы не сможете никогда сказать упал тест потому, что его еще не успели обновить или потому, что ошибка.
Если следовать test first, то всегда потому что ошибка. Собственно если тесты зелёные, а приходит баг-репорт и он подтверждается, то пишется тест, который должен быть красным, а потом код исправляют чтобы он был зеленым.
Фраза про лаг относилас к варианту с аутсорсерами — с ними тест фёст будет еще тормознее + разные взаимные попытки сказать «этого не было в ТЗ» и прочее.
Хоть проголосовало всего около 100 человек, статистика получается интересная и для меня неожиданная. А может среди нас есть люди занимающиеся сабжем?
Я бы не стал аутсорсить тесты на постоянной основе. Это все равно что аутсорсить составление ТЗ — тесты фактически исполняемые примеры использования.

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

И постараться побольше покрыть юнит и интеграционными тестами, соблюдая test pyramid.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории