Unit-тестирование мобильных приложений
на примере платформы iOS
Роман Петров, технический директор Omega-R
Зачем писать юнит-тесты?
Зачем писать юнит-тесты?● Быть уверенным в том, что ваш код работает как надо.● Продолжать быть уверенным в этом после внесения изменений
(защита от регрессии).● Сокращать время ручного тестирования (как программистов, так и
тестировщиков).● Эффективно использовать системы непрерывной интеграции (без
авто-тестов смысла в них становится меньше).● Повышать ЧСВ: «Я могу в юнит-тесты!»
Почему многие не пишут юнит-тесты?
«Тут ломаться нечему!»
«Я же крутой, я и без тестов правильно напишу!»
«Чукча не читатель, чукча писатель!»
«Как на ЭТО вообще можно тесты написать?»
Немного теории
Немного теории● Юнит-тесты — они же модульные тесты.● Минимальный модуль в ООП — класс.● Тестируем каждую нетривиальную функцию.● Пишем более комплексные тесты на взаимосвязанные функции.● Пишем как положительные, так и отрицательные тесты.● Аксиома: НИКОГДА не верь входным данным, даже если данные дает
твой собственный код.● В сферическом приложении в вакууме все функции являются
«чистыми», а классы — абсолютно изолированы.● Реальность кусается.
Средства тестирования на мобильных платформах
iOSXCTest — родное средство для юнит-тестов, умеет все: собственно юнит-тесты, тесты асинхронных процессов, замеры производительности, тестирование UI.
OCMock — средство для создания mock-объектов (полноценно работает только с Objective-C).
KIF Framework — более удобное средство для автоматизации тестирования UI.
AndroidJUnit — стандартный фреймворк для написания юнит-тестов на Java, тесты запускаются в виртуальной машине Java на компьютере.
Espresso — фреймворк для тестирования UI (входит в Android Testing Support Library).
AndroidJUnitTestRunner — средство для запуска JUnit-тестов на реальных устройствах и симуляторе.
Windows PhoneВ среде MS Visual Studio есть все необходимые инструменты как для модульного тестирования, так и для интерфейсного тестирования.
Что надо тестировать?
В идеале
ВСЁ
В реальностиРасставим приоритеты:
● Весь код модели (в паттерне MVC).● Работа с API (как со своим, так и с чужим).● Use cases (без UI).● Производительность критических участков.
Перестаем бояться тестов и начинаем их писать
Тестируем факториалХороший Плохой
Тестируем факториалВсе хорошо
Почти все плохо
Измеряем производительность
Измеряем производительность
Более практические примеры
Тест работы с API: делаем это правильноНеобходимо разорвать зависимость (если она есть) и определить протокол. В Objective-C можно использовать OCMock, но лучше и в нем использовать протоколы.
Тест работы с API: делаем это правильно
Тестируем работу с CoreDataНе включаем классы сущностей в тестовый таргет и импортируем модуль приложения в классе теста. Классы сущностей надо будет сделать публичными.
Тестируем работу с CoreData
Тест на вызов метода делегатаВ OCMock есть готовое средство для таких тестов, но работает это, опять же, только в Objective-C. Поэтому на Swift пишем сами.
Тест на вызов метода делегата
Общие методы в нескольких наборах тестов
Очевидно, но не очень правильно
Наследование приводит к появлению лишнего пустого набора тестов
ПравильноРасширение класса
Протокол с реализацией по умолчанию
Пример использования
Как улучшать архитектуру, чтобы тесты писались легче (и вообще писались)
Улучшаем архитектуру● Чистые функции и чистые классы● Разрыв зависимостей● Один класс — одна задача (single responsibility)● Применяем паттерны проектирования
Благодарю за внимание!А теперь время для вопросов