Дипломная работа: Разработка технологии непрерывного тестирования программного кода при контейнерной виртуализации на примере многопользовательского мультиплатформенного приложения

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Бизнес-логика управляет приложением, а не деревом представлений;

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

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

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

Первая задача при создании проекта с таким архитектурным паттерном -- это упорядочить пакеты по функциям. Таким образом достигается ряд преимуществ:

Высокая модульность.

Высокая сплоченность компонентов.

Более простая навигация по коду.

Минимизация объема кода.

Инкапсуляция кода.

Более быстрое время сборки.

Возможность повторного использования общей функциональности.

Уменьшение конфликтов (особенно при работе с git-потоками).

Более контролируемые зависимости.

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

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

Рис. 4. Модульная система распределения пакетов.

Древо пакетов на изображении слева (cм. рис. 4) -- это один из логических модулей приложения, а именно авторизация пользователя. Он разделен на три области по паттерну MVP. Пакет view_layer отвечает за отображение данных пользователя и оповещение пользователя о состоянии работы приложения. Пакет presenter_layer управляет пакетом отображения, а также отвечает за бизнес-логику модуля, состояние приложения, переносит и берет данные из пакета model_layer.

Древо пакетов на изображении справа - общий модуль приложения. Здесь хранится базовая часть модуля, отвечающего за работу с сервером, Общие для приложения модели для работы с UI, реактивная библиотека по работе с Web-сокетами, база данных, а также часть бизнес логики приложения.

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

8.2 Разработка алгоритма непрерывного тестирования кода:

Чтобы разобраться в особенностях разработки модуля CI, с учетом дальнейшей интеграции, необходимо понять процесс CI и его этапы:

Первый этап интеграции, перенос кода из системы контроля версий приложения в CI tool. Этот этап не зависит от сложности приложения и вообще от кода, как такового. Нужно лишь настроить файл config (.yaml), в котором должна содержаться информация о проекте в системе контроля версий и правила, по которым происходит клонирование в CI-tool. Файл конфиг пишется по следующему шаблону:

before_script:

- export ANDROID_HOME="$HOME/Library/Android/sdk"

- bundle install

stages:

- build

- test

- quality_assurance

- deploy

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

На предыдущем этапе приложение было скомпилировано и собрано. Результатом этих действий является специфичный для платформы артефакт, который по умолчанию просто хранится в контейнере инструментов CI. Поскольку мы интегрируем версию приложения для Android, мы получаем файл с расширением «.apk», который представляет собой исполняемую программу, которую можно загрузить и установить. Тем не менее, этот файл требует сгенерированного ключа загрузки и хранилища ключей, с которым он должен быть подписан, для загрузки на платформу Play Market. Это можно сделать с помощью системы «build.gradle».

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

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

8.3 Написание E2E тестов на платформе Appium:

Другой важной задачею, которую мы хотели разобрать в модуле CI являлось продумывание и разработка надежного механизма тестирования. Чтобы понять, для чего такой механизм необходим, можно представить себе следующую ситуацию: над одним проектом в команде работает множество разработчиков, некоторые из которых имеют более низкий стаж, чем их коллеги, или просто недавно подключились к новой команде. Один из таких программистов может сделать определенную часть приложения (фичу) и сохранить ее в инструменте контроля версий, но не зная особенностей реализации приложения непременно совершит какой-то недочет или ошибку. Однако эта ошибка не пойдет дальше и не будет замечена пользователями, потому что она натолкнется на «стену» в виде непрерывного тестирования в модуле CI.

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

Для написания такого блока тестирования мною была выбрана платформа Appium, из-за ее интегрированности с мобильной платформой разработки Android Studio, а также возможности написания тестов на любом предпочитаемым языком программирования.

Проконсультировавшись с моим коллегой по разработке приложения iOS было решено продолжить писать тесты на Python, ввиду его простого синтаксиса и распространенности, а также возможности написания общих тестов на обе мобильные платформы. Таким образом все end-to-end тесты в проекте были написаны на Python с использованием библиотеки PyTest.

Сперва мною были написаны тесты для UI, для тех элементов, с которыми взаимодействовал пользователь.

8.4 Запуск системы:

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

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

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

9 Разработка Web части

9.1 Разработка веб-приложения

Первой задачей в web-части нашего диплома по теме «Разработка технологии непрерывного тестирования программного кода при контейнерной виртуализации на примере многопользовательского мультиплатформенного приложения» являлась разработка полноценного веб-приложения, на примере которого можно было апробировать разработанную систему тестирования. Приложение должно было быть достаточно сложным, чтобы имелась возможность продемонстрировать все ключевые моменты работы системы тестирования.

Для разработки приложения необходимо было выбрать актуальный на рынке язык программирования и соответствующий фреймворк. Это было необходимо, так как предполагается, что описанная далее технология тестирования будет востребована в IT-компаниях. По этой причине, был выбран язык программирования JavaScript и фреймворк React, выпущенный компанией Facebook, как абсолютные лидеры рынка фронтенд-разработки.

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

Версия приложения для Desktop-браузера;

Версия приложения для мобильного браузера;

Работа с History API и организация «роутинга» внутри приложения;

Логика работы с REST API;

Логика работы с веб-сокетами;

Логика работы c cookies и localstorage;

Управление глобальным состоянием приложения с помощью Redux.

Рис. 5. Пример интерфейса разработанного приложения для браузера

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

9.1.1 Адаптация под мобильные и Desktop-браузеры

Чтобы тестирование было полноценным, необходимо было создать интерфейс, который способен работать на различных платформах и расширениях экранов. Для этого верстка интерфейсов велась в адаптивной манере и использовались такие решения современной веб-разработки, как: @media queries и webkits для CSS-движков браузеров. Те задачи, которые невозможно было решить исключительно языком стилей, решались с помощью языка JavaScript. Например, необходимо было измерять ширину экрана, чтобы не просто менять стили отдельных компонентов на странице, но и заменять целиком шаблон страниц, как это делается на страницах «Настройки».

9.1.2 «Роутинг» и навигация по приложению

В классических веб-приложениях, организующих SSR (Server Side Rendering), взаимодействие с историей браузера и, соответственно, навигацией по веб-приложению осуществлялось за счет history API [9]. Так как в нашем конкретном случае используется SPA-архитектура (Single Page Application), то для навигации используется React Router, реализующий гораздо более современный подход.

9.1.3 Взаимодействие с сервером

Почти все веб-приложения, реализующие более-менее сложную логику, должны работать с сервером. В нашем случае используется два протокола: HTTP(s) и WebSocket. Через первый организована логика авторизации, регистрации, изменения пользовательских данных и получение истории переписки. Через WebSocket-протокол организован поиск и чат. В первом случае используется специализированный пакет для асинхронных запросов Axios; для работы с сокетами используются нативные интерфейсы языка программирования JavaScript. Логика работы с WebSockets организована в виде конечного автомата.

9.1.4 Работа с хранилищами браузера

Для управления ключевыми данными пользователя, такими, как токены авторизации, используется интерфейсы браузера. Они позволяют фиксировать критичную для пользователя информацию в браузерных хранилищах. Из трех известных: indexDB, localstorage и cookies [10-12] - используются последние два, в виду их удобства использования, так как заводить базу данных для данных задач считается излишним.

9.1.5 Глобальное состояние приложения

Наравне с хранилищами браузера, в разработке современных веб-приложений возникает ситуация, когда необходимо обмениваться данными между страницами и компонентами не через API браузеров, описанных выше. Для этих целей существует архитектурные подход, построенный на Flux-принципе. В данном приложении используется его расширенная версия Redux [13], которая позволяет получать доступ к большим структурам данных, лежащим в коде приложения, не перегружая API браузеров.

Также хочется отметить, что наравне с архитектурными подходами и решениями, реализованными в процессе разработке и описанным выше, одним из основных ключевых преимуществ данного приложения является возможность интеграции его кодовой базы с применяемой в тестировании экосистемой. Так как и разработка, и тестирование ведется на едином языке программирования JavaScript, то окружение, формируемое NodeJS (серверным вариантом языка JavaScript), поддерживается повсеместно. Хочется заострить внимание на следующих положительных моментах:

9.1.6 Общий пакетный менеджер

В разработке и тестировании используется общий пакетный менеджер npm (Node Package Manager) [14]. Соответственно, все загружаемые пакеты, используемые в ходе работы, такие, как:

ImmutableJS - библиотека для работы с иммутабельными структурами [15];

Ramda - библиотека для функционального программирования [16];

Moment - библиотека для работы с датами и календарем [17];

Axios - библиотека для HTTP-запросов [18];

Babel - библиотека для «транспиляции» старого синтаксиса JavaScript-кода в современный ES6 [19]

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

9.1.7 Облегченная сборка проекта

Сборка проекта происходит с помощью «бандлера» Webpack [20], open-source`ного решения, позволяющего грамотно «минифицировать» и оптимизировать JavaScript-код для работы в браузере. Помимо непосредственной сборки проекта и уменьшения финального кода, данный сборщик оптимизирует загрузку стилей (в разработке использовался препроцессором SCSS, который «транспилируется» в классический CSS) и обновление HTML верстки. Кроме этого, Webpack делит JavaScript, CSS и HTML файлы на куски, «чанки», что позволяет браузеру подгружать новый код по мере работы в приложении, то есть асинхронно. В дополнении к этому имеется функционал для запуска локального сервера с целью повышения удобства разработки и отладки приложения.