Тёмный

Unit тестирование в Android c Clean architecture 

Тимофей Коваленко
Подписаться 8 тыс.
Просмотров 12 тыс.
50% 1

Рассказываю про Unit тестирование в Android, очень подробно, как для "чайников" ;). На реальном примере показываю JUnit и Mockito, зачем это и как эффективно использовать тесты в разработке. Показываю пример с Clean architecture Android.
Курсы по разработке Android приложений: ✅ KIPARO.COM.
СОДЕРЖАНИЕ:
-------------------------------------------------------------------
00:00:00 - введение
00:00:39 - Clean architecture Android
00:01:40 - кратко, что такое Unit тестирование Android
00:02:25 - подключаем библиотеки JUnit и Mockito
00:03:26 - пишем тест на JUnit 5
00:14:46 - используем библиотеку Mockito
-------------------------------------------------------------------
На канале также есть уроки по Android Studio, уроки по Java и уроки по Kotlin.
Так же, найти меня можно вот тут:
✅ Linkedin: / timofeykovalenko
✅ Instagram: / ttimofey
✅ На моем сайте: kiparo.com/teacher/timofey-ko...
✅ FB с анонсами видео: / kiparocom
#android #junit #kiparo

Опубликовано:

 

29 июн 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 45   
@TimofeyKovalenko
@TimofeyKovalenko 2 года назад
СОДЕРЖАНИЕ: 00:00:00 - введение 00:00:39 - Clean architecture Android 00:01:40 - кратко, что такое Unit тестирование Android 00:02:25 - подключаем библиотеки JUnit и Mockito 00:03:26 - пишем тест на JUnit 5 00:14:46 - используем библиотеку Mockito
@MarselNz
@MarselNz 2 года назад
Единственный человек во всем ютубе, кто дает такую актуальную информацию. Спасибо вам
@dmitriygushel5587
@dmitriygushel5587 2 года назад
Спасибо, очень подробно! Кстати, что бы не создавать самому пакеты, можно нажать ctrl+shift+T и студия сама создаст класс с названием исходного класса+test с тем же пакетом в папке test
@readmeandanswer8142
@readmeandanswer8142 2 года назад
Спасибо, понятно, после ваших уроков статьи по этим темам читаются легче.
@pauilegorov
@pauilegorov 2 года назад
Спасибо, очень полезная тема!!
@chriswaytt6009
@chriswaytt6009 Год назад
спасибо, сделайте еще пожалуйста на эту тему видео. Объясняете доступно но хочется больше примеров и по сложнее задачи
@spyro2008
@spyro2008 3 месяца назад
Как всегда все на высшем уровне, спасибо вам!
@user-we6si4mi3x
@user-we6si4mi3x 2 месяца назад
Спасибо, все очень понятно объясняете!
@alexanderj8981
@alexanderj8981 2 года назад
Спасибо за видео. Понравился стиль объяснения, спокойный рассказ с примерами без лишней воды - приятно слушать такое. Я конечно понимаю, что все упрощено для новичков, но некоторые моменты хотелось бы уточнить, т.к. где-то можно чуть улучшить, а где-то из-за упрощения даются немного вредные советы, которые сказываются потом. 1. ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-iGqVm0atAMQ.html : вообще вначале, когда проект почти пустой и все элементарно, то классы с тестами могут лежать в точно таких же пакетах и называться по имени класса. Но чем дальше, тем все больше тесты должны быть структурированы иначе, чем основной код. У них будет единый фасад как точка входа, но вовсе не обязательно, что на каждый класс вообще будет ровно симметричный класс с тестами. Тесты должны быть не чувствительными к изменению структуры основного кода, а это означает, что если вдруг из того же UseCase мы захотим вынести что-то в отдельный класс или сделать изменение, которое не меняет поведение программы, то тесты при этом должны практически не меняться и на новый выделенный класс не создаются новые тесты, ведь поведение уже будет протестировано через внешний. Если соблюдать это правило про класс и симметричный тест класс к нему под тем же именем и расположением, то мы создаем лишнюю связанность, которая будет мешать при дальнейших изменениях кода. 2. ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-iGqVm0atAMQ.html : еще хорошо бы показать, раз код в IDE, что тесты создавать проще не вручную, а через хоткеи: Alt+Enter (если windows) и там через диалог дальше. А создавать тесты в том же пакете и переключаться между основным кодом и тестами можно по Ctrl+Shift+T. Вот тут можно посмотреть справку: www.jetbrains.com/help/idea/create-tests.html. 3. ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-iGqVm0atAMQ.html : стандартным Assertions лучше предпочесть AssertJ и ему подобные с более выразительным синтаксисом, где вместо assertEquals(a, b), в котором новички долго путаются где “ожидаемое”, а где “реальное” на каком месте, - там будет assertThat(2+2).isEqual(4). 4. ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-iGqVm0atAMQ.html : вообще-то, названия тестов как предложения с пробелами в котлине работают и для junit4, тут никакой разницы. “shouldReturnCorrectData” - совсем слабое название и второй вариант заметно лучше. И хотя “should” достаточно распространенная практика именования, но следовать ей не стоит: это лишнее слово в каждом тесте, притом еще и лексически означающее, что “тут следовало бы вернуть (но не обязательно)”, а мы хотим, чтоб поведение было строгим точным требованием без “желательно”. 5. ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-iGqVm0atAMQ.html : а вот это неправильный и вредный совет. Как раз любым mock библиотекам лучше предпочитать свои тестовые утилиты с настоящими и полноценными методами, а где можно, то и реальные классы. Для этого нужно аккуратно продумать куда положить такой TestRepository, чтоб можно было переиспользовать в других тестах (т.е. не тут в этом же файле). Для этого кстати нельзя просто так забивать имена внутри (first и last name), а придется передавать данные параметрами. Это делается очень просто и потом легко менять в одном месте раз и для всех тестов. А вот с моками если что меняется, то нужно обновить каждый тест в отдельности. Настройка каждого мока - кроме того, что это лишний код - так это и каждый раз излишняя привязка к тому, как тест ожидает какой метод вызовется в основном коде и как он себя ведет. А это означает, что тест знает детали имплементации, чего он знать не должен. И именно это потом не позволяет менять основной код без тонны изменений в тестах. 6. ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-iGqVm0atAMQ.html : mockito был стандартом в java. С котлином он изначально плохо работал. Зато упомянутый mockk и советую использовать вместо mockito - он создавался сразу для котлина с его синтаксическими возможностями, не требует второй вспомогательной библиотеки, более мощный (может при необходимости и object, и enum, и конструкторы чужих классов мокать). 7. ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-iGqVm0atAMQ.html : вообще да, про это и вправду надо задумываться будет ли сравнение по ссылке или по equals тоже сработает. Но для теста самого это не должно быть важным, ведь поведение будет работать так или иначе. Даже технически именно сам testUserName, а не копию, метод и вернет. А если очень важно убедиться, что возвращенное значение equals подобному, то это отдельно можно протестировать. Есть в AssertJ и методы такие как assertThat(actual).isSameAs(expected) (или isNotSameAs).
@TimofeyKovalenko
@TimofeyKovalenko 2 года назад
Уххххх) Спасибо за такой развернутый фидбек 👍. 1) Не могу полностью согласиться. Да, когда проект большой, то и тестов бывает много на один класс, а где-то и структура другая. Но для большинства классов классическая структура более чем подходит, и позволяет проще ориентироваться в коде, особенно, когда заводишь в проект новых разработчиков. К тому же это видео для студентов, если начать показывать на таких примерах, то студентов быстро поубавится))))). 2) По опыту, не стоит такое показывать со старта. Лучше пусть студент чуть больше потратит времени, но набьет руку. А потом уже и IDE под себя настроят и хот кеи. Вообще, когда преподаешь, приходится отучиваться от хот кеев))) и писать код намного более развернуто. 3) Нуу не знаю, мне больше нравится использовать стандартный стек, так проще программистов заводить на проект. Да и для обучения, я бы никогда не брал что-то не стандартное. Все такие либы уже учатся на работе в реальном проекте если необходимо. 4) Хм, спасибо не знал. “should” - да, это лишнее. 5) Не спорю, вариант со своими реализациями стоящий, но нужно понимать, что в этом случае вы теряете весь функционал mock, который не ограничивается просто созданием фейковых объектов. Плюс, подход с mock все же популярнее. 6) mockito это стандарт от гугла, mockk все же сторонняя либа, поэтому для базового обучения не годится. 7) "для теста самого это не должно быть важным," - еще как важно, так можно написать тест, который только с виду будет работать).
@TheVincet1998
@TheVincet1998 Год назад
Спасибо за видео!
@user-bu7zr1kd1j
@user-bu7zr1kd1j 2 года назад
Спасибо за ваш труд!
@TimofeyKovalenko
@TimofeyKovalenko 2 года назад
😀
@namefamily957
@namefamily957 2 года назад
Спасибо! :)
@user-tg1yr1dt4n
@user-tg1yr1dt4n 2 года назад
Выглядит и вправду смешно но в реальных проектах я думаю пойму всю прелесть использование тестов спасибо
@MxMayers
@MxMayers 2 года назад
Спасибо за видео!) 14:27 я представил как в офис разработки на 3м этаже, в помещение с джунами заходит сеньер и говорит что тесты сломались, вся команда подрывается и выпрыгивает в окно 😂
@mikhaillazarev5378
@mikhaillazarev5378 Год назад
Спасибо большое.
@pavelpotapov9866
@pavelpotapov9866 2 года назад
🔥🔥🔥
@max__am
@max__am 2 года назад
лучший!
@__Minecraft_Poseidon__
@__Minecraft_Poseidon__ 2 года назад
Сотый лайк 👍
@DarkWeret
@DarkWeret 2 года назад
Спасибо, все очень понятно объясняете) Вопрос: будут ли видео с тестированием viewModel? В котором возвращается какой-нибудь sealed класс state: с loading, success или error? Очень сложная для моего понимания тема)
@TimofeyKovalenko
@TimofeyKovalenko 2 года назад
Будет но чуть позже, сначала закончим с этим приложением, а вот затем сделаем что-то посложнее.
@fournonblondes4089
@fournonblondes4089 2 года назад
viewModel в котором возвращается какой-нибудь sealed класс state: с loading, success или error скажите где об этом можно почитать, лучше на русском. смотрел видео у Филиппа но не всё понял, делать по аналогии сложновато даже.
@luckydevil1601
@luckydevil1601 Год назад
@@fournonblondes4089 это который Philipp Lackner?)
@user-vl2uw6rb1v
@user-vl2uw6rb1v Год назад
лучший
@user-vl2uw6rb1v
@user-vl2uw6rb1v Год назад
хочу подсказать, у вас в шапке канала тот основной баннер, там ничего не написано о котлине)) не порядоооок
@PandaTop.
@PandaTop. 2 года назад
Дякую
@oleg12395
@oleg12395 2 года назад
Как вы поставили кавычки в методе: should return the same data ...
@TimofeyKovalenko
@TimofeyKovalenko 2 года назад
JUnit 5 позволяет такое делать.
@alishanvaliani9952
@alishanvaliani9952 2 года назад
let's make course about Jetpack Compose!!
@vladlen_ak
@vladlen_ak Год назад
Как ставить эти одинарные кавычки под скосом на маке?
@karamba6936
@karamba6936 Год назад
а что вы думаете насчет подхода для каждого класса создавать интерфейс?Нашел канал, там человек опытный пишет такой код, не использует DI библиотеки, тесты тоже пишет. Но код очень отличается от всего, что я видел. Код для меня непонятный и очень расщепленный по файлам отдельным
@TimofeyKovalenko
@TimofeyKovalenko Год назад
Я придерживаюсь подхода, который строится на конкретной необходимости. Если интерфейсы решают какую-то проблему и улучшают работу с приложением, то почему нет. Если же это делается потому, что в умной книжке так написали, нууу такое себе. А не использовать DI библиотеки - это называется сделать свой велосипед, который никто кроме тебя не поймет))).
@mirzorasulpulotov129
@mirzorasulpulotov129 Год назад
Что делать? Выдает ошибку Mockito cannot mock/spy because : - final class. Хотя класс не финал. Это в котлин.
@nikitatkachenko1694
@nikitatkachenko1694 2 года назад
Привет, я начинающий андроид разработчик и для меня этот канал как алмаз среди груды мусора) Посмотрев твои уроки начал переделывать свой пет-проект на клин, но столкнулся с проблемой( У меня в проекте есть работа с API(retrofit+moshi+okhttp), если я правильно понял то это относиться к "data" слою ? Короче говоря, мои модельки для работы с API лежат в слое "data", а также эти модели нужны для слоя "domain", так как там описан интерфейс репозитория, как мне достучаться до этих моделек если по правильному я не могу юзать модели "data" в "domain" ? Заранее спасибо за ответ !
@TimofeyKovalenko
@TimofeyKovalenko 2 года назад
Да, API(retrofit+moshi+okhttp) это часть слоя "data" и у них есть свои модельки, тут все правильно. Но, модельки, которые лежат в слое "data", никакому больше кроме как слою "data" не должны быть видны. Интерфейс репозитория должен возвращать модельки "domain". То есть в реализации репозитория вы должны конвертнуть "data" модельки в "domain" и вернуть их из методов репозитория. Domain главный слой и задает всем правила работы, тоесть репозиторий должен отдать то, что хочет домен. Поэтому "data" модельки используются чисто для внутренней работы "data" слоя.
@nikitatkachenko1694
@nikitatkachenko1694 2 года назад
@@TimofeyKovalenko спасибо за ответ, а сможешь как-то показать на практике как правильно внедрить работу з api, room, fireBase ?! Думаю будет полезно и информативно)
@TimofeyKovalenko
@TimofeyKovalenko 2 года назад
Да, есть планы на такие темы, но чуть позже.
@devkot7040
@devkot7040 2 года назад
Есть вопросы. Вот мы тестируем реализацию UseCase'а(интерактор) . 1. Почему этот интерактор, не наследуется от какого-то интерфейса интерактора? То есть каким образом мы будем тестировать viewmodel, подставляю туда фейковый интерактор? 2. Так же хотел спросить, нет ли какого-то либо механизма, который позволяет тестировать интерфейс этого самого интерактора, но, чтобы посредством di каким-то образом в тест inject-ить реализацию этого интерактора. То есть, мы один раз провайдим реализацию интерфейса, а он уже сам тестируется, т.к. в тесте тестировался интерфейс, а не его реализация.
@TimofeyKovalenko
@TimofeyKovalenko 2 года назад
1) Просто делаете фейковый интерактор на основе реального и все. Что-бы делать моки не обязательно использовать именно интерфейсы. 2) "тесте тестировался интерфейс, а не его реализация" - не понял, если честно ваш вопрос, что значит тестировался только интерфейс, интерфейс никогда не тестируется, в этом нет никакого смысла.
@devkot7040
@devkot7040 2 года назад
@@TimofeyKovalenko 1) да, можно сделать фейковый интерактор на основе реального, но получается, что если мы заменим реализацию интерактора, то нам придётся во всех тестах его менять вручную, да и в коде собственно. 2) про тестировался интерфейс. Я имел ввиду, что прописывается работа с интерфейсом в классе теста. Во время компиляции, с помощью DI в класс теста inject- ится реализация этого интерфейса, и уже тестируется реальный класс. Чтобы в следующий раз, когда меняется реализация этого интерфейса, которую мы везде inject- им, нам не пришлось вручную менять тесты.
@TimofeyKovalenko
@TimofeyKovalenko 2 года назад
1) Понял вас. Ну тут с одной стороны да, это может быть удобно, но с другой - это очень редкий случай. Дело в том, что для каждой реализации интерактора нужно писать новый тест. А если логика возвращаемых данных остается также, то и врят ли придется писать новую реализацию ;). Да и вообще, лучше все же менять вручную, дело в том, что я часто вижу тесты, которые написаны так, что при изменение тестируемой логики, они тоже "самоизменяются" или подстраиваются под новые требования))), в итоге, от таких тестов нет никакого толка. 2) Да, в тесте можно использовать зависимости из DI, но опять же вопрос зачем(пункт 1).
@garifzyanovrr
@garifzyanovrr Год назад
Тимофей привет! Выдает ошибку, Expected :...cleanarchitecturelearnapp.domain.models.UserName@632ceb35 Actual :...cleanarchitecturelearnapp.domain.models.UserName@1c93f6e1 Все как у тебя в коде.
@TimofeyKovalenko
@TimofeyKovalenko Год назад
Вы сравниваете объекты, а нужно сравнивать содержимое этих объектов.
@decemd1946
@decemd1946 Год назад
в дата классе метод equals(==) содержимое сравнивает
Далее
Dagger в Android на практике с MVVM
32:41
Задержали в аэропорту
00:56
Просмотров 708 тыс.
Docker за 20 минут
21:42
Просмотров 63 тыс.
Юнит тест для View Model в Android
26:57
Kotlin in 100 Seconds
2:22
Просмотров 1,1 млн
ТЕСТИРОВАНИЕ НА JAVA (JUNIT, MOCKITO)
9:14
MVVM в Android на практике
41:32
Просмотров 46 тыс.