Писал ли тесты

Ответ

Да, писал unit- и UI-тесты. Использую JUnit, Mockito для модульного тестирования и Espresso для UI-тестов. Пример unit-теста с Mockito:

@Test
fun `validate email correct input`() {
    val validator = EmailValidator()
    assertTrue(validator.isValid("test@example.com"))
}

Для UI-тестов с Espresso:

@Test
fun loginButton_click_showsProgress() {
    onView(withId(R.id.login_button)).perform(click())
    onView(withId(R.id.progress_bar)).check(matches(isDisplayed()))
}

Также знаком с тестированием ViewModel через TestCoroutineDispatcher и LiveData.

Ответ 18+ 🔞

Ну ты представляешь, сидишь такой, пишешь код, а потом тебе говорят — а теперь всё это ещё и протестируй, ёпта. Ну ладно, блядь, тестирую. В основном, конечно, unit-тесты и UI-тесты — это как два разных мира, один в тишине и спокойствии, а второй — это ёперный театр с нажатиями и ожиданиями.

Для модульного тестирования, где логика чистая, беру JUnit и Mockito. Это чтобы не тащить в тест всю вселенную, а подсунуть какую-нибудь заглушку, манду с ушами. Вот, смотри, простой пример, проверяем валидацию email:

@Test
fun `validate email correct input`() {
    val validator = EmailValidator()
    assertTrue(validator.isValid("test@example.com"))
}

Всё чинно, благородно. Никаких гомосеков, которые налетели** из сети. Просто вызвал метод и проверил. Красота.

А вот UI-тесты — это уже хитрая жопа. Тут Espresso в дело идёт. Настроить его — это ещё та сосалка, но когда работает — красота. Ты буквально говоришь приложению: «нажми вот эту кнопку» и «покажи мне, что прогресс-бар виден». Выглядит это примерно так:

@Test
fun loginButton_click_showsProgress() {
    onView(withId(R.id.login_button)).perform(click())
    onView(withId(R.id.progress_bar)).check(matches(isDisplayed()))
}

Сам от себя охуевал, когда впервые заставил это работать. Кажется, что всё просто, а потом раз — тест падает, потому что view не найдена, а оказывается, она ещё не отрисовалась. Волнение ебать, пока не настроишь все ожидания.

Ну и куда же без ViewModel. Тут уже своя баня. Использую TestCoroutineDispatcher, чтобы эти все асинхронные штуки LiveData не выносили мозг в тестах. Иначе получается доверия ебать ноль — то сработает, то нет. А так — запустил, подождал, проверил состояние. Как говорится, вилкой в глаз или в жопу раз, но результат должен быть предсказуемым.

В общем, тестирование — это такая штука, которая сначала кажется лишней работой, а потом, когда находишь баг, который мог бы уйти в прод, думаешь: «Ни хуя себе, а ведь могло и выстрелить». Так что терпения ноль ебать, но писать их надо.

Видео-ответы