Тестирование сигналов
Одна из ключевых особенностей Qt – это объектная связь на основе сигналов и слотов, которая по сути является системой, основанной на событиях.
Для ее тестирования Qt Test предлагает класс под названием , который представляет собой на стероидах, который может перехватывать и записывать сигналы.
Как и предполагалось во введении, класс выдает два сигнала:
- – выдается после нажатия кнопки CONCAT и объединения входного текста.
- – выдается после нажатия кнопки CANCEL и очистки всего текста.
В следующем тесте код будет имитировать нажатие двух кнопок и проверять выдаваемые сигналы.
Первая часть кода для простоты устанавливает текст непосредственно в поля ввода. А затем создаются два объекта , каждый из которых связан с сигналом, выдаваемым объектом :
Вторая часть имитирует нажатие кнопки CONCAT, а затем проверяет, записан ли сигнал . Проверить это можно, просто определив, сколько элементов содержит соответствующий объект (). Затем последний проверяет, соответствует ли параметр, полученный из сигнала, строке результата.
Последняя часть функции тестирования имитирует нажатие кнопки CANCEL и проверяет, получен ли сигнал , и что он не содержит никаких параметров.
В этом примере для простоты я проверил 2 сигнала в одном тесте, но было бы лучше держать эти вещи изолированными в двух разных тестах. Помните об этом при написании реальных юнит-тестов.
Как пишутся тесты
Составление тестов начинается со сбора списка требований к тестируемому коду. Затем для каждого требования пишется тестовый сценарий, который проверяет, что оно выполняется. Сценарии бывают позитивными — когда мы передаем корректные данные и ждем успешный результат, и негативными — когда мы передаем неправильные данные и ждем сообщение об ошибке.
Вот пример сбора требований. Допустим, что у нас есть функция , которая обрезает строку, если она длиннее N символов. Каким требованиям она должна соответствовать?
- если передать ей строку из 5 символов и = 10, функция должна вернуть строку без изменений
- если передать ей строку из 11 символов и = 5, то функция должна обрезать строку до
Вот более сложный пример. Допустим, у нас есть система бронирования номеров в отеле, и мы хотим написать интеграционные тесты для класса , который отвечает за создание броней. Тут список требований будет другой:
- если передать корректные дату заезда, дату выезда, количество человек и в наличии есть свободные номера, то должна создаться бронь
- если дата выезда раньше или совпадает с датой заезда, должна вернуться ошибка
- если количество человек меньше или равно нулю, должна вернуться ошибка
- если свободных номеров на выбранные даты нет, должна вернуться ошибка
На каждое требование мы пишем отдельный тест — это позволит при ошибке понять, что именно сломалось. Тесты обычно пишут в стиле Arrange, Act, Assert. Мы сначала подготавливаем и настраиваем нужные компоненты (Arrange), выполняем действие (Act) и проверяем результат (Assert).
class TruncateTest extends \PHPUnit\Framework\TestCase { public function testShortStringRemainsAsIs() { // Act: вызываем функцию $result = truncate("hello", 10); // Assert: проверяем, что возвращенный результат совпадает с ожидаемым $this->assertEquals("hello", $result); } public function testLongStringIsTruncated() { $result = truncate("hello world", 5); $this->assertEquals("hello…", $result); } }
Метод из PhpUnit проверяет, что фактический результат совпадает с ожидаемым, и выдает ошибку, если это не так. В PhpUnit много assert-функций на все случаи жизни.
Модульное тестирование графического интерфейса пользователя с помощью Qt Test
В данном руководстве я расскажу о модульном тестировании GUI с помощью Qt Test, фреймворка Qt для модульного тестирования кода на C++. В частности, я расскажу, как написать базовый юнит-тест для класса виджета, как имитировать события мыши и клавиатуры и как для графических интерфейсов писать тесты, управляемые данными.
Это третий пост из серии, посвященной Qt Test. Посты этой серии:
- Модульное тестирование кода на C++ с помощью Qt Test. Часть1. Введение
- Модульное тестирование кода на C++ с помощью Qt Test. Часть 2. Расширенное тестирование
- Модульное тестирование GUI (графического интерфейса пользователя) с помощью Qt Test. Часть 1. Введение
- Модульное тестирование GUI (графического интерфейса пользователя) с помощью Qt Test. Часть 2. Расширенное тестирование
Рекомендую прочитать предыдущие посты этой серии, чтобы полностью понять новые концепции, которые я представлю здесь.
Исходный код
Полный исходный код этого руководства доступен на GitHub.
Полная структура проекта включает 3 подпроекта:
- – динамическая библиотека, содержащая класс виджета;
- – пример приложения, использующего виджет ;
- – юнит-тест .
Чтобы попробовать этот пример в работе, загрузите в Qt Creator верхний проект с поддиректориями под названием .
Имейте в виду, что по умолчанию при запуске проекта запускается пример приложения. Для запуска модульных тестов вы можете изменить активную конфигурацию запуска, использовать панель Тесты или использовать меню Инструменты (Tools) → Тесты (Tests) → Запустить все (Run All Tests).
Справочная информация
Чтобы узнать больше о Qt Test, вы можете ознакомиться с последней документацией по пространству имен и классу .
Преимущества и недостатки
1. Преимущества
- Низкая связь, Представления могут быть изменены и изменены независимо от модели. Модель представления может быть привязана к различным «представлениям». При изменении представления модель не может изменяться, а при изменении модели вид также может изменяться.
- Улучшить ремонтопригодность, Решить проблему ручной синхронизации MVP большого количества видов и моделей и предоставить механизм двусторонней привязки. Повысить удобство сопровождения кода.
- Упростить тестирование, Поскольку логика синхронизации выполняется Binder, и представление изменяется одновременно с моделью, вам нужно только убедиться в правильности модели и представления. Значительно уменьшите тест для просмотра синхронного обновления.
2. Недостатки
- Чрезмерно простой графический интерфейс не подходит, или, скорее, убивает курицу.
- Для больших графических приложений существует много состояний просмотра, и стоимость создания и поддержки ViewModel относительно высока.
- Оператор связывания данных обязательно записывается в шаблон представления, это содержимоеНевозможно отладить точки остановаA.
6. Резюме
Разработка различных режимов MV + X,По сути, это управление моделью и видом экономичным и экономичным способом., В MVC модель и представление не полностью разделены, в результате чего код Activity будет раздутым. В MVP Presenter используется для передачи. Модель и представление полностью разделены, но код не элегантен, поскольку V и P ссылаются друг на друга. ViewModel достигает привязки представления и данных через привязку данных, которая устраняет недостатки этого MVP, но есть также проблема, заключающаяся в том, что привязка данных все еще незрелая.
Переход от Presenter к ViewModel с помощью привязки данных обеспечивает двустороннюю привязку данных, уменьшая связь между модулем просмотра и модулем управления. Я считаю, что с постоянным обновлением и улучшением технологии привязки данных Google режим MVVM будет более широко использоваться на платформе Android.
Ссылка:
Functional
От внешнего переходим к внутреннему — функциональному тестированию. Если в тестировании GUI мы проверяли наличие и внешний вид элементов, то в функциональном тестировании мы проверяем их работоспособность и взаимодействие.
Самый простой способ подготовиться к функциональному тестированию — это выписать список элементов вашего приложения и написать их целевое назначение («зачем?»).
Например:
Кнопка | Зачем? | После нажатия происходит какое-то действие. |
Поле ввода | Для передачи какой-то информации и взаимодействия с приложением. | |
Поиск | Для того, чтобы пользователь мог быстро найти релевантную информацию. | |
Логин-форма | Чтобы пользователи могли иметь доступ к определенным функциям приложения (или наоборот, ограничить их доступ). | |
Календарь | Например, для выбора дат (билеты, бронирование и т. п.). | |
Дата и время | Например, расписание прибытия транспорта. | |
Сообщения об ошибках | Чтобы сообщить пользователю о том, что приложение работает некорректно, либо он делает некорректные действия. | |
Всплывающие окна и подсказки | Направить пользователя по нужному сценарию. |
У вас уже почти готов список тестовых сценариев. Зная целевое назначение любого элемента, мы можем легко описать все позитивные и негативные сценарии, необходимые для тестирования этого элемента.
Но и тут мы можем кое-что забыть. Часто забываемые проверки функциональных элементов приложения:
Кнопки:
- Enter должна срабатывать как submit;
- Tab должен переводить курсор на следующий элемент.
Поля ввода:
- trimming («убирание») пробелов в полях ввода;
- пустота/пробелы в поле ввода;
- все способы редактирования (Insert, Delete, Backspace, Ctrl+C/V/X/Z и т. д.);
- дроби ( 1.5 | 1,5 | ⅕).
Поиск:
- wildcard symbols (* | ?);
- написание поискового запроса слитно | раздельно | через дефис должно вести к одному результату;
- ввод текста в другой раскладке.
Сообщения об ошибках:
пробуем отключить в настройках браузера.
Календарь:
- 31 июня;
- 29 февраля + не высокосный год;
- прошлое/будущее (например, купить билет на уже прошедшее число).
Время:
- синхронизация с сервером (на сервере приложения может быть выставлено другое время, отличающееся от таймзоны пользователя);
- временные зоны.
логин (63 символа) @ домен (253 символа (может быть ip)).
Всплывающие окна / подсказки:
- пробуем закрыть разными способами (нажатие на кнопку (если есть), на «крестик», клавишей ESC, просто нажатием в другую область экрана);
- рефреш страницы особенно в момент запроса на сервер (например, совершение транзакции по покупке) иногда может приводить к появлению ошибок.
Функция main приложения
Как упоминалось ранее, каждый юнит-тест должен быть независимым исполняемым файлом. Это означает, что после создания юнит-теста вам понадобится функция для его запуска.
Для формирования кода функции , в соответствии с вашими потребностями, Qt Test предоставляет 3 макроса:
Вы можете добавить один из этих макросов в конец файла cpp, определяющего юнит-тест. В этом примере, поскольку я тестировал простой код на C++ (без Qt), я использовал:
Следует помнить, что если вы объявляете класс юнит-теста непосредственно в файле .cpp (а не в файле .h), вам нужно будет добавить в конце дополнительный :
Это требует Qt для правильной работы.
Пример создания карты тест-кейсов для UI-тестирования
Вокруг формы минимум 13 тест-кейсов. Сделаем разметку от TC-1 до TC-13 и выполним тестирование пользовательского интерфейса:
Пример покрытия тестами формы авторизации.
ТC-1
Проверить логотип, его положение и шрифт страницы.
ТC-2
- Проверить правильность заголовка страницы.
- Проверить шрифт
ТC-3
- Проверить фокус курсора на поле по умолчанию.
- Проверить обязательные поля, нажав кнопку «Далее», пока форма пуста.
- Проверить положение и выравнивание текстового поля.
- Проверить ввод как допустимых, так и недопустимых символов в метках полей.
ТC-4
- Проверить положение и выравнивание текстового поля.
- Проверить метки полей, убедитесь, что принимаются как допустимые, так и недопустимые символы.
ТC-5
- Проверить положение и выравнивание текстового поля.
- Проверить метки полей, убедитесь, что принимаются как допустимые, так и недопустимые символы.
ТC-6
- Проверить сообщение об ошибке, введя разрешенные и запрещенные символы.
- Проверить правильность сообщения об ошибке.
ТC-7
Проверить всплывающие окна и гиперссылки.
ТC-8
- Проверьте метки полей, убедитесь, что принимаются как допустимые, так и недопустимые символы.
- Проверьте положение и выравнивание текстового поля.
ТC-9
- Сохраните неподходящий пароль.
- Проверьте метки полей, убедитесь, что принимаются как допустимые, так и недопустимые символы.
- Проверьте положение и выравнивание текстового поля.
ТC-10
- Проверьте положение значка.
- Проверьте значок, показывает или скрывает пароль пользователя.
- Проверить качество изображения.
ТC-11
- Проверьте сообщение об ошибке, введя разрешенные и запрещенные символы.
- Проверьте правильность сообщения об ошибке.
ТC-12
Протестируйте всплывающие окна и гиперссылки.
ТC-13
- Протестируйте отправку данных.
- Проверьте положение и ясность кнопки.
Usability
За внешним видом и функциональностью следует удобство (Usability). Не менее важная часть, так как от нее зависит, будет ли востребован ваш продукт вообще. О каких моментах нужно помнить при тестировании usability веб-приложения?
- Соответствует ли приложение ожиданиям конечного пользователя;
- Логичность интерфейса;
- Самое нужное «сверху»;
- Продуманная навигация;
- Локализация (да, да, она относится и сюда тоже);
- Совместимость с другим софтом (соцсети) и железом;
- Скорость работы приложения;
- Информативность (сообщения / обязательные поля);
- Возможность отмены действий пользователя;
- Help — должна быть инструкция, как работать с приложением;
- Возможность печати (если нужно).
Почитать
Как обмануть Face ID
Biometric Authentication Under Threat: Liveness Detection Hacking — презентация с Black Hat, посвященная способам обмана биометрических сенсоров в смартфонах (датчик отпечатка пальца, сканер лица и сетчатки). Авторы приводят несколько способов обхода датчиков, в том числе с помощью прямого подключения к шине камеры и подачи на нее заранее снятого изображения (это позволяет обойти алгоритмы определения реального присутствия человека, но не лазерные сканеры в iPhone и некоторых других смартфонах). Но интереснее всего способ обмана сканера Face ID в iPhone X и более поздних моделях.
Во время сканирования iPhone строит подробную 3D-модель лица человека и требует, чтобы глаза были открыты. Такой подход сводит на нет почти все методы манипуляции, включая показ фотографии, видеозаписи, поднесение смартфона к лицу спящего человека и так далее.
Но у этого механизма есть фундаментальный изъян. При сканировании лица человека в очках он не может полагаться на 3D-сканирование глаз и переключается на куда более простой алгоритм: если в районе глаз есть белая точка на черном фоне — глаза считаются открытыми. Достаточно взять любые очки, наклеить на них два кусочка черной изоленты, нарисовать в их центре белые кружки, и вуаля: надеваем очки на спящего человека, подносим к его лицу смартфон — и экран разблокирован.
Очки для обмана Face ID
Реверс-инжиниринг прошивок IoT-устройств
How to Start IoT device Firmware Reverse Engineering? — введение в реверс-инжиниринг прошивок различных IoT-устройств, таких как роутеры, камеры, устройства для умного дома и так далее. Статья короткая, простая, но содержит несколько вводных рекомендаций, которые могут пригодиться новичкам.
- Любой реверс начинается с поиска самой прошивки. Обычно ее можно скачать с сайта производителя или на форумах.
- Зачастую прошивки распространяются в zip-архиве, внутри которого находится файл с расширением .bin.
- Обычно файл .bin — это сплав из загрузчика, ядра Linux и образов одного или нескольких разделов. Чтобы узнать адреса смещений, по которым находятся эти образы в файле, можно использовать утилиту :
- Адрес смещения можно использовать, чтобы извлечь образ раздела с помощью утилиты (в данном случае образ корневой файловой системы squashfs):
- Получить содержимое файловой системы squashfs позволяет утилита :
- На этом все, можно начинать анализ содержимого прошивки.
Типы MVP
Существует несколько основных подходов к созданию MVP. В зависимости от этого выделяют несколько типов такого продукта.
Волшебник страны Оз
Волшебник страны Оз использовал трюки, чтобы притворяться тем, кем он на самом деле не был. То же можно сказать о данном типе MVP. Продукт только кажется функциональным, но на самом деле его разработчик делает всю работу вручную. Это нужно для того, чтобы проверить саму концепцию продукта и понять, востребован ли он. Так развивался сайт заказа обуви Zappos. Изначально у авторов идеи не было ни склада, ни закупленных партий товара, а существовал лишь сайт с фотографиями обуви. Когда ее начали заказывать, разработчики обновили функциональность сайта.
MVP-консьерж
Продукт работает по тому же принципу, что и в случае с Волшебником страны Оз: изначально все работы выполняются вручную. Однако клиенты при этом осознают, что за товаром или услугой стоит человек. Сотрудники службы финансового планирования и инвестиций Wealthfront изначально общались напрямую с клиентами, которым нужна была помощь в управлении капиталом, а автоматизированная система появилась позднее. Такой тип MVP помогает сформировать план развития продукта и собрать фидбэк от целевой аудитории.
Разрозненный MVP
Продукт с одним параметром
Это рабочий продукт с минимальным набором функций, которые нужно проверить. Такой тип MVP позволяет сформировать целевую группу, получить обратную связь и проанализировать ее, а также провести тестирование функциональности.
Место автоматизации GUI в процессе разработки
Для успешного тестирования с применением автоматизации необходимо определиться с местом автотестов в процессе разработки. Поскольку при помощи автоматизации GUI покрываются в основном регрессионные сценарии, то есть смысл запускать тесты для каждой новой сборки. Для этого мы используем Jenkins. После каждого успешного билда автоматически стартует сборка проекта с тестами. Также есть возможность ручного запуска или по расписанию, для запуска тестов ночью — в момент минимальной нагрузки на тестовые стенды.
Инструменты для автоматизации GUI
Путем проб и ошибок мы в Ukad пришли к следующему инструментарию для GUI автоматизации:
- Java — как язык для написания тест-скриптов.
- Maven — для сборки проекта.
- Selenide — как фреймворк для написания GUI тестов.
- TestNG — как фреймворк для управления запуском тестов.
- Selenoid — для непосредственного управления сессиями браузера.
- Allure — для создания и эффектной презентации отчета.
- Jenkins — для непрерывной интеграции тестов в процесс разработки.
Более подробно об инструментах и причинах, почему мы выбрали именно этот набор:
- Java. Мы используем Java, так как это путь наименьшего сопротивления ведь сообщество просто огромно, что дает доступ к большому количеству готовых решений для тестирования и не только. Это в свою очередь позволяет не тратить много времени на исследование и решение часто возникающих проблем, так как очень велика вероятность того, что решение уже найдено.
- Maven. Можно использовать любой другой сборщик. Для автотестов это не принципиально, но лично мне Maven ближе.
- Selenide позволяет не изобретать свой велосипед для решения стандартных проблем Selenium (таких как ожидания и поиск элементов на странице, добавление «мягких» проверок и т. д.) и значительно повысить скорость разработки и стабильность тестов.
- TestNG. Мы перешли с Junit на TestNG для использования наборов на основе .xml файлов, а также возможности объединения тестов в группы.
- Selenoid. Мы используем Selenoid вместо Selenium Hub, так как он более стабилен и позволяет запускать сессии браузеров в Docker контейнерах, плюс добавляет такие приятные бонусы, как просмотр выполнения конкретного теста и запись видео его прохождения.
- Allure. Позволяет значительно расширить возможности стандартного TestNG отчета, эффектно и удобно презентовать всю информацию о пройденных сценариях. В репорте каждый член команды сможет найти для себя полезную информацию. Начиная от времени и количества пройденных сценариев с результатами прохождения, до прикрепленного видео прохождения и скриншотами для упавших тестов.
- Jenkins. Мы используем Jenkins для сборки некоторых своих проектов, поэтому мы решили использовать его же для сборки тестов. Также с Jenkins удобно интегрировать Allure репорты при помощи дополнительного плагина.
Настройка проекта
Идея Qt Test заключается в том, что каждый тестовый случай должен быть независимым исполняемым файлом и иметь собственный проект.
Самый быстрый способ создать проект – использовать шаблон «Проект автотестирования» (Auto Test Project), который находится в группе «Другой проект» (Other Project) диалогового окна «Новый проект» (New Project).
Рисунок 1 – Создание проекта автоматического тестирования в Qt Creator для модульного тестирования кода на C++ с помощью Qt Test
Мастер проведет вас через настройку проекта. В частности, в разделе «Подробнее» (Details) можно указать несколько параметров.
Рисунок 2 – Детали настройки проекта автотестирования в Qt Creator
«Имя теста» (Test case name) будет именем класса, представляющего юнит-тест.
Если вы не хотите использовать мастер проекта, вам нужно добавить в переменную в qmake файле проекта:
Если в вашем модульном тесте нет элементов графического интерфейса, можно отключить модуль :
GUI
GUI — у любого тестируемого предмета и веб-приложения есть внешний вид, поэтому тестирование графического интерфейса или попросту, внешнего вида — это самое первое, что мы можем сделать. Сравнить его с требованиями и/или с макетом и все. Или не все? А как насчет верстки?
Верстка — размещение элементов веб-приложения (изображения, текст, кнопки, видео…) в соответствии с макетом или требованиями.
Проверяем:
- наличие всех элементов;
- их размер и цвет;
- расположение относительно друг-друга.
Все? — Нет У верстки есть еще множество параметров и элементов, которые мы очень часто забываем проверить.
Сравнение с макетом — метод наложения готового эталонного макета (обычно psd-файл) на приложение в экране браузера, все несовпадения можно рассматривать как ошибки (для этого есть хороший инструмент Pixel Perfect).
Измерение размеров элемента — если это имеет значение, то померять размеры элемента и сравнить их со спецификацией можно с помощью, например Page Ruler.
Правильность шрифтов (название, размер, цвет) — WhatFont.
Цвета интерфейса — ColorZilla.Контент — проверить на наличие орфографических и грамматических ошибок (SpellChecker).
Появление курсора — довольно часто мы забываем проверить, появляется ли вообще и как выглядит курсор в полях ввода, на кликабельных элементах.
Фавикон — такая маленькая незначительная вещица, но может изрядно подпортить впечатление пользователя (в моей практике были случаи, когда разработчики или дизайнеры шаблона оставляли фавикон с логотипом своей компании на сайте у заказчика).
Обозначение возможности переноса элементов.
Кодировка (UTF8…).
Стандарты HTML/CSS — достаточно неплохие решения для быстрой проверки предлагает W3C.
Заголовки по всему приложению должны быть приведены к одному стандарту (пример).
Title страницы — о нем мы тоже часто забываем, также как и разработчики
Back button — достаточно часто встречается ошибка при переходе на какую-то страницу и нажатии на браузерную кнопку Back, предыдущая страница крашится или возврат на нее вовсе не осуществляется.
Масштабируемость — особенно это важно при тестировании на смартфонах и планшетах. Где пользователь часто меняет масштаб экрана (Window Resizer), а также режим адаптивного дизайна (например в FireFox Developer Edition)
Кроссбраузерность — одна и та же страница может выглядеть по-разному в разных браузерах (пример).
Проверяем Scroll.
Браузерные расширения, которые могут влиять на внешний вид приложения (например, AdBlock) — пробуем включить и отключить.
Проверить контент при отключенных (режим WebDeveloper) изображениях, flash, JavaScript.
Все? — Нет
Локализация — что мы знаем об этом? Обычно наши знания сводятся к невнятным «ну, это язык», «кодировка», «раскладка», еще реже «геолокация». Что еще мы так часто забываем проверять в рамках тестирования локализации?
Проверяем тестовый образец на правильность перевода — тут, конечно, хорошо бы подключить переводчика или носителя языка, но за неимением таких, берем тестовый образец и переводим через любой онлайн-переводчик (ну и все мы помним, как прекрасно и весело читать описание товаров на русском языке на AliExpress).
Длина переведенных слов — количество символов в переведенном слове может быть гораздо больше (пример), что может привести к «расползанию» интерфейса при переводе.
Сокращения/аббревиатуры — существуют правила, по которым их либо переводят, либо транслитерируют, либо оставляют как есть.
Валюта.
Параметры шрифта могут также значительно отличаться в зависимости от языка ввода.
Проверить работу поиска во всех локализациях — к примеру, на AliExpress результаты поиска одного и того же слова «смартфон» дают разный результат по количеству найденных товаров, причем разница исчисляется десятками тысяч.
Мета-информация (keywords/title/description) — столь незначительное для пользователя, невидимое, но такое важное для поисковых машин и продвижения сайта в гугле и других поисковиках.
RTL (right to left languages) — языки c обратным написанием (арабский, иврит) имеют свои особенности: числа пишутся слева направо, значки и иконки отзеркаливаются, названия программ не переводятся, нет переносов, кнопки редактирования Backspace и Delete работают наоборот.
Библиотеки
- AndroidX Tech — сайт с дополнительной информацией о библиотеках семейства Android X;
- Colibri — библиотека для автоматизированного тестирования UI приложения;
- Ulfberht — написанный на Kotlin DI-фреймворк;
- Submarine — всплывающая панель навигации;
- Coil — написанная на Kotlin библиотека для загрузки изображений, быстрая и легкая альтернатива Picasso и Glide;
- sign-in-with-apple-button-android — Android-библиотека для аутентификации с помощью сервиса Sign In with Apple;
- finch — панель для инспекции okHttp-трафика;
- kotlin-multiplatform-template — готовый темплейт для мультиплатформенного Kotlin-приложения, в комплекте: бэкенд, фронтенд, Android-приложение и iOS-приложение;
- Bulldog — библиотека, упрощающая работу с SharedPreferences;
- SimpleGenericAdapter — универсальный адаптер для RecyclerView;
- ProgressView — анимированный гибко настраиваемый виджет прогресса;
- BottomNavigator — библиотека для навигации между фрагментами с помощью табов в нижней части экрана.
Читать новость в источнике Xakep
4.2 UI интерфейс интерфейса
Чтобы хорошо понять MVP, у вас должна быть возможность взаимодействовать с пользовательским интерфейсом. Посмотрите на интерфейс ниже и выделите пользовательский элемент управления, отмеченный красным, чтобы получить интерфейс ниже.
public interface IUserAdd { event EventHandler UserAddEvent; string UserName { get; set; } string UserAge { get; set; } }
Два поля ввода в интерфейсе разделены на два атрибута: UserName и UserAge. Событие нажатия кнопки «Сохранить» абстрагируется в событии UserAddEvent. Код для реализации этого интерфейса в winform выглядит следующим образом:
public partial class UserAdd : UserControl, IUserAdd { public event EventHandler UserAddEvent; public string UserName { set { this.txbName.Text = value; } get { return this.txbName.Text; } } public string UserAge { set { this.txbAge.Text = value; } get { return this.txbAge.Text; } } public UserAdd() { InitializeComponent(); } private void btnAdd_Click(object sender, EventArgs e) { if (UserAddEvent != null) UserAddEvent(this, e); } }
Возьмем атрибут UserAge, чтобы объяснить волшебство интерфейса UI. Когда внутренний код хочет получить значение возраста в интерфейсе, ему нужен только атрибут get, а когда он хочет обновить отображение интерфейса, ему нужен только атрибут set. В это время работа внутреннего кода интерфейса абстрагируется в операции атрибута UserAge, который не имеет отношения к конкретному отображению интерфейса.
Заключение
Выше была описана, если можно так выразиться, базовая версия паттерна, однако внутри генеральной линии возможно несколько модификаций и вариантов применения.
Например, упомянутый здесь уже неоднократно Фаулер, выделяет аж три возможных модификации MVP, это Presentation Model, Supervising Controller и Passive View. Все они отличаются исключительно способом взаимодействия Presenter-а и Представления, а точнее способами передачи данных представлению. Если мы себе позволяем передавать в Представление бизнес-объекты, вместо примитивных типов, то это Presentation Model, если же позволили Представлению знать о наличии модели и самому забирать из нее данные, то это Supervising Controller, ну а самый простой случай, когда логика Представления действительно минимальна то с нами Passive View. В каждом конкретном случае выбор между этими тремя модификациями паттерна зависит от того, на сколько умную автоматическую привязку бизнес объектов к интерфейсу Представления вы можете использовать и какая степень покрытия тестами логики Presenter-а вас устроит… Ну и, само собой, от сложности бизнес-объектов и интерфейсов.
Для реальных ситуаций, которые, как правило, несколько сложнее приведенного примера, существуют модификации паттерна позволяющие выстроить определенную иерархию. Выделяют два варианта таких иерархических паттернов – это Hierarchical Model-View-Controller (HMVC) и Presentation-Abstraction-Control (PAC), который пришел из мира Java. Отличие заключается в том, что HMVC позволяет выстраивать независимые иерархии, отдельно для Представлений, отдельно для Контроллера/Presenter-а, ну и само-собой для Модели, с прямыми ссылками между собой, то есть, например, Представление может ссылаться непосредственно на дочернее Представление. В свою очередь PAC, более строгий паттерн, и предписывает иметь связи между собой только Контроллерам, другие сущности доступны извне исключительно через свой Контроллер.
В целом, применение MVP, вместо уже ставшего традиционным Document-View, с одной стороны, несколько увеличивает объем ручного кодирования, однако с другой, позволяет покрыть большую часть логики тестами, уменьшает связность между компонентами и может служить основой для реализации механизма «скинов» (оболочек, шкурок) приложения, вплоть до того, что для одного и того же «движка», можно иметь как Win, так и Web «шкурку».