Русский
Русский
English
Статистика
Реклама

Software testing

Перевод Что такое CICD? Разбираемся с непрерывной интеграцией и непрерывной поставкой

13.08.2020 22:14:38 | Автор: admin
В преддверии старта курса CI/CD на AWS, Azure и Gitlab подготовили для вас перевод полезного материала.



Непрерывная интеграция (Continuous Integration, CI) и непрерывная поставка (Continuous Delivery, CD) представляют собой культуру, набор принципов и практик, которые позволяют разработчикам чаще и надежнее развертывать изменения программного обеспечения.

CI/CD это одна из DevOps-практик. Она также относится и к agile-практикам: автоматизация развертывания позволяет разработчикам сосредоточиться на реализации бизнес-требований, на качестве кода и безопасности.

Определение CI/CD


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

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

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

Инструменты CI/CD помогают настраивать специфические параметры окружения, которые конфигурируются при развертывании. А также CI/CD-автоматизация выполняет необходимые запросы к веб-серверам, базам данных и другим сервисам, которые могут нуждаться в перезапуске или выполнении каких-то дополнительных действий при развертывании приложения.

Непрерывная интеграция и непрерывная поставка нуждаются в непрерывном тестировании, поскольку конечная цель разработка качественных приложений. Непрерывное тестирование часто реализуется в виде набора различных автоматизированных тестов (регрессионных, производительности и других), которые выполняются в CI/CD-конвейере.

Зрелая практика CI/CD позволяет реализовать непрерывное развертывание: при успешном прохождении кода через CI/CD-конвейер, сборки автоматически развертываются в продакшн-окружении. Команды, практикующие непрерывную поставку, могут позволить себе ежедневное или даже ежечасное развертывание. Хотя здесь стоит отметить, что непрерывная поставка подходит не для всех бизнес-приложений.

Непрерывная интеграция улучшает коммуникации и качество


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

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

Многие используют фича-флаги (feature flag) механизм для включения и выключения функционала в рантайме. Функционал, который еще находится в стадии разработки, оборачивается фича-флагами и развертывается из master-ветки в продакшн, но отключается до тех пор, пока не будет полностью готов к использованию. По данным недавнего исследования 63 процента команд, использующих фича-флаги, говорят об улучшении тестируемости и повышении качества программного обеспечения. Для работы с фича-флагами есть специальные инструменты, такие как CloudBees Rollout, Optimizely Rollouts и LaunchDarkly, которые интегрируются в CI/CD и позволяют выполнять конфигурацию на уровне фич.

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

Этап сборки заключается в автоматизации упаковки необходимого программного обеспечения, базы данных и других компонент. Например, если вы разрабатываете Java-приложение, то CI упакует все статические файлы, такие как HTML, CSS и JavaScript, вместе с Java-приложением и скриптами базы данных.

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

Большинство CI/CD-инструментов позволяет запускать сборку вручную, по коммиту или по расписанию. Командам необходимо обсудить расписание сборки, которое подходит для них в зависимости от численности команды, ожидаемого количества ежедневных коммитов и других критериев. Важно, чтобы коммиты и сборка были быстрыми, иначе долгая сборка может стать препятствием для разработчиков, пытающихся быстро и часто коммитить.

Непрерывное тестирование это больше, чем автоматизация тестирования


Фреймворки для автоматизированного тестирования помогают QA-инженерам разрабатывать, запускать и автоматизировать различные виды тестов, которые помогают разработчикам отслеживать успешность сборки. Тестирование включает в себя функциональные тесты, разрабатываемые в конце каждого спринта и объединяемые в регрессионные тесты для всего приложения. Регрессионные тесты информируют команду: не сломали ли их изменения что-то в другой части приложения.

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

Регрессионные тесты это только начало. Тестирование производительности, тестирование API, статический анализ кода, тестирование безопасности эти и другие виды тестирования тоже можно автоматизировать. Ключевым моментом является возможность запуска этих тестов из командной строки, через веб-хук (webhook) или через веб-сервис и возврат результата выполнения: успешный был тест или нет.

Непрерывное тестирование подразумевает не только автоматизацию, но и интеграцию автоматического тестирования в конвейер CI/CD. Модульные и функциональные тесты могут быть частью CI и выявлять проблемы до или во время запуска CI-конвейера. Тесты, требующие развертывания полного окружения, такие как тестирование производительности и безопасности, часто являются частью CD и выполняются после разворачивания сборок в целевых средах.

CD-конвейер автоматизирует поставку изменений в различные окружения


Непрерывная поставка это автоматическое развертывание приложения в целевое окружение. Обычно разработчики работают с одним или несколькими окружениями разработки и тестирования, в которых приложение развертывается для тестирования и ревью. Для этого используются такие CI/CD-инструменты как Jenkins, CircleCI, AWS CodeBuild, Azure DevOps, Atlassian Bamboo, Travis CI.

Типичный CD-конвейер состоит из этапов сборки, тестирования и развертывания. Более сложные конвейеры включают в себя следующие этапы:

  • Получение кода из системы контроля версий и выполнение сборки.
  • Настройка инфраструктуры, автоматизированной через подход инфраструктура как код.
  • Копирование кода в целевую среду.
  • Настройка переменных окружения для целевой среды.
  • Развертывание компонентов приложения (веб-серверы, API-сервисы, базы данных).
  • Выполнение дополнительных действий, таких как перезапуск сервисов или вызов сервисов, необходимых для работоспособности новых изменений.
  • Выполнение тестов и откат изменений окружения в случае провала тестов.
  • Логирование и отправка оповещений о состоянии поставки.


Например, в Jenkins конвейер определяется в файле Jenkinsfile, в котором описываются различные этапы, такие как сборка (build), тестирование (test) и развертывание (deploy). Там же описываются переменные окружения, секретные ключи, сертификаты и другие параметры, которые можно использовать в этапах конвейера. В разделе post настраивается обработка ошибок и уведомления.

В более сложном CD-конвейере могут быть дополнительные этапы, такие как синхронизация данных, архивирование информационных ресурсов, установка обновлений и патчей. CI/CD-инструменты обычно поддерживают плагины. Например, у Jenkins есть более 1500 плагинов для интеграции со сторонними платформами, для расширения пользовательского интерфейса, администрирования, управления исходным кодом и сборкой.

При использовании CI/CD-инструмента разработчики должны убедиться, что все параметры сконфигурированы вне приложения через переменные окружения. CI/CD-инструменты позволяют устанавливать значения этих переменных, маскировать пароли и ключи учетных записей, а также настраивать их во время развертывания для конкретного окружения.
Также в CD-инструментах присутствуют дашборды и отчетность. В случае сбоя сборки или поставки они оповещают об этом. При интеграции CD с системой контроля версий и agile-инструментами облегчается поиск изменений кода и пользовательских историй, вошедших в сборку.

Реализация CI/CD-конвейеров с Kubernetes и бессерверными архитектурами


Многие команды, использующие CI/CD-конвейеры в облаках используют контейнеры, такие как Docker, и системы оркестрации, такие как Kubernetes. Контейнеры позволяют стандартизировать упаковку, поставку и упростить масштабирование и уничтожение окружений с непостоянной нагрузкой.

Есть множество вариантов совместного использования контейнеров, инфраструктуры как код и CI/CD-конвейеров. Подробнее изучить это вы можете в статьях Kubernetes with Jenkins и Kubernetes with Azure DevOps.

Архитектура бессерверных вычислений представляет собой еще один способ развертывания и масштабирования приложений. В бессерверном окружении инфраструктурой полностью управляет поставщик облачных услуг, а приложение потребляет ресурсы по мере необходимости в соответствии с его настройками. Например, в AWS бессерверные приложения запускаются через функции AWS Lambda, развертывание которых может быть интегрировано в CI/CD-конвейер Jenkins с помощью плагина.

CI/CD обеспечивает более частое развертывание кода


Итак, подведем итоги. CI упаковывает, тестирует сборки и оповещает разработчиков, если что-то пошло не так. CD автоматически разворачивает приложения и выполняет дополнительные тесты.

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

CI/CD является одной из DevOps-практик, поскольку направлена на борьбу с противоречиями между разработчиками, которые хотят часто вносить изменения, и эксплуатацией, требующей стабильности. Благодаря автоматизации, разработчики могут вносить изменения чаще, а команды эксплуатации, в свою очередь, получают большую стабильность, поскольку конфигурация окружений стандартизирована и в процессе поставки осуществляется непрерывное тестирование. Также настройка переменных окружения отделена от приложения и присутствуют автоматизированные процедуры отката.

Эффект от внедрения CI/CD-конвейеров можно измерить в виде ключевых показателей эффективности (KPI) DevOps. Такие KPI как частота поставки (deployment frequency), время реализации изменений (change lead time) и среднее время восстановления после инцидента (mean time to recovery) часто улучшаются при внедрении CI/CD с непрерывным тестированием. Однако CI/CD это лишь один из процессов, который может способствовать этим улучшениям. Есть и другие условия для увеличения частоты поставки.

Для начала работы с CI/CD команде разработчиков и эксплуатации необходимо совместно определиться с технологиями, практиками и приоритетами. Команды должны выработать консенсус в отношении правильных подходов к своему бизнесу и технологиям, чтобы после внедрения CI/CD команда постоянно придерживалась выбранных практик.



Краткий обзор инструментов CICD: Gitlab CI, Docker, Ansible


Подробнее..

Тестирование приложений в условиях нехватки памяти

10.10.2020 20:06:06 | Автор: admin

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


Часть людей считает, что надо пытаться обрабатывать все виды runtime ошибок, в т.ч. и OOM ситуации. Другие считают, что с OOM всё равно мало что можно сделать и лучше дать приложению просто упасть. На стороне второй группы людей ещё и тот факт, что дополнительная логика обработки OOM с трудом поддаётся тестированию. А если код не тестируется, то почти наверняка он не работает.


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


Вопрос о том надо ли пытаться обрабатывать OOM ситуации в библиотеках/приложениях является противоречивым и мы не будем его здесь касаться. В рамках данной публикации я лишь хочу поделиться опытом того как можно тестировать реализованную логику обработки OOM ситуаций в приложениях написанных на C/C++. Разговор будет идти об операционных системах Linux и macOS. Ввиду ряда причин, Windows будет обойдён стороной.


Введение


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


  • Объем RAM всегда ограничен.
  • SWAP не всегда включен.
  • Приложения не всегда ведут себя адекватно и порой пытаются выделить нереально большие объёмы памяти мешая себе и другим.
  • 32-битные приложения всё ещё существуют.
  • overcommit не всегда включен.

Если вы дочитали до этого места, то будем считать, что вы согласны с тем, что обрабатывать OOM важно и нужно. Почему это важно для себя каждый решает сам, со своей стороны могу кратко сказать, что ко многим компонентам надо которыми работал я предъявлялись следующие требования:


  • Компонент никогда не должен падать, приложения его использующие не должны падать из-за ошибок в таких компонентах.
  • При возникновении OOM ситуаций приложение должно уметь завершить свою работу не падая. Данные над которыми работает ПО не должны повреждаться даже в случае нехватки памяти.
  • При временной нехватке памяти ПО должно переходить в режим пониженного потребления ресурсов и при возможности продолжать выполнять свои функции пусть даже с низкой производительностью. Если памяти начинает снова хватать, приложение должно выходить на нормальный режим работы.

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


Сразу скажем, что, к сожалению, порой мы бессильны и не можем гарантировать выполнение данных требований. К нам может прийти OOM Killer, от него можно частично защитится, но не всегда. Ещё одним сюрпризом может оказаться то, что вам не всегда может удаться бросить объект исключения в C++, об этом мы расскажем чуть позже.


Шаг 1. Наивный подход или лучше чем ничего


На первых шагах может показаться, что создать приложению OOM ситуации для целей тестирования легко. Можно просто создать пару функций my_malloc и my_free и везде в коде использовать их вместо нативных malloc и free.


К слову переопределение my_free опционально. И так же не стоит забывать про потенциальную необходимость реализации my_realloc.


В нормальных условиях my_malloc будет просто оборачивать malloc не внося никакой логики. Для целей тестирования в my_malloc можно заложить некоторую логику, которая будет приводить к возвращению NULL в определённых условиях.


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


  • Нет никакой возможность покрыть тестами 3rd party код не изменяя его.
  • Многие библиотечные функции используют malloc под капотом и будут продолжать вызывать его напрямую. Одним из широко-используемых примеров таких функций является strdup.
  • Оборачивание mallocа порождает дополнительные накладные расходы, в большинстве случаев они будут незначительны, но всё же не равны нулю.
  • Данный подход слабо подходит для тестирования C++ кода в котором редко происходят явные вызовы malloc и free.

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


Шаг 2. Метод грубой силы


Те кто тесно работают с Linux наверняка в курсе что такое LD_PRELOAD. С помощью данной переменной окружения можно принудительно заставить загрузить свою библиотеку вперёд других. С её помощью чаще всего и переопределяют поведение таких стандартных функций как malloc. Возможно это того, что такие функции как malloc/realloc/free исторически являются слабыми (weak). Сразу скажем, что на macOS есть брат LD_PRELOAD, зовут его DYLD_INSERT_LIBRARIES.


И так, в целях тестирования, с помощью LD_PRELOAD и DYLD_INSERT_LIBRARIES можно подменить стандартные malloc/realloc своими реализациями которые и помогут нам возвращать NULL когда нам этого нужно.


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


Опять же, если просто "заваливать" случайным образом все аллокации, не беря в расчёт контекст, мы мало чего сможем добиться. Суровая реальность преподносит следующие сюрпризы:


  • Зачастую приложение может упасть даже не дойдя до выполнения функции main. С этим сделать мы ничего не можем, соответственно и симулировать подобные ситуации нет никакого смысла.
  • Runtime библиотеки на macOS уж очень не стабильны и норовят упасть при каждом "удобном случае". Опять же за чужой код мы не отвечаем, если мы знаем, что он хрупкий, то не стоит пытаться его уронить.
  • Даже вызов printf на macOS может привести к SIGSEGV/SIGBUS.
  • Чтобы бросить исключение, например std::bad_alloc, необходимо выделить память под объект исключения. И, внезапно, память под объект исключения тоже может быть не выделена, если мы сталкиваемся с OOM. В этих ситуациях приложение просто получает std::terminate. Данная ситуация также малоинтересна и её не стоит допускать в процессе тестирования.
  • Создание потока с помощью std::thread в условиях нехватки памяти может привести к std::terminate на macOS.

UPDATE: По результатам тестирования с помощью Travis CI можно сказать, что с новыми версиями macOS / Xcode ситуация улучшилась, бросать std::bad_alloc можно даже когда кончилась память, создание потока с помощью std::thread больше не приводит к std::terminate.


Для того чтобы принять в расчёт все известные факторы суровой реальности и была написана библиотека Overthrower. Она позволяет несколькими псевдо-случайными способами заставлять malloc возвращать NULL. Одновременно с этим Overthrower позволяет не допускать падений из-за кода, который нам неподвластен.


Шаг 3. Берём в расчёт суровую реальность


Гарантируем возможность дойти до main


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


К слову, когда мы покидаем main мы тоже мало на что можем повлиять. То есть библиотека Overthrower, которая будет синтетически создавать OOM ситуации должна иметь возможность отложенного запуска и раннего останова. Необходим некий способ который позволит проинформировать библиотеку Overthrower о том, когда ей стоит начать работать и когда стоит прекратить.


Самым простым способом оказалось создать пару функций которые будут видны тестируемому приложению:


  • activateOverthrower
  • deactivateOverthrower

Чтобы иметь возможность увидеть эти функции в тестируемое приложение необходимо добавить следующее:


#ifdef __cplusplusextern "C" {#endifvoid activateOverthrower() __attribute__((weak));unsigned int deactivateOverthrower() __attribute__((weak));#ifdef __cplusplus}#endif

В исходных кодах библиотеки есть заголовочный файл с объявлениями этих функций: https://github.com/kutelev/overthrower/blob/master/overthrower.h


Если библиотека Overthrower не подгружена с помощью механизма LD_PRELOAD, эти функции будут указывать в NULL, очевидно, что пытаться вызывать их в данном случае не стоит.


Итак, в самом простом случае, протестировать некий код на предмет устойчивости можно следующим образом:


int main(int argc, char** argv){    activateOverthrower();    // Some code we want to test ...    deactivateOverthrower();}

На практике вызывать activateOverthrower/deactivateOverthrower можно где угодно и сколько угодно раз, на практике это можно делать в модульных тестах следующим образом:


TEST(Foo, Bar){    activateOverthrower();    // Some code we want to test ...    deactivateOverthrower();}

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


#ifdef __cplusplusextern "C" {#endifvoid pauseOverthrower(unsigned int duration) __attribute__((weak));void resumeOverthrower() __attribute__((weak));#ifdef __cplusplus}#endif

Использовать это можно следующим образом:


TEST(Foo, Bar){    activateOverthrower();    // Some code we want to test ...    pauseOverthrower(0);    // Some fragile code we can not fix ...    resumeOverthrower();    // Some code we want to test ...    deactivateOverthrower();}

Реальные примеры использования библиотеки Overthrower можно найти в тестах самой библиотеки: https://github.com/kutelev/overthrower/blob/master/tests.cpp


Гарантируем возможность бросить исключение


Для выделения памяти под объект исключения используется функция __cxa_allocate_exception, она, о сюрприз, может вызвать под капотом malloc, который может вернуть NULL. Тут стоит отметить, что на Linux, при невозможности выделить память с помощью malloc, __cxa_allocate_exception будет пытаться использовать запасной буфер (emergency buffer), данный буфер аллоцируется статически и в большинстве случаев позволяет без проблем бросать небольшие исключения даже тогда, когда память на куче закончилась совсем. Дополнительное подробности могут быть найдены тут: http://refspecs.linuxfoundation.org/abi-eh-1.22.html#imp-emergency


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


UPDATE: Как уже было сказано ранее, новые версии macOS / Xcode не имеют этой проблемы.


Чтобы гарантировать возможность тестирования кода, который пишем мы, нам не остаётся ничего иного как гарантировать то, что __cxa_allocate_exception всегда сможет выделить память под объект исключения с помощью вызова malloc. Из-за этого Overthrowerу приходится немного анализировать стек вызовов на каждый вызов malloc. Overthrower никогда не заваливает malloc который приходит из __cxa_allocate_exception.


Также, некоторые широко используемые функции славятся тем, что никогда явно не освобождают за собой память, например на macOS этим славится __cxa_atexit, на Linux dlerror. Есть и другие примеры.


Overthrower ожидает, что всё что выделяется с помощью malloc будет освобождено с помощью free. При вызове упомянутых выше функций Overthrowerу может показаться, что в коде вызываемом между activateOverthrower и deactivateOverthrower есть утечки, о чём он обязательно пожалуется:


overthrower got deactivation signal.overthrower will not fail allocations anymore.overthrower has detected not freed memory blocks with following addresses:0x0000000000dd1e70  -       2  -         1280x0000000000dd1de0  -       1  -         1280x0000000000dd1030  -       0  -         128^^^^^^^^^^^^^^^^^^  |  ^^^^^^  |  ^^^^^^^^^^      pointer       |  malloc  |  block size                    |invocation|                    |  number  |

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


Поиск утечек памяти не есть основная функция Overthrowerа, для этого есть инструменты получше, такие как valgrind. Однако, эти инструменты не могут быть использованы при запуске приложения в условиях OOM. Поскольку мы требуем, что в приложении не возникает утечек ни при каких обстоятельствах, мы используем Overthrower в том числе и для поиска возможных утечек памяти. Если Overthrower считает, что он нашёл утечки памяти, функция deactivateOverthrower вернёт количество не освобождённых блоков памяти, а в stderr будет выведен краткий отчёт.


Выбор стратегии заваливания


Overthrower имеет 3 стратегии для заваливания аллокаций:


  • Random заваливает аллокации для которых rand() % duty_cycle == 0. Параметр duty_cycle, можно установить в желаемое значение.
  • Step начинает заваливать все аллокации после достижения указанного момента (malloc_seq_num >= delay), delay регулируется по желанию.

<--- delay --->--------------+              |              | All further allocations fail              |              +------------------------------

  • Pulse заваливает указанное количество аллокаций после некоторой задержки (malloc_seq_num > delay && malloc_seq_num <= delay + duration), параметры delay и duration могут быть настроены согласно требованиям.

<--- delay --->--------------+                +------------------------------              |                |              |                | All further allocations pass              |                |              +----------------+              <--- duration --->

Выбор стратегии и её настройка выполняются с помощью переменных окружения:


  • OVERTHROWER_STRATEGY
  • OVERTHROWER_SEED
  • OVERTHROWER_DUTY_CYCLE
  • OVERTHROWER_DELAY
  • OVERTHROWER_DURATION

Переменные окружение можно выставить в любой момент до вызова activateOverthrower. Если переменные окружения не заданы, Overthrower выбирает стратегию и её параметры случайным образом, в качестве источника случайных данных используется устройство /dev/urandom.


В некотором виде возможные способы тонкой настройки описаны в файле README.md.


Заключение


  • Overthrower позволяет завалить любой вызов malloc по отдельности и проверить как это обрабатывает тестируемое приложение/библиотека.
  • Можно тестировать отдельные части приложения по отдельности многократно задавая разные параметры заваливания.
  • Overthrower можно использовать для тестирования кода написанного на голом Си.
  • Хрупкие фрагменты кода можно защитить от падения поставив Overthrower на паузу.
  • Overthrower замедляет работу приложения, но не катастрофически.
  • Побочным эффектом использования Overthrowerа является возможность обнаруживать утечки памяти которые могут возникнуть в том числе и вследствие неправильной обработки ошибочных ситуаций.
  • Для того чтобы интегрировать Overthrower в процесс тестирования необходимо писать Overthrower-aware тесты. В принципе, сложного в этом ничего нет.
  • Сам Overthrower тестируется на Ubuntu (начиная с версии 14.04) и macOS (начиная с Sierra (10.12) и Xcode 8.3). В процессе тестирования Overthrower пытается в том числе уронить сам себя.
  • Если в системе возникает реальный OOM, Overthrower делает всё чтобы не упасть самому.
Подробнее..

Перевод Что нам стоит автоматизацию построить три паттерна для повышения эффективности процессов

20.05.2021 20:12:40 | Автор: admin

Меня зовут Владислав Романенко, я старший iOS QA Engineer в Badoo и Bumble. Несколько лет назад мы начали активнее использовать автотесты в разработке, но столкнулись с некоторыми трудностями.

Логичный вопрос: почему мы занялись автоматизацией тестирования? Ответ кроется в еженедельном выпуске новых версий наших мобильных приложений. QA-отделу приходится тестировать новые фичи, их интеграцию в сервисы и заниматься регрессионным тестированием. За неделю комплексное регрессионное тестирование нужно проводить как минимум один раз, что довольно утомительно. Автоматизация помогла нам выпускать новые версии быстрее и без потери качества. Подробнее об автоматизации мобильного тестирования в докладе моих коллег.

В разработке проблемы часто решаются с помощью паттернов обобщённых решений для часто возникающих проблем в заданном контексте. То же и с автоматизацией тестирования, есть даже хорошее wiki-описание. В этой статье мы поговорим о паттернах процессов (Process Patterns). Они помогают организовать и улучшить процесс автоматизации тестирования.

Без дальнейших предисловий перейдём к трудностям, с которыми мы боролись, и рекомендациям по их преодолению с помощью тех самых паттернов. Замечу, что это не единственные проблемы, которые у нас были и есть. Но в рамках данной статьи я решил остановиться именно на них.

Паттерн 1. Просьба о помощи (Ask for Help)

Как это часто бывает, мы все имели разный опыт, знания и навыки. На тот момент не все в команде сталкивались с автоматизацией тестирования некоторым пришлось учиться на ходу. Чтобы помочь коллегам из команды QA справиться со сложностями, мы предложили им обратиться за помощью к команде автоматизации. Идея в том, что если ты застреваешь на какой-то проблеме, то не нужно самостоятельно бороться с ней слишком долго, ведь другие уже могли столкнуться с подобным и найти решение. А чтобы автоматизаторов не завалили вопросами, мы решили формализовать этот подход. Прекрасным решением оказался паттерн ASK FOR HELP:

Просите о помощи, а не теряйте время, пытаясь всё сделать самостоятельно.

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

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

Внутрениий StackOverflow

Стоит отметить, что в нашей вики есть документация и описания решений для большинства распространённых проблем. Возможно, документировать все возможные ошибки и объяснения в вики не лучший подход, но мы считали, что сохранить их в одном месте будет полезно. Так у нас возникла идея создания локального Stack Overflow. Для этого мы воспользовались open source-решением Scoold. Оно предназначено для использования на первой линии обработки запросов и работает как обычная Stack Overflow, только для сотрудников компании. Когда у кого-нибудь возникает проблема, достаточно зайти в наш локальный Stack Overflow, чтобы найти решение или написать вопрос, на который ответит кто-то из специалистов.

Так выглядит наш локальный StackOverflowТак выглядит наш локальный StackOverflow

Преимущества

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

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

  • Стало меньше сообщений и веток в чатах, где их трудно отслеживать и искать. Мессенджеры не лучшее место для хранения документации и обращения к ней как к источнику истины. Stack Overflow гораздо удобнее.

Недостатки

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

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

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

Паттерн 2. Введение стандартов (Set Standards)

По мере возможности мы стараемся переиспользовать код в разных приложениях и на разных платформах, чтобы упростить сопровождение и поддержку. Но, как и в любой другой системе, которую несколько лет разрабатывало много людей, разные части кода могут быть написаны в разных стилях. Наш основной язык для сквозных автотестов это Ruby (об истории автоматизации мобильного тестирования в нашей компании рассказывал agile_seph здесь), потому что он как раз позволяет писать код в разных стилях (автор языка Юкихиро Мацумото хотел, чтобы разработчики использовали его язык так, как им удобно). Однако работать с чужим кодом бывает сложно.

Для решения этой проблемы мы выбрали паттерн SET STANDARDS:

Введите и соблюдайте стандарты для артефактов автоматизации.

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

Что мы сделали

  • Создали локальную вики с актуальными руководствами и документами (например, как настроить окружение, как запускать и поддерживать тесты), которая помогла сократить циклы ревизии кода. Всю документацию мы храним в Confluence, который разделили на несколько частей. Команды регулярно проверяют актуальность своей документации.

  • Добавили в вики межкомандные ретроспективы и соглашения. Ежемесячно мы проводим встречи и по результатам каждой из них делаем какие-то практические выводы.

  • Что касается самого кода тестов и ограничений на уровне кода для основных этапов и методов верификации, мы внедрили стандартные инструменты, включая RuboCop (статический анализатор и инструмент форматирования кода для Ruby), защитные проверки (Guard Cheсks) и pre-commit-хуки.

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

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

Преимущества

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

  • На ревью кода уходит меньше времени. С одной стороны, код становится аккуратнее, с другой всегда есть источник истины для рецензента и рецензируемого.

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

Недостатки

  • После создания документации её никто не сопровождает. Это общая проблема для любой документации, особенно для той, что не используется постоянно. Поэтому мы назначили ответственных за сопровождение документов и настроили отправку им на почту уведомлений из Confluence, чтобы ничьи комментарии не оставались без внимания.

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

Паттерн 3. Делимся информацией (Share Information)

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

Этот паттерн называется SHARE INFORMATION:

Просите и давайте информацию начальству, разработчикам и другим тестировщикам.

Для нас это способ улучшить автоматизацию тестирования за счёт более широкого набора знаний. Для реализации этого паттерна мы запустили еженедельные короткие презентации QA Lightning Talks. Любой человек может предложить тему и в течение 10-15 минут выступить с ней. Поскольку у встреч чёткий тайминг, это хорошая возможность узнать что-то новое, не потратив на это много времени. Для тех, кто не смог присутствовать, мы сохраняем видеозаписи встреч во внутренней библиотеке.

Доклады могут быть посвящены не только тестированию и его автоматизации. Например, однажды bayandin рассказывал о своём опыте поддержки проекта Homebrew. А я как-то рассказывал о том, что я диванный картограф в Humanitarian OpenStreetMap. Я создаю карты районов, которые плохо картографированы, и потом ими пользуются в работе сотрудники разных организаций вроде Красного Креста или Врачей без границ. Сокращённая версия этого доклада позднее была представлена на сессии Soapbox конференции EuroSTAR 2020.

Преимущества

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

  • Общий объём знаний растёт. А согласно исследованию, обмен знаниями улучшает взаимодействие между департаментами и внутри них.

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

Недостатки

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

  • Трудно удерживать интерес аудитории и увеличивать ее. Мы каждый раз меняем тему и сосредотачиваемся на актуальных проблемах. Например, один из проектов заключался в том, что мы собирали результаты всех тестовых прогонов тикета в таблицу и интегрировали её в Jira. Об этом на ближайшей встрече и рассказал один из участников команды автоматизации тестирования.

Бонус: паттерн для обучения разделение на пары (Pair Up)

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

Чтобы достичь цели, мы воспользовались паттерном PAIR UP:

Более опытный сотрудник получает себе в пару менее опытного.

Для QA-инженеров мы запустили внутреннюю программу менторства. Что это такое? QA-инженеры присоединяются к автоматизаторам на короткий промежуток времени (обычно на две недели) и работают над задачами из бэклога этой команды, а не из своего. Помогают им в этом менторы из числа старших инженеров-автоматизаторов. Цель внутреннего менторства заключается в обучении. Мы разработали такой манифест:

  • Сосредоточенность на обучении, а не на строгом соблюдении сроков.

  • Интерактивные обсуждения, а не работа в бункере.

  • Ранняя и регулярная обратная связь, а не ретрообзор в конце менторства.

Хотя утверждения справа ценны, утверждения слева для нас ценнее.

Подробнее о менторстве, о том, почему и как мы его практикуем, я рассказывал в недавнем выступлении.

Итоги

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

Какие проблемы мы смогли решить

  • Нежелание обращаться за помощью к коллегам (решили с помощью паттерна Ask for help). Как отметили в своей книге A Journey through Test Automation Patterns: One teams adventures with the Test Automation Серетта Гамба и Дороти Грэхем, не бойтесь просить о помощи: большинству людей на самом деле нравится помогать.

  • Высокая стоимость сопровождения кодовой базы тестирования (решили с помощью паттерна Set Standards). Если вы давно работаете над автоматизацией, то стандарты просто необходимы.

  • Информационный бункер (решили с помощью паттерна Share Information). Общайтесь с другими людьми: в процессе обсуждения часто рождаются новые идеи.

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

Расскажите в комментариях, с какими сложностями при автоматизации тестирования столкнулись вы и как их решали.

Подробнее..

Дополняем чек-лист тестирования при обновлении иконки и сплеша в мобильных приложениях

29.10.2020 10:19:47 | Автор: admin

Алоха! Меня зовут Даша, я тестирую мобильные приложения. Скоро Хэллоуин, а FunCorp традиционно обновляет к некоторым праздникам иконку и сплеш. Сейчас именно такой случай, потому что большинство наших пользователей находятся в США. Задача показалась тривиальной, я быстро составила базовый чек-лист на 8 пунктов, но в процессе нашла ещё несколько кейсов, и он вырос до 13-ти (прилагается).

Здесь нет rocket science, я лишь расскажу, на что стоит обращать внимание в таких тасках, чтобы не пропустить лишних багов в прод и на Android, и на iOS.


Итак, что мы ожидали получить во время праздничного обновления:


Ожидаемые результат. Всё просто

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

  1. Обновление приложения.
  2. Чистая установка.
  3. Запуск сворачивание.
  4. Свёрнутое в недавних.
  5. Добавление иконки на главный экран (Android only).
  6. Разные экраны.
  7. Разные версии оси.
  8. Сплеш.


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

Трудности Android


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

Иконка

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



Также иконка может криво выглядеть на разных icon shapes:

Android 10/Pixel

Добавляем в чек-лист:
  • Иконки в пушах
  • Разные icon shapes.


Сплеш

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

Например, лого отдельно может оказаться меньше или больше ожидаемого:


Растянутым или сжатым:


Не по центру (если это не ожидаемо):


Теперь рассмотрим возможные проблемы с фоном сплеша.

Он может спрятаться под виртуальные кнопки:


Сжаться или растянуться:


Те же проблемы с центрированием фона, что и у иконки:


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


Ко всему прочему добавляем в чек-лист:

  • Поворот экрана.


Трудности iOS



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

Но не спешите нажимать Tested: основная проблема связана с кешированием ОС иконки и сплеша.

Иконка

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



В чек-лист добавляем:

  • Поиск приложения на устройстве.
  • Свёрнутое приложение в списке недавних.


Сплеш

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

Вот что могли бы увидеть пользователи, но до них это, к счастью, не дошло

Но мы нашли решение. Например, чистить кеш так, как написано в этой статье.

Добавляем пометку не забыть про кэширование на iOS.

Финальный чек-лист


Итак, я добавила шесть новых пунктов, и теперь список выглядит вот так:

  1. Обновление приложения + не забыть про кэширование на iOS.
  2. Чистая установка.
  3. Запуск сворачивание.
  4. Свёрнутое приложение в недавних.
  5. Поиск приложения на девайсе.
  6. Разные экраны.
  7. Поворот экрана.
  8. Разные версии оси.
  9. Иконка в пушах.
  10. Разные icon shapes.
  11. Добавление иконки на главный экран (Android only).
  12. Сплеш.
  13. Cплеш с виртуальными кнопками (Android only).


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

А если во время тестирования вы тоже сталкивались с нетривиальными проблемами и способами их решения, пожалуйста, напишите, чтобы мы могли вместе дополнить этот список. Весёлого Хэллоуина!
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru