Хочу представить вашему вниманию библиотеку для unit тестирования Android приложений от Google. Espresso была анонсирована 23 апреля прошлого года на Google Test Automation Conference 2013. В октябре прошлого года она стала официально Open Source проектом. Что же из себя представляет эта библиотека, мы рассмотрим ниже.
GoogleInstrumentationTestRunner
oogleInstrumentationTestRunner, наследник стандартного InstrumentTestRunner, который был улучшен. Одно из самых главных его достоинств, то что он гарантирует выполнение теста после запуска и старта приложения. Другими словами, он гарантирует что все тесты будут стартоваться после выполнения onCreate (если это условие не выполняется то это может привести к неожиданным исключениям). Так же гарантирует что все запущенные активити завершаться до окончания отработки GoogleInstrumentationTestRunner. Поддерживает тесты начиная с Api 8.
Версия 1.1
8 января 2014 вышла новая версия. Что нового:
- Включена поддержка свайпов. Это очень хорошее дополнение, так как до этого нужно было писать свой кастомный обработчик;
- Поддержка multi-window;
- Исправлены баги.
От автора
Прежде чем переходить от теории к практике, хочется поделится своими впечатлениями. Библиотека очень молодая, ей нету ещё и года. Но работает таки стабильно и выходила она сразу с версии 1.0, что уже говорит о том что она вышла не просто ради бета/альфы теста. Писать с её помощью тесты очень приятно, так как много функционала она берёт на себя. Например, не нужно делать фокус на кнопке, проверять доступна ли она на экране и т.д., с Espresso вам достаточно обратится к кнопке по её id или text/description и Espresso уже всё сделает за вас, если кнопка не видна или не доступна на экране то тест автоматом уже не пройдёт. Они действительно сделали большой упор на UI.
Парни с тех поддержки (они же и разработчики сего чуда) стараются максимально быстро и развернуто давать ответы на ваши вопросы. Мне довелось немножко с ними пообщаться. Так вот, самый главный вопрос который им задавали «Чем Espresso лучше Robotium?». Они говорят, что Robotium действительно хороша, но самой главной причиной, по которой они решили написать свой фреймворк это скорость выполнения тестов и их не всегда стабильность. Они уверяют что Espresso работает намного быстрее чем другие фреймворки (хотя цифры не приводят, я постараюсь в ближайшее время сделать сравнения). Но ещё одна не мало важная особенность, это то что Espresso использует синхронизацию с Main Thread. Instrumentation запускается в отдельном потоке, без синхронизации тестов с обновлением UI возникают проблемы со скоростью и могут возникнуть критические ошибки в самих тестах. Большинство разработчиков игнорируют этот факт и ставят задержки в потоке (sleep), что есть уже не правильно. С Espresso вам этого делать уже не надо будет. Robotium в свою очередь не использует синхронизацию, что влечёт за собой присыпания потоков и медленное выполнение тестов. Изначально все приложения Google тестировались при помощи Robotium, потому что в тот момент не было времени писать свой инструментал. Покрыть тестами свои проекты вы сможете до 95%!
Ещё была ситуация когда мне понадобилось запустить тестовый проект в своем Application. Казалось бы, всё просто, переопределил стандартный, подставил в манифест и всё. Но как оказалось тесты все работают в том же Application что и приложение. Понимаю, что это логично, но вот такая реализация оказалась не возможной.
От теории к практики
Основные классы:
- Espresso – основной класс. Содержит в себе статические методы, такие как нажатия на системные кнопки (back, home), вызвать/спрятать клавиатуру, открыть меню, обратится к View;
- ViewMatchers – коллекция объектов для нахождения View на экране;
- ViewActions – используется для обработчиков View (click, longClick, doubleClick, swipe, scroll и т.д.);
На Espresso стоит переходить хотя бы за её простоту. Работа с View пишется в одну строчку. Напишем простой пример для ввода данных в EditText и нажатие на кнопку:
@SmallTest
public void testSendMessageUI()
{
Espresso.onView(ViewMatchers.withId(com.eleks.espresso.example.app.R.id.etEmail)).perform(ViewActions.typeText("test@test.com"));
Espresso.onView(ViewMatchers.withId(com.eleks.espresso.example.app.R.id.etMessage)).perform(ViewActions.typeText("Espresso"));
Espresso.onView(ViewMatchers.withId(com.eleks.espresso.example.app.R.id.btnSend)).perform(ViewActions.click());
}
Всё просто. Ищется View на экране при помощи ViewMatchers по id, вводится текст имитируя человеческий ввод. Далее находится кнопка и происходит событие onClick по ней. Попробуйте спрятать кнопку и вы увидите, что тест не пройдёт так как Espresso просто не найдёт её на экране.
@SmallTest
public void testOpenNavigationDrawer()
{
Espresso.onView(ViewMatchers.withId(com.eleks.espresso.example.app.R.id.content_frame)).perform(ViewActions.swipeRight());
ListView lvDrawerMenu = (ListView) getActivity().findViewById(com.eleks.espresso.example.app.R.id.lvDrawerMenu);
Preconditions.checkNotNull(lvDrawerMenu, "lvDrawerMenu is null");
final int count = lvDrawerMenu.getAdapter().getCount();
Preconditions.checkPositionIndex(2, count, "No 1 index " + count + " size");
Object obj = lvDrawerMenu.getItemAtPosition(2);
Espresso.onView(Matchers.allOf(ViewMatchers.withId(com.eleks.espresso.example.app.R.id.tvItem), ViewMatchers.hasSibling(ViewMatchers.withText(obj.toString())))).perform(ViewActions.click());
}
В этом примере делается свайп вправо и открывается NavigationDrawer. Далее в происходит событие onClick по третьей ячейке листа. Класс Preconditions используется для проверки входных данных. Им удобно проверять null, выход за границы массива, проверка позиции, проверка значения и т.д. Далее мы ищем любую View с значением, которое мы предварительно вытянули с листа.
Для более лучшей надёжности и совместимости тестов, разработчики Espresso рекомендуют метод onView и класс ViewMatcher который сам ищет View на активити, вместо привычной нам findViewById. Но в таком случае приходится писать кастомные обработчики и методы, так как если мы найдём View при помощи ViewMatcher, то багаж методов которые мы можем вызвать будет ограничен. Но в любом случае Espresso движется в правильном направлении и её разработчики пытаются сделать так что бы написание тестов было как можно более приятным.
Example на Github
Где скачать Espresso
Автор: viacheslav_dev