35. Тестирование
/**
* Synchronously wait for the application to be idle. Can not be called
* from the main application thread -- use {@link #start} to execute
* instrumentation in its own thread.
*/
public void waitForIdleSync() {
validateNotAppThread();
Idler idler = new Idler(null);
mMessageQueue.addIdleHandler(idler);
mThread.getHandler().post(new EmptyRunnable());
idler.waitForIdle();
}
36. Тестирование
• Ui Test Framework
• Ui Automator
• Robotium/Espresso
• Appium
• …
Test Support Library
Добрый день, меня зовут Кирилл, я занимаюсь разработкой мобильной почты в Mail.Ru,
Сегодня я расскажу о нашем опыте оргинизации процесса сборки мобильного приложения.
Сразу скажу что это не гайдлайн, не учебник. Это то, как мы видим задачи, которые решаются за счет правильного организованного процесса сборки.
Кто-то сможет узнать что-то полезное для себя и своего проекта, а кто-то просто послушает альтернативный подход для привычных задач.
На самом деле рассказывая про сборку нужно вернуться чуть назад и посмотреть что мы будем собирать
В разных командах разный флоу, завязанный на ветки
Ключевой момент здесь с точки зрения процесса разработки это то, что мы должны без лишних манипуляций получать билд как в фичовой ветке, так и в основной ветке, в любой интеграционной ветке, хотфиксе и т.д.
С точки зрения всей разработки, особенно в большой команде, это дает преимущество, которое сложно переоценить – ИЗОЛИРОВАННОЕ ТЕСТИРОВАНИЕ
Имеет как плюсы так и минусы
Держать ветку в актуальном состоянии
Тестировать последние изменения
Раньше узнавать о конфликтах
Вот после того как мы вытащили правильные сорцы, мы можем приступать к упаковке кода в APK
Итак сборка. Сборка безусловно у нас используется в единственном числе. Но как и все нормальные менеджеры, наши, подразумевают чуть больше чем просто одна apk:
Начнем с того что это три разных продукта, назовем их A, B и C
Начнем с того что это три разных продукта, назовем их A, B и C
Начнем с того что это три разных продукта, назовем их A, B и C
Начнем с того что это три разных продукта, назовем их A, B и C
Начнем с того что это три разных продукта, назовем их A, B и C
Все это делает конфигурацию проекта очень гибкой.
Мы можем избегать странных условий, свитч кейзов и прочих гадостей в коде проекта
Вместо этого мы просто подставляем уже правильные значения во время сборки приложения
Таким образом можно скрыть за абстракцией различные реализации фич, включать\выключать целые разделы в приложении и многое другое.
Идеальных вариантов не бывает
Общие ресурсы, например разметка написания письма
Дублирование – плохо, зашиваться на то что все должно быть одинаково – тоже.
Идеальных вариантов не бывает
Общие ресурсы, например разметка написания письма
Дублирование – плохо, зашиваться на то что все должно быть одинаково – тоже.
Идеальных вариантов не бывает
Общие ресурсы, например разметка написания письма
Дублирование – плохо, зашиваться на то что все должно быть одинаково – тоже.
Идеальных вариантов не бывает
Общие ресурсы, например разметка написания письма
Дублирование – плохо, зашиваться на то что все должно быть одинаково – тоже.
Идеальных вариантов не бывает
Общие ресурсы, например разметка написания письма
Дублирование – плохо, зашиваться на то что все должно быть одинаково – тоже.
ВАЖНО – набор для каждого продукта не должен содержать дубликатов
ВАЖНО – набор для каждого продукта не должен содержать дубликатов
Остается запустить gradle task и собрать либо все сразу, либо что-то конкретное.
Таким образом сборку можно распараллелить
Автоматизированное тестирование – тренд последних пары лет
Все об этом говорят, но никто не видел
Проверки можно делать разные. Не стоит зацикливаться на каком-то одном варианте, для каждой проблемы нужно выбирать способ, который лучше всего подходит.
я не знаю почему этому подходу уделяется так мало внимания, потому что
это очень мощный инструмент, который позволяет применять формализованные правила ко всему проекту, а не к отдельным классам.
Android – lint
Find bugs
В каждой команде есть свои правила
Конвенции, за которыми сложно следить
Не совсем статический анализ, но статические проверки, - проверки которые выполняются с помощью хуков репозитория
Например отсутствие SNAPSHOT версий библиотек в основной ветке разработки
Здесь по большому счету все обыденно. На некоторые классы написаны проверки, которые позволяют убедиться, что класс работает именно так как задумывалось и заодно показывают клиенту класса пример как им можно воспользоваться.
Главная техническая особенность юнит тестов это возможность мокать ответы зависимостей класса. Для этого етсь многие фреймворки, которые поддерживаются и могут быть использованы в android проектах.
Это удобно когда нужно замокать вызов какой-то функции, поведение какого-то класса.
Сложнее, когда речь идет о том, чтобы мокать сетевое взаимодействие.
Оказывается, что не все знают что делается это достаточно просто – через подстановку UrlStreamHandler’а при этом не нужно ни одной строчки менять в коде, который выполняет сетевой запрос
Выглядит это все вот так
В этом тесте мы делаем честный запрос на сервер, то есть команда работает абсолютно так же как и в приложении.
Проблема в том, что юнит тест зависит от того как настроена сеть на девайсе, на котором он выполняется.
А ниже идет второй тест, который проверяет абсолютно то же самое, но уже подставляя желаемый ответ, не выполняя реального запроса и не взаимодействуя с сервером.
Таким образом мы имеем возможность управлять тем, как тесты выполняются, это нужно например, для того, чтобы статус билда не учитывал то, как ответил нам сервер.
Мы закладываемся на протокол.
Однако, например, для ночной сборки, неплохо было бы убедиться еще и в том, что контракт с сервером не нарушен
Дело в том, что мы не хотим постоянно зависеть от сервиса, но хотим мониторить ситуацию и в виде ежедневных отчетов получать информацию о том, что все в порядке или о том, что какая-то часть приложения не в порядке.
Здесь я предпочитаю разделять наше приложение и сторонние сервисы, которые критичны для полноценной работы приложения, но не являются зоной нашей ответственности. Мы можем обнаружить проблему в нашем приложении, связанную с работой стороннего сервиса, но мы не сможем ее поправить.
Наша задача состоит в том, чтобы сообщить о проблеме, дождаться исправления и прогнать тесты на работу с этим сервисом, чтобы убедиться в том, что проблема устранена.
Все как завещал Фаулер – тесты должно быть легко писать, легко запускать, тогда они будут помогать, а не мешать.
С точки зрения пользователя - самые честные тесты.
С точки зрения разработчика - самые сложные.
Самые честные потому что тестируют конечный продукт, а не какую-то его часть.
То есть по определению не получится свалить вину на кого-то другого. Если письмо не открылось, значит это баг приложения. И плевать, баг из-за несовершенства android’а, либо подвели кривые руки другого разработчика, либо что-то еще.
Факт остается фактом и ошибку нужно исправить
Если Unit-testы больше для того, чтобы разработчик убедился в том, что его код работает именно так как он задумывал, то ui-testы больше для того, чтобы продуктовая команда убедилась в том, что пользовательские сценарии в приложении отрабатывают корректно.
TDD
В этом случае нет необходимости в том, чтобы задействовать весь бюррократический аппарат, в котором несколько человек должны проаппрувить, что баг исправлен, что ничего нового не сломалось и т.д.
Вся соль в том, что если тест написан вдумчиво и целью написания теста было обнаружение и выявление проблемы, то такой тест уже дает повод считать проблему решенной, если он успешно проходит.
Чем больше таких кейзов закрыто тестами, тем качественне является проверка, потому что выше вероятность, что мы ничего не упустили.
На рынке их много
Исторически мы в проекте Почта Mail.Ru использовали Robotium. Это весьма известное решение, которое используется большим количеством команнд как у нас в стане так и за рубежом.
Что объединяет всех пользователей фреймворка - так это нелюбовь к этому самому фреймворку
Его использование, как мы на своем опыте убедились, решает большинство проблем с тем, что View не найдена, хотя скрины показывают, что все отображается, с тем, что View находится в промежуточном состоянии анимируя свои свойства от одного значения к другому и т.д.
С появлением test Support library тестирование стало намного проще.
Не нужно выбирать какой-то один фреймворк, можно пользоваться тем что удобно даже внутри одного тестового сценария, например
Мы проверили, сделали все возможные тесты и убедились, что приложение отвечает всем заявленным требованиям качество
запускаем
Мы проверили, сделали все возможные тесты и убедились, что приложение отвечает всем заявленным требованиям качество
Мы проверили, сделали все возможные тесты и убедились, что приложение отвечает всем заявленным требованиям качество
Мы проверили, сделали все возможные тесты и убедились, что приложение отвечает всем заявленным требованиям качество