SlideShare a Scribd company logo
1 of 22
Тестируемая rxJava
Виктория Сулейманова
Rambler&Co
Observable
Observable
Observable
Observable
Observable
filter
init
sort
map
2
Observer pattern
3
Observable SubscriberData
Subscriber
4
subscribeOn & observeOn
5
Преобразование списка видов
спорта в последовательность их
названий
6
Mockito
7
Тестирование логики
преобразования
последовательности
8
BlockingObservable
9
TestSubscriber
10
TestScheduler
11
Виртуальное время
12
Data1 Data2 Data3
20 сек 8 сек
triggerActions()
advanceTimeTo(28, TimeUnit.SECONDS)
advanceTimeBy(20, TimeUnit.SECONDS)
advanceTimeBy(8, TimeUnit.SECONDS)
Постановка задачи
13
Twitter
текстовый блок с «Чемпионат»
Тестирование корректной
последовательности при дозагрузке
данных
14
Анонимный Subscriber
15
…
Тестирование анонимного
Subscriber
16
Именованный
Subscriber
17
Тестирование
именованного Subscriber.
TestSubject
18
Rx Plugins: Пример
логирования
19
Creating class rx.internal.operators.OnSubscribeRange
Creating class rx.internal.operators.OnSubscribeMap
Creating class rx.internal.operators.OnSubscribeFilter
Rx Plugins: Подмена стандартных Schedulers:
io, computation, newThread
20
Hello from: main
Выводы
• Код с rxJava - тестируемый
• Нужно помнить о правильных Schedulers в тестовом окружении
• TestSubscriber и TestScheduler позволяют с легкостью
протестировать любой Observable
• TestSubject отлично подходит для тестирования именованных
Subscribers
21
Ответы на часто задаваемые
вопросы
flatMap, concatMap, switchMap - в чем разница?
• flatMap - получим все onNext от предыдущего Observable, но порядок их не
гарантируется
• concatMap - получим все onNext только после завершения предыдущего Observable
• switchMap - отписывается от всех предыдущих Observable, какие-то onNext можем не
получить
Scheduler.io() vs Scheduler.computation()?
• io - количество потоков в пуле не ограничено, добавляется новый поток по
необходимости, хорошо для использования нересурсоемких задач т.к. переключение
между потоками затратная операция
• computation - число потоков равно числу ядер процессора, подходит для интенсивных
задач
22

More Related Content

What's hot

Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Ontico
 
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))Noveo
 
Java осень 2013 лекция 6
Java осень 2013 лекция 6Java осень 2013 лекция 6
Java осень 2013 лекция 6Technopark
 
В ногу со временем, или как делать upgrade PostgreSQL / Андрей Сальников (Dat...
В ногу со временем, или как делать upgrade PostgreSQL / Андрей Сальников (Dat...В ногу со временем, или как делать upgrade PostgreSQL / Андрей Сальников (Dat...
В ногу со временем, или как делать upgrade PostgreSQL / Андрей Сальников (Dat...Ontico
 
Курс Java-2016. Занятие 07. Логи, фасады, библиотеки и коллекции
Курс Java-2016. Занятие 07. Логи, фасады, библиотеки и коллекцииКурс Java-2016. Занятие 07. Логи, фасады, библиотеки и коллекции
Курс Java-2016. Занятие 07. Логи, фасады, библиотеки и коллекции7bits
 
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)Noveo
 
monit — простой мониторинг
monit — простой мониторингmonit — простой мониторинг
monit — простой мониторингAndrew Pantyukhin
 
Система управления автоматическими тестами на примере использования Visual St...
Система управления автоматическими тестами на примере использования Visual St...Система управления автоматическими тестами на примере использования Visual St...
Система управления автоматическими тестами на примере использования Visual St...SQALab
 
Оптимизация – стоимость владения
Оптимизация – стоимость владенияОптимизация – стоимость владения
Оптимизация – стоимость владенияАнастасия Масенко
 
Некриптографическое исследование носителей православной криптографии
Некриптографическое исследование носителей  православной криптографииНекриптографическое исследование носителей  православной криптографии
Некриптографическое исследование носителей православной криптографииSergey Soldatov
 
Android - 11 - Multithreading
Android - 11 - MultithreadingAndroid - 11 - Multithreading
Android - 11 - MultithreadingNoveo
 
Android: Как написать приложение, которое не тормозит
Android: Как  написать приложение, которое не тормозитAndroid: Как  написать приложение, которое не тормозит
Android: Как написать приложение, которое не тормозитElena Kotina
 
implementation of 'go'-like language constructions in scala (russian)
implementation of 'go'-like language constructions in scala (russian)implementation of 'go'-like language constructions in scala (russian)
implementation of 'go'-like language constructions in scala (russian)Ruslan Shevchenko
 
Database First! О распространённых ошибках использования РСУБД
Database First! О распространённых ошибках использования РСУБДDatabase First! О распространённых ошибках использования РСУБД
Database First! О распространённых ошибках использования РСУБДNikolay Samokhvalov
 
QA Fest 2018. Святослав Логин. Что такое Metasploit? Как его использовать для...
QA Fest 2018. Святослав Логин. Что такое Metasploit? Как его использовать для...QA Fest 2018. Святослав Логин. Что такое Metasploit? Как его использовать для...
QA Fest 2018. Святослав Логин. Что такое Metasploit? Как его использовать для...QAFest
 
Практическое применение HTML5 в Я.Почте
Практическое применение HTML5 в Я.ПочтеПрактическое применение HTML5 в Я.Почте
Практическое применение HTML5 в Я.ПочтеAlexey Androsov
 
FreeRTOS
FreeRTOSFreeRTOS
FreeRTOSquakke
 
Курс Java-2016. Занятие 08. Итераторы, многопоточность
Курс Java-2016. Занятие 08. Итераторы, многопоточностьКурс Java-2016. Занятие 08. Итераторы, многопоточность
Курс Java-2016. Занятие 08. Итераторы, многопоточность7bits
 

What's hot (20)

Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
 
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
 
Java осень 2013 лекция 6
Java осень 2013 лекция 6Java осень 2013 лекция 6
Java осень 2013 лекция 6
 
В ногу со временем, или как делать upgrade PostgreSQL / Андрей Сальников (Dat...
В ногу со временем, или как делать upgrade PostgreSQL / Андрей Сальников (Dat...В ногу со временем, или как делать upgrade PostgreSQL / Андрей Сальников (Dat...
В ногу со временем, или как делать upgrade PostgreSQL / Андрей Сальников (Dat...
 
Mocks and stubs
Mocks and stubsMocks and stubs
Mocks and stubs
 
Курс Java-2016. Занятие 07. Логи, фасады, библиотеки и коллекции
Курс Java-2016. Занятие 07. Логи, фасады, библиотеки и коллекцииКурс Java-2016. Занятие 07. Логи, фасады, библиотеки и коллекции
Курс Java-2016. Занятие 07. Логи, фасады, библиотеки и коллекции
 
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
 
monit — простой мониторинг
monit — простой мониторингmonit — простой мониторинг
monit — простой мониторинг
 
Система управления автоматическими тестами на примере использования Visual St...
Система управления автоматическими тестами на примере использования Visual St...Система управления автоматическими тестами на примере использования Visual St...
Система управления автоматическими тестами на примере использования Visual St...
 
Rac
RacRac
Rac
 
Оптимизация – стоимость владения
Оптимизация – стоимость владенияОптимизация – стоимость владения
Оптимизация – стоимость владения
 
Некриптографическое исследование носителей православной криптографии
Некриптографическое исследование носителей  православной криптографииНекриптографическое исследование носителей  православной криптографии
Некриптографическое исследование носителей православной криптографии
 
Android - 11 - Multithreading
Android - 11 - MultithreadingAndroid - 11 - Multithreading
Android - 11 - Multithreading
 
Android: Как написать приложение, которое не тормозит
Android: Как  написать приложение, которое не тормозитAndroid: Как  написать приложение, которое не тормозит
Android: Как написать приложение, которое не тормозит
 
implementation of 'go'-like language constructions in scala (russian)
implementation of 'go'-like language constructions in scala (russian)implementation of 'go'-like language constructions in scala (russian)
implementation of 'go'-like language constructions in scala (russian)
 
Database First! О распространённых ошибках использования РСУБД
Database First! О распространённых ошибках использования РСУБДDatabase First! О распространённых ошибках использования РСУБД
Database First! О распространённых ошибках использования РСУБД
 
QA Fest 2018. Святослав Логин. Что такое Metasploit? Как его использовать для...
QA Fest 2018. Святослав Логин. Что такое Metasploit? Как его использовать для...QA Fest 2018. Святослав Логин. Что такое Metasploit? Как его использовать для...
QA Fest 2018. Святослав Логин. Что такое Metasploit? Как его использовать для...
 
Практическое применение HTML5 в Я.Почте
Практическое применение HTML5 в Я.ПочтеПрактическое применение HTML5 в Я.Почте
Практическое применение HTML5 в Я.Почте
 
FreeRTOS
FreeRTOSFreeRTOS
FreeRTOS
 
Курс Java-2016. Занятие 08. Итераторы, многопоточность
Курс Java-2016. Занятие 08. Итераторы, многопоточностьКурс Java-2016. Занятие 08. Итераторы, многопоточность
Курс Java-2016. Занятие 08. Итераторы, многопоточность
 

Similar to Тестируемая RxJava

Java 9: what is there beyond modularization
Java 9: what is there beyond modularizationJava 9: what is there beyond modularization
Java 9: what is there beyond modularizationIvan Krylov
 
Java осень 2014 занятие 6
Java осень 2014 занятие 6Java осень 2014 занятие 6
Java осень 2014 занятие 6Technopark
 
Stream API: рекомендации лучших собаководов
Stream API: рекомендации лучших собаководовStream API: рекомендации лучших собаководов
Stream API: рекомендации лучших собаководовtvaleev
 
SECON'2017, Лесовский Алексей, Потоковая репликация в PostgreSQL.
SECON'2017, Лесовский Алексей, Потоковая репликация в PostgreSQL.SECON'2017, Лесовский Алексей, Потоковая репликация в PostgreSQL.
SECON'2017, Лесовский Алексей, Потоковая репликация в PostgreSQL.SECON
 
PostgreSQL Streaming Replication
PostgreSQL Streaming ReplicationPostgreSQL Streaming Replication
PostgreSQL Streaming ReplicationAlexey Lesovsky
 
Введение в современную PostgreSQL. Часть 1
Введение в современную PostgreSQL. Часть 1Введение в современную PostgreSQL. Часть 1
Введение в современную PostgreSQL. Часть 1Dzianis Pirshtuk
 
Производительность параметрического поиска на основе опенсорс-платформы
Производительность параметрического поиска на основе опенсорс-платформыПроизводительность параметрического поиска на основе опенсорс-платформы
Производительность параметрического поиска на основе опенсорс-платформыYandex
 

Similar to Тестируемая RxJava (8)

Java 9: what is there beyond modularization
Java 9: what is there beyond modularizationJava 9: what is there beyond modularization
Java 9: what is there beyond modularization
 
Practical usage of RxJava 2
Practical usage of RxJava 2Practical usage of RxJava 2
Practical usage of RxJava 2
 
Java осень 2014 занятие 6
Java осень 2014 занятие 6Java осень 2014 занятие 6
Java осень 2014 занятие 6
 
Stream API: рекомендации лучших собаководов
Stream API: рекомендации лучших собаководовStream API: рекомендации лучших собаководов
Stream API: рекомендации лучших собаководов
 
SECON'2017, Лесовский Алексей, Потоковая репликация в PostgreSQL.
SECON'2017, Лесовский Алексей, Потоковая репликация в PostgreSQL.SECON'2017, Лесовский Алексей, Потоковая репликация в PostgreSQL.
SECON'2017, Лесовский Алексей, Потоковая репликация в PostgreSQL.
 
PostgreSQL Streaming Replication
PostgreSQL Streaming ReplicationPostgreSQL Streaming Replication
PostgreSQL Streaming Replication
 
Введение в современную PostgreSQL. Часть 1
Введение в современную PostgreSQL. Часть 1Введение в современную PostgreSQL. Часть 1
Введение в современную PostgreSQL. Часть 1
 
Производительность параметрического поиска на основе опенсорс-платформы
Производительность параметрического поиска на основе опенсорс-платформыПроизводительность параметрического поиска на основе опенсорс-платформы
Производительность параметрического поиска на основе опенсорс-платформы
 

More from Rambler Android

Разбираемся с CoordinatorLayout
Разбираемся с CoordinatorLayoutРазбираемся с CoordinatorLayout
Разбираемся с CoordinatorLayoutRambler Android
 
Как мы измеряем наши проекты
Как мы измеряем наши проектыКак мы измеряем наши проекты
Как мы измеряем наши проектыRambler Android
 
Vector Drawable API. Возможности применения
Vector Drawable API. Возможности примененияVector Drawable API. Возможности применения
Vector Drawable API. Возможности примененияRambler Android
 
Конвейерное производство приложений
Конвейерное производство приложенийКонвейерное производство приложений
Конвейерное производство приложенийRambler Android
 
Android M: опыт личного знакомства
Android M: опыт личного знакомстваAndroid M: опыт личного знакомства
Android M: опыт личного знакомстваRambler Android
 
Google Identity Platform
Google Identity PlatformGoogle Identity Platform
Google Identity PlatformRambler Android
 
Революционный Android. Ищем замену фрагментам
Революционный Android. Ищем замену фрагментамРеволюционный Android. Ищем замену фрагментам
Революционный Android. Ищем замену фрагментамRambler Android
 

More from Rambler Android (8)

Разбираемся с CoordinatorLayout
Разбираемся с CoordinatorLayoutРазбираемся с CoordinatorLayout
Разбираемся с CoordinatorLayout
 
Как мы измеряем наши проекты
Как мы измеряем наши проектыКак мы измеряем наши проекты
Как мы измеряем наши проекты
 
Feature-toggles
Feature-togglesFeature-toggles
Feature-toggles
 
Vector Drawable API. Возможности применения
Vector Drawable API. Возможности примененияVector Drawable API. Возможности применения
Vector Drawable API. Возможности применения
 
Конвейерное производство приложений
Конвейерное производство приложенийКонвейерное производство приложений
Конвейерное производство приложений
 
Android M: опыт личного знакомства
Android M: опыт личного знакомстваAndroid M: опыт личного знакомства
Android M: опыт личного знакомства
 
Google Identity Platform
Google Identity PlatformGoogle Identity Platform
Google Identity Platform
 
Революционный Android. Ищем замену фрагментам
Революционный Android. Ищем замену фрагментамРеволюционный Android. Ищем замену фрагментам
Революционный Android. Ищем замену фрагментам
 

Тестируемая RxJava

Editor's Notes

  1. Всем привет, меня зовут Виктория Сулейманова. В Рамблере я являюсь ведущим разработчиком на проектах Чемпионат и Афиша-Рестораны. Сегодня я с вами хочу обсудить тестируемость кода, написанного с использованием библиотеки RxJava, так как реактивный стиль все сильней пронизывает критически важные участки кода наших программ, которые нуждаются в автоматизированном тестирование. Поднимите пожалуйста руки те кто использует эту библиотеку у себя в продакшн коде? А кто покрывает такой код юнит-тестами? Отлично, нам с вами тогда есть что обсудить, надеюсь что каждый найдет для себя в моем докладе что-то новое. Предлагаю для начала вспомнить за что мы так любим rxJava ->
  2. Observable. Думаю каждый из вас начинал свое знакомство с реактивным программированием на Java с этого класса. Именно этот класс позволяет нам в декларативном стиле описывать работу над потоком данных. Используя уже готовые операторы из библиотеки rxJava мы строим свой Observable куда помещаем порой достаточно сложную логику вычислений. Операторы легко комбинируются, добавляются и удаляются. Все вычисления описанные в Observable имеют отложенный характер и начинают свое выполнение только когда на него кто-то подписался, используя метод subscribe ->
  3. Такая комбинация в свою очередь реализует шаблон Наблюдатель, где Observable является генератором потока событий. Подписаться на Observable можно используя одну из множества перегрузок метода subscribe, но самым каноничным примером является перегрузка использующая в качестве параметра экземпляр класса Subscriber ->
  4. Subscriber описывает процесс доставки данных, а если говорить в терминах языка Java, то Subscriber является абстрактным классом и реализует 2 интерфейса Observer и Subscription. Интерфейс Observer содержит три метода onCompleted, onError и onNext, первые два из которых являются терминальными состояниями для цепочки вычислений, и одним из них может быть вызван не больше одного раза. Метод onNext используется для отправки и обработки сообщений представленных Java классом и таких сообщений может быть от 0 до бесконечности. Observer описывает основной контракт rxJava, подробней о нем вы сможете ознакомится по ссылке в правом нижнем углу. Subscribtion необходим для того, чтобы иметь возможность из вне отписаться, освободив связанные ресурсы, а так же прекратить досрочно цепочку вычислений. Subscriber реализует методы интереса Subscribtion и отписывается от нее после терминального состояния. Рассмотрев основную концепцию библиотеки rxJava хочется упомянуть еще об одной чудесной возможности данной библиотеки, которая для многих я думаю, стала решающей при выборе данного инструмента. ->
  5. subscribeOn и observeOn - методы которые нам позволяют с легкостью манипулировать планировщиками потоков, тем самым решать сложные вопросы асинхронности и параллелизма вычислений. Предлагаю рассмотреть на примере их работу. На экране представлен код, который осуществляет загрузку списка видов спорта с сервера, далее осуществляет фильтрацию, сортировку и преобразование списка видов спорта в последовательность их названий. Как вы можете заметить, помимо операторов преобразования, я здесь использую subscribeOn и observeOn. Обратим внимание на subscribeOn, в который я передаю планировщик потоков io. subscribeOn указывает на каком планировщике необходимо начать выполнение цепочки вычислений, а цепочка вычислений, как мы видим начинается с загрузки данных с сервера и очевидно, что осуществлять запрос на сервер нужно не в главном потоке, а если бы subscribeOn не был использован, то уверяю, так бы и произошло. Планировщик из subscribeOn актуален до первого observeOn, используя который я после загрузки данных сервера меняю планировщик на более подходящий для реализации преобразований над списком полученных данных. Методов observeOn - может быть сколько угодно, это позволяет регулировать смену планировщиков в цепочке вызовов, поэтому после окончания всех преобразований, я снова меняю планировщик, чтобы вывести результат на какое-то средство вывода. Вспомнив об основных плюшках rxJava, перейдем к написанию тестов. Протестируем этот метод, но для начала приведем его в контексте интерактора ->
  6. Как вы можете видеть теперь ранее разобранный кусок кода является реализацией метода getSportLabels класса SportInteractor, его то мы и будем тестировать. При запуске юнит-теста в тестовой среде не хочется грузить реальные данные с удаленного сервера, поэтому подменим реализацию метода loadSports класса SportProvider -> Mockito
  7. Я надеюсь все в этой аудитории знакомы с Mockito, так как на работе с этой библиотекой я останавливаться не буду. На экране приведен код создания фейковой реализации интерфейса SportProvider, который передается в объект класса SportInteractor, который мы будем тестировать. Ниже мы переопределяем поведение метода провайдера loadSports, который теперь нам возвращает список из трех видов спорта, где только 2 являются активными, фильтрация происходит по этому критерию. А сортируются объекты по рейтингу в порядке возрастания. И так тестовая среда настроена пора написать тест на метод интерактора. ->
  8. Тестируемый нами метод getSportLabels возвращает Observable, а чтобы запустить на выполнение всю закодированную там логику, необходимо на Observable подписаться, что мы и делаем, а в соответсвующих коллбэках выполняем проверки на корректность полученного результата, используя ассерты junit. Вроде как выглядит все корректно и если запустить тест, он будет пройден. Но гарантирует ли это правильно написанный код логики? Если поставить точки останова на проверках и запустить тест в режиме debug, то мы заметим что не в один breakpoint мы не попадем. А значит результаты вычислений проверены не были. Почему так произошло? Дело все в subsribeOn и observeOn, как вы помните мы входе вычислений переключаем планировщики потоков, а тест выполняется в своем потоке и завершается не дождавшись коллбеков в подписчике. что делать? самый первый вариант пришедший в мою голову такой :) Так действительно отработают все проверки и тесту можно будет верить, ну а что если я не угадала и секунды не хватит? да и вообще не умели мы правда хотим, чтобы каждый юнит тест выполнялся секунду? Одним из вариантов решения возникшей проблемы является BlockingObservable ->
  9. BlockingObservable - можно получить вызвав метод у Observable - toBlocking(), тем самы вы запустите на исполнение цепочку вычислений инкапсулираную в Observable и заблокируете основной поток, чтобы дождаться ее окончания. Результаты вычислений находятся внутри BlockingObservable и доступны с помощью ряда методов: first, last, а я в своем примере использую getIterator, который возвращает как Iterator всю последованность отправленных сообщений. Преобразовав итератор в лист я с помощью стандартных junit asserts проверяю корректность отработанного метода. небольшая ремарка: в документации к BlockingObservable сказано, что этот класс может быть полезен для тестирования и демонстрационных целей, но, как правило, не подходит для кода в продавшее и если вы все же обнаружили этот класс в своем продакшн коде - это обычно признак того, что вы должны пересмотреть свой дизайн. И так, наш тест стал выглядеть гораздо лучше, но как в этом случае наглядно проверить, что вызвался onComplite() или onError()? Думаю, пришло самое время рассказать про TestSubscriber ->
  10. TestSubscriber - представляет специальную реализацию класса Subscriber со встроенными полезными методами для целей тестирования Возьмем наш тестируемый метод getSportLabels и подпишемся на него, используя TestSubscriber. Не забудем у testSubscriber вызвать метод awaitTerminalEvent для того чтобы заблокировать основной поток, пока мы не дождемся терминального состояния цепочки вычислений, и далее используя встроенные assert-ы testSubscriber проверим правильность результата вычислений. Тест теперь стал совсем наглядным, но что если наша цепочка вычислений не имеет терминального состояния? здесь нам на помощь прийдет еще один представитель тестовой среды TestScheduler ->
  11. Давайте разберем следующий пример бесконечной цепочки вычислений. У нас есть метод, который с некоторой заданной периодичностью и на заданном планировщике потоков запрашивает сообщения с сервера. Мы хотим протестировать, что за 10 секунд с периодом в 1 секунду сообщения будут запрошены 10 раз. Для этого мы: Предварительно замокали метод получения сообщений Создали тестовый планировщик потоков 3) Задаем интервал равный 1 секунде и передаем в трестируемый метод тестовый планировщик 4) На тестовом планировщике эмулируем работу равную 10 секундам 5) Проверяем, что в onNext пришел список сообщений с сервера 10 раз используя встроенный assert-ы testSubscriber Используя TestScheduler мы можем контролировать виртуальное время работы потока, в котором выполняется цепочка вычислений, что это значит? а это значит что наш тест не будет выполнятся 10 секунд, он будет выполняться ровно столько, сколько необходимо для того чтобы прогнать цепочку вычислений 10 раз, игнорируя задержки во времени, мы как будто переводим стрелки часов до нужного времени, вместо того, чтобы ждать. Рассмотрим методы TestScheduler, которые позволяют нам это делать ->
  12. На экране представлена абстрактная временная шкала отправки сообщений подписчику, как мы видим первое сообщение отправляется немедленно, далее следует задержка в 20 секунд, а после еще одна задержка в 8 секунд. Теперь рассмотрим как методы TestSchedule будут отрабатывать на этой шкале. Первый метод triggerActions - выполнит только те вычисления которые запланированы немедленно, то есть без задержек advanceTimeTo выполнит все вычисления, которые, учитывая все промежутки временного ожидания, укладываются в обозначенное время. advanceTimeBy отработает аналогично advanceTimeTo, однако если мы снова вызовем advanceTimeBy, то виртуальное время на testScheduler не перепишется, а добавится к имеющимуся. Предлагаю рассмотреть реальный пример теста с использованием TestScheduler ->
  13. Не так давно у нас стояла задача грузить в статьи на Чемпионате врезы из социальных сетей. То есть мы сначала получаем статью с кучей блоков и какие-то из этих блоков являются врезами из той или иной соц сети, соответственно весь контент блока нужно загружать дополнительно после получения самой статьи. Врезов таких статье может быть достаточно много и все они могут быть из разных источников, а показать мы их хотим быстро, поэтому грузим параллельно, но не забываем соблюдать хронологический порядок. Сейчас я вам как раз покажу кусок кода, который этот хронологический порядок и тестирует ->
  14. Как вы видите сначала мы мокаем нужные для теста методы репозитория, эмулируем используя delay разное время загрузки врезов и затем проверяем что последовательность блоков статьи после загрузки врезов эквивалента первоначальному порядку. Но помимо тестирования создаваемых нами Observable, появляется необходимость тестировать Subscriber-ы, которые мы бывают анонимные и именованные, для начала разберемся как тестировать, анонимный Subscriber ->
  15. Есть класс SportPresenter, и нам необходимо протестировать метод loadSport, проверить что в определенных колбэках были вызваны ожидаемые методы view. Как в этом случае будет выглядеть тест ->
  16. Мокнем метод интерактора нужным нам Observable и выполняем тестируемый метод и затем проверяем используя средства Mockito что у view действительно были вызваны только ожидаемые методы и больше никаких. А теперь представим что такой Subscriber мы используем в нескольких местах и для того чтобы не дублировать код мы вынесли его в отдельный класс и у нас получился - именованный Subscriber ->
  17. Напишем для него тест, который проверяет что вызываются нужные методы у view в случае возникновения ошибки и тут нам поможет TestSubject ->
  18. Subject - это и Observable и его подписчик вместе, создан для того чтобы скрестить реактивный и императивный мир, subjects бывают разных типов, сегодня поговорим на мой взгляд о самом полезном. TestSubject - работает на TestScheduler, что позволяет точно определять время уведомлений подписчикам с использованием относительного виртуального времени Мы создаем TestSubject, подписываемся на него тем именованным Subscriber, который хотим протестировать и посылаем сообщение об ошибке. Далее не забываем активировать TestScheduler и снова используя mockito проверяем, что поведение view на ошибку соответствует нашим ожиданиям. О тестировании тут наверно все, но на закусочку я хочу вам немного рассказать о RxPlugins ->
  19. Как мы видим слева, сначала регестрируется событие на срабатывание create у Observable, и позже мы выполняем некий Observable - каждый раз при создании нового Observable в цепочке вычислений должна срабатывать переданная нами функция и писаться лог. По окончанию выполнения Observable восстанавливаются дефолтные настройки. Давайте посмотрим что получилось в логе, вывод вполне ожидаемый, учитывая небольшую сложность нашего Observable. Давайте теперь посмотрим как можно подменять стандартные планировщики потоков ->
  20. Для подмены стандартных планировщиков потоков предоставляемых библиотекой rxJava существуют специальные сеттеры, как видно на слайде мы подменили планировщик io на immediate, давайте посмотрим на результат исполнения, как мы видим Observable выполнился в текущем потоке, это может быть удобным для написания тестов. Ну вот пожалуй и все, давайте пройдемся по выводам сегодняшнего доклада ->
  21. Как мы сегодня выяснили, код с использованием rxJava вполне поддается тестированию. При написании тестов нужно помнить о том, что где то возможно переключаются планировщики потоков Классы помощники TestSubscriber, TestScheduler и TestSubject делают написание юнит-тестов еще проще. Спасибо за внимание, готова ответить на ваши вопросы.