Работаю в IT уже 8 лет. Рассказываю про разработку простым языком. Полезность скрыта под тупыми шутками и слоем мата. Лучший underground канал про разработку, который вы сможете найти.
По сотрудничеству писать @haroncode
Post #247
2.71K
После всего выше сказанного в воздухе витает вопрос, а как правильно тестировать то епт? Плохая новость – никто не знает, каждый проект по своему уникальный. Хорошая – у меня есть концепция, используя которую, вы с меньшей вероятностью наплодите хрень.
Что имеем по тестам в мобиле: UI – мрази требующие кучу ресурсов, да еще и придется заняться сексом с инфраструктурой, чтобы это все завелось. Однако они позволяют рефакторить код без изменений в тестах. Unit тесты хоть пишутся быстро и не требуют ресурсов, но тестируют что удобно, вместо того что действительно нужно.
В итоге я предлагаю вариант, который находится посередине этих двух. Вариант требует дохера ресурсов и ничего не тестит, прям как джун QA. Ладно, ладно шутки в сторону.
На проекте должен быть или MVVM или MVI, в идеале чтобы было единое состояние. Дальше вы делаете следующим образом, либо берете Robolectric и нажимаете на кнопки через него, либо делаете специальную прослойку, которая позволяет прокинуть события до MVVM или MVI. Эта прослойка нужна, чтобы если вы перешли на другую либу MVI или перешли с MVVM на MVI, такой переход не вызывал переписывание всех тестов.
Теперь как это работает. Вы через прослойку отправляете события которые доходят до Store, ViewModel или что у вас там, я буду называть Store. В этом Store у вас происходит логика со всеми настоящими репозиториями и интеракторами. Мокаем мы только базу данных снаружи и подсовываем локальный сервер для запросов. Да у нас каждый тест прям ходит на сервер, только локальный.
Затем у вас Store начинает выдавать поток State, через Flow или LiveData тут значения не имеет. И вы в тесте, просто проверяете этот самый State. На этом все, никаких страданий с мокито и проверкой, что нужный аргумент вызвался с нужными данными, никаких дурацких непонятных проверок. Максимально просто, вот мы нажали на кнопку, вот проверили состояние.
Чего имеем с таким подходом? Да в начале придется поебаться с настройкой либ, общего кода, и моковым локальным сервером, но лишь один раз и в начале. А какие плюсы всего этого?
👉 Первое. Любой тест будет очень близко повторять сценарий пользователя. Вы что-то делаете на экране, а затем проверяете объект State или Single Live event для показа диалогов и т.д. Вы тестируете то, как реально ведет себя ваша программа, а не абстрактные вещи в вакууме.
👉 Второе. Теперь можете хоть зарефакторить до смерти ваши репозитории, интеракторы и т.д. Тесты при этом как были, так и останутся. Вы можете перейти с MVVM на MVI и обратно, в тестах либо ничего не поменяется либо будет минимум изменений. Это реально вас дико ускорит, вы не будете постоянно тратить время на починку тестов
👉 Третье. Такие тесты будут (на самом деле не обязательно, уж как настроите) медленнее чем Unit, но при этом в десятки раз быстрее UI и при этом не будут требовать инфраструктуры с эмуляторами.
Разумеется от unit и ui тестов не нужно отказываться, но их должно быть меньше тех, про которые описал в посте.
Возможно после прочтения появится ощущения аля: ну ты кэп, просто предложил тестить презенторы, мы так уже делаем сотню лет. Обычно презентеры тестируют с моковыми репозиториями и интеракторами, в этом и проблема. Стоит вам немного их порефачить, вам нужно искать тесты, где вы эти самые интеракторы заиспользовали и менять их и там. Я предлагаю мокать именно окружение, а не код проекта, это очень важное отличие.
Тут я описал лишь концепцию, а вот уже конкретную реализацию я возможно как-нибудь оформлю на github и скину сюда. Ставь ❤️ если хочется увидеть код.
Что имеем по тестам в мобиле: UI – мрази требующие кучу ресурсов, да еще и придется заняться сексом с инфраструктурой, чтобы это все завелось. Однако они позволяют рефакторить код без изменений в тестах. Unit тесты хоть пишутся быстро и не требуют ресурсов, но тестируют что удобно, вместо того что действительно нужно.
В итоге я предлагаю вариант, который находится посередине этих двух. Вариант требует дохера ресурсов и ничего не тестит, прям как джун QA. Ладно, ладно шутки в сторону.
На проекте должен быть или MVVM или MVI, в идеале чтобы было единое состояние. Дальше вы делаете следующим образом, либо берете Robolectric и нажимаете на кнопки через него, либо делаете специальную прослойку, которая позволяет прокинуть события до MVVM или MVI. Эта прослойка нужна, чтобы если вы перешли на другую либу MVI или перешли с MVVM на MVI, такой переход не вызывал переписывание всех тестов.
Теперь как это работает. Вы через прослойку отправляете события которые доходят до Store, ViewModel или что у вас там, я буду называть Store. В этом Store у вас происходит логика со всеми настоящими репозиториями и интеракторами. Мокаем мы только базу данных снаружи и подсовываем локальный сервер для запросов. Да у нас каждый тест прям ходит на сервер, только локальный.
Затем у вас Store начинает выдавать поток State, через Flow или LiveData тут значения не имеет. И вы в тесте, просто проверяете этот самый State. На этом все, никаких страданий с мокито и проверкой, что нужный аргумент вызвался с нужными данными, никаких дурацких непонятных проверок. Максимально просто, вот мы нажали на кнопку, вот проверили состояние.
Чего имеем с таким подходом? Да в начале придется поебаться с настройкой либ, общего кода, и моковым локальным сервером, но лишь один раз и в начале. А какие плюсы всего этого?
👉 Первое. Любой тест будет очень близко повторять сценарий пользователя. Вы что-то делаете на экране, а затем проверяете объект State или Single Live event для показа диалогов и т.д. Вы тестируете то, как реально ведет себя ваша программа, а не абстрактные вещи в вакууме.
👉 Второе. Теперь можете хоть зарефакторить до смерти ваши репозитории, интеракторы и т.д. Тесты при этом как были, так и останутся. Вы можете перейти с MVVM на MVI и обратно, в тестах либо ничего не поменяется либо будет минимум изменений. Это реально вас дико ускорит, вы не будете постоянно тратить время на починку тестов
👉 Третье. Такие тесты будут (на самом деле не обязательно, уж как настроите) медленнее чем Unit, но при этом в десятки раз быстрее UI и при этом не будут требовать инфраструктуры с эмуляторами.
Разумеется от unit и ui тестов не нужно отказываться, но их должно быть меньше тех, про которые описал в посте.
Возможно после прочтения появится ощущения аля: ну ты кэп, просто предложил тестить презенторы, мы так уже делаем сотню лет. Обычно презентеры тестируют с моковыми репозиториями и интеракторами, в этом и проблема. Стоит вам немного их порефачить, вам нужно искать тесты, где вы эти самые интеракторы заиспользовали и менять их и там. Я предлагаю мокать именно окружение, а не код проекта, это очень важное отличие.
Тут я описал лишь концепцию, а вот уже конкретную реализацию я возможно как-нибудь оформлю на github и скину сюда. Ставь ❤️ если хочется увидеть код.
- ❤ 56
- 👍 6





