project-management
February 11, 2023

Как пасти (с)котов. Часть 3: Качество

Как и какими жертвами достигается качество программного продукта. Кому продать душу, чью кровь пить и кому именно поклоняться. Детально, с картинками.

Чего? Это всего лишь церемония вручения Гремми 2023.

Предыдущие части этого сериала: первая, вторая. Про первый релиз тут.

Вкалывают роботы а не человек

В век победившего искуственного интеллекта, когда из всех щелей идет вой о том что «AI заменит программистов» — всерьез думать что тестировщики нужны и востребованы?

Но тем не менее дела обстоят именно так.

И чем дальше в лес к полноценному продукту — тем больше нужно тестировщиков и все более высокого класса.

Disclaimer:

Все описанное — про продукт для живых пользователей. Когда есть интерфейс и живой человек, который вашим софтом пользуется.

Про разработку библиотек и фреймворков — в другой раз.

Главное чтобы костюмчик сидел.

Что такое качество

Дорогой костюм всегда хорошо сидит, ведь он либо пошит с нуля либо подшит специально под вас и вашу фигуру. Дорогое офисное кресло — обязательно удобно и эргономично:

из-за сплава дорогих материалов, технологий и сложного и выверенного ручного производства.

Все самые дорогие машины и телефоны собираются вручную, живым человеком. У этого есть причины.

Уберем вопросы окупаемости автоматизированной линии и социально-психологический аспект:

мой дорогой костюм должен быть пошит только английским джентельменом в годах и только собственными руками.

Это все тоже важные вещи безусловно, но есть кое-что еще:

Шанс на ошибку в каком-то комплексном процессе у человека сильно меньше.

Как ни автоматизируй, как ни изгаляйся с нейросетями — без процесса мышления машина так и останется лишь исполнителем набора инструкций.

Поэтому наличие живого тестировщика многократно повышает качество вашего продукта по сравнению с любым набором тестов и любой автоматикой.

Первое что вы должны сделать на пути к качеству своего ПО это найти себе хорошего QA Engineer он же «Тестировщий обыкновенный, офисный».

Кнопки, ваши.

Жмем на кнопки

Вообще самый идеальный вариант, это когда вы сами всей командой используете собственный продукт в ежедневной работе.

Это дает максимальный эффект.

В Microsoft было правило, что на определенной стадии тестирования новой версии Windows и офисных продуктов — они раскатывались на все рабочие компьютеры сотрудников.

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

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

Поэтому знания о продукте в типичном проекте делятся на три части:

  • программисты — умеют входить/выходить из системы и нажимать на кнопки в описанной последовательности из задачи;
  • админы — умеют систему устанавливать, делать дамп базы и входить/выходить;
  • тестировщики - умеют входить под разными ролями, проходить определенные цепочки бизнес-логики.

А вот сквозных знаний нет:

нет никого кто может и собрать и починить и запустить и пройтись по логике.

По идее еще есть всякие Product Owner, тимлиды, архитекторы, менеджеры — но их уровень знаний о системе обычно «теоретическо-стратегический»:

мы знаем как должно быть и куда продукт должен двигаться, но на текущие реалии и проблемы нам поеб#ть.

Знакомая картина?

И вы такие не одни:

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

Как нетрудно догадаться — такое разделение крайне негативно влияет на качество продукта и общее ощущение от использования.

Чтобы выправить ситуацию придется ломать ноги шаблон работы, это больно и неприятно.

Главный эксперт по нешаблонному применению познаний о химии.

Ломая шаблоны

Самое первое что я всегда делал — перемешивал разработчиков между частями системы:

Если кто-то один годами работал над формами, а другой — над скриптовым движком, они меняются местами.

Не должно быть «черных пятен» в проекте для членов команды разработки.

Иначе будут простои и сюрпризы. Разработчики приходят и уходят, если позволять разделение — большой кусок знаний о проекте уйдет вместе c уходящим в закат разработчиком.

Заодно этот самый первый шаг немедленно покажет реальное положение дел в проекте:

будут вылезать на свет все костыли и подпорки, который каждый разработчик успел лично для себя насочинять.

Особенности сборки, секретные ключи запуска, закомментированные параметры и куски кода — вы все это сразу увидите.

Следущая стадия: перемешивание между бекэнд и фронэнд разработкой.

Да да, именно так.

Я всегда был и буду против разделения на фронтэнд и бекэнд — это слишком узкая специализация, не дающая возможности развития в полноценного человека программиста.

«Программист» — это то что сейчас называется full-stack, чем таких будет больше в команде тем лучше.

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

Ок, перемешали:

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

Мои поздравления если получилось.

Это был ваш самый первый серьезный шаг на пути к качеству всего проекта.

Также на этой стадии должны уйти API-срачи и перекладывание ответственности между фронтэнд и бекэнд «принцессами».

Но этого конечно мало.

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

Самый лучший вариант это создание дистрибьютива.

Да да, тот самый Windows 7 Box - самый красивый вариант упаковки для ОС.

Дистрибьютив

Как только ваш чудо-софт можно будет поставить самостоятельно без представителя команды разработки — это очень сильно повысит его качество.

Даже если вы делаете и продаете SaaS — хотя-бы ради своих же сейлов и показов, но сделайте блин дистрибьютив.

Огромное количество кривизны, костылей и подпорок откроется когда ваш софт начнут запускать не в уютном контейнере на сервере а локально.

Сейлы по своему поведению сильно ближе к пользователям — они обязательно дадут фидбек о качестве, близкий к реальности.

Вам нужно будет пройти следующие шаги:

  • Начальный набор данных — локальную базу нужно запустить, создать в ней необходимые структуры и залить начальные данные: тестовых пользователей и какие-то тестовые записи;
  • Универсальные скрипты запуска и остановки - очевидно что у пользователей будет Windows или Mac но точно не ваш любимый Линукс, поэтому придется делать подготовку окружения и скрипты запуска;
  • Механизм взаимодействия с вебом - у вас же наверняка веб-интерфейс, который открывается в браузере? Вот его надо как-то открыть локально после запуска вашего приложения.

Представляете масштаб этого геммороя?

Зато это еще и несравненное влияние на качество продукта:

Как только появится дистрибьютив — даже ваша собственная команда начнет относиться к проекту как к продукту.

А если еще и документацию напишете — будет прям следующий уровень восприятия.

Теперь перейдем наконец к более-менее очевидному способу обеспечения качества ПО — тестированию.

Кровавый ад автотестов

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

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

Как правильно

Если у вас в проекте есть веб-интерфейс, то самое лучшее это функциональные тесты на Selenium, с полным реальным браузером под капотом и эмуляцией действий пользователя.

Если у вас десктоп — все чуть сложнее, поскольку зависит от используемой технологии и ОС. Для JavaFX и Swing есть например Robot Framework. Для Windows и .NET есть Microsoft UI Automation.

Но общий смысл один и тот же: максимально полная симуляция действий пользователя.

Вот этого и надо достичь для адекватных результатов.

Что нужно тестировать:

Не поверите но только типовые кейсы. И все.

Не надо подставлять случайные или сгенеренные данные, не надо выбирать последовательность выполнения случайным образом — это все не поможет.

Скорее даже навредит, поэтому не тратьте на это время.

Также не надо пытаться делать полную изоляцию теста:

Создание и регистрация нового пользователя при запуске автотеста с его удалением в конце.

Это не типичный кейс использования и рано или поздно он встанет поперек одному из настоящих, реальных кейсов. Например про устаревание сессии или использование 2FA.

Типичные последователи TDD в корпоративных проектах

Вам это не надо

Cамым тупым делом в моем личном рейтинге тупизны, является погоня за стопроцентным покрытием юнит-тестами.

Это мало того что недостижимо для любого проекта сложнее «Hello World» так еще и бесполезно:

То что один конкретный метод отрабатывает с указанным набором параметров — не значит что вся система работает. Даже не намекает.

И сто таких методов тоже этого не гарантируют. И тысяча.

Вообще применение юнит-тестов в проекте должно быть строго ограничено библиотечными методами — которые максимально изолированы от окружающей среды и отвечают за расчеты:

Расчетные математические функции, логика расчета с конечным значением

Вот такие вещи имеет смысл тестировать юнит-тестами.

Вторым, но не менее тупым делом являются раздельные тесты фронтэнда и бекэнда:

Фронт тестируется с симуляцией ответа API бекэнда (data mocking), бекэнд — на уровне факта формирования ответа.

Проблема с этим все та же:

даже тысяча таких тестов не гарантируют что система работает.

Их наличие лишь успокаивает бдительность — не может же все сломаться при наличии тысячи тестов.

К сожалению может, еще как может.

Потому что «работает/не работает» — это булевое состояние для пользователей, для которых система не может работать наполовину или быть частично сломанной.

Любителям TDD

Помнится я обещал подорвать жопы?

Выполняю (отсюда):

I get paid for code that works, not for tests, so my philosophy is to test as little as possible to reach a given level of confidence (I suspect this level of confidence is high compared to industry standards, but that could just be hubris). If I don't typically make a kind of mistake (like setting the wrong variables in a constructor), I don't test for it. I do tend to make sense of test errors, so I'm extra careful when I have logic with complicated conditionals. When coding on a team, I modify my strategy to carefully test code that we, collectively, tend to get wrong.

Kent мать его Beck!

Создатель и идейный лидер того самого «Test Driving Development», где «сначала мы пишем тест затем под тест пишем код».

Это примерно как если бы Столлман начал продавать свой Emacs за деньги под брендом Microsoft.

Вообщем камингаут удался.

To be continued..

В следующей части расскажу про локализацию, чего это на самом деле стоит и как делается.