Test

https://developer.android.com/training/testing
https://developer.android.com/training/testing/fundamentals
https://developer.android.com/training/testing/fundamentals/what-to-test
https://developer.android.com/training/testing/fundamentals/test-doubles
https://developer.android.com/training/testing/fundamentals/strategies
https://developer.android.com/training/testing/local-tests
https://developer.android.com/training/testing/instrumented-tests
https://developer.android.com/training/testing/instrumented-tests/stability
https://developer.android.com/training/testing/instrumented-tests/performance
https://developer.android.com/training/testing/instrumented-tests/androidx-test-libraries/test-setup
https://developer.android.com/training/testing/instrumented-tests/androidx-test-libraries/runner
https://developer.android.com/training/testing/ui-tests
https://developer.android.com/training/testing/ui-tests/behavior
https://developer.android.com/training/testing/ui-tests/screenshot
https://developer.android.com/training/testing/different-screens
https://developer.android.com/training/testing/different-screens/tools
https://developer.android.com/training/testing/other-components/content-providers
https://developer.android.com/training/testing/other-components/services
https://developer.android.com/training/testing/other-components/ui-automator
https://developer.android.com/studio/run/resizable-emulator
13.05.2023https://maxkim.eu/full-guide-to-testing-android-applications-in-2022
Snapshot Testing

Метод тестирования UI, при котором создаются и сравниваются “снимки” состояния интерфейса приложения. Основная идея заключается в том, чтобы сохранить изображение или структуру UI в виде “снапшота” и затем проверить, что текущий вывод совпадает с ожидаемым.

• Снапшот-тесты позволяют быстро обнаруживать изменения в UI, которые могут возникнуть в результате изменений кода или стилей.

• Упрощают тестирование сложных интерфейсов, так как позволяют фокусироваться на визуальных аспектах, а не на логике.

Синтетические тесты

Синтетические тесты в моделируют работу приложения в определенных условиях, используя заранее подготовленные данные, а не реальные пользовательские сценарии. Они фокусируются на измерении производительности, скорости выполнения операций или других метрик приложения (например, время рендеринга или загрузки), но могут не отражать реальные взаимодействия пользователей. Такие тесты полезны для оценки производительности отдельных компонентов или сценариев, но их результаты могут отличаться от показателей при реальном использовании.

JUnit
https://developer.android.com/training/testing/instrumented-tests/androidx-test-libraries/rules

Фреймворк для написания и выполнения тестов в Java. Он является стандартным инструментом для юнит-тестирования и широко используется в разработке приложений, включая Android-приложения. JUnit позволяет создавать автоматические тесты, что способствует повышению качества кода и уменьшению количества ошибок.

public class CalculatorTest {
    
    private Calculator calculator;

    @Before
    public void setUp() {
        calculator = new Calculator();
    }

    @Test
    public void testAdd() {
        assertEquals(5, calculator.add(2, 3));
    }

    @Test
    public void testSubtract() {
        assertEquals(1, calculator.subtract(3, 2));
    }
}
Robolectric
https://developer.android.com/training/testing/local-tests/robolectric

Библиотека для тестирования Android-приложений, которая позволяет запускать юнит-тесты на обычной JVM без необходимости эмулятора или реального устройства. Это делает процесс тестирования быстрее и удобнее для разработчиков, так как нет необходимости ожидать загрузки эмулятора или устройства.

@RunWith(RobolectricTestRunner::class)
@Config(sdk = [28]) // Указываем версию SDK
class MainActivityTest {

    @Test
    fun testActivityLaunch() {
        // Запуск Activity
        val activity = Robolectric.buildActivity(MainActivity::class.java).create().start().resume().get()

        // Проверка, что Activity запустилась
        assertNotNull(activity)
    }

    @Test
    fun testIntent() {
        val intent = Intent(ApplicationProvider.getApplicationContext(), MainActivity::class.java)
        val activity = Robolectric.buildActivity(MainActivity::class.java, intent).create().get()

        // Проверка, что Activity получила правильный Intent
        assertEquals(activity.intent, intent)
    }
}
Espresso
https://developer.android.com/training/testing/espresso
https://developer.android.com/training/testing/espresso/basics
https://developer.android.com/training/testing/espresso/setup
https://developer.android.com/training/testing/espresso/cheat-sheet
https://developer.android.com/training/testing/espresso/idling-resource
https://developer.android.com/training/testing/espresso/intents
https://developer.android.com/training/testing/espresso/lists
https://developer.android.com/training/testing/espresso/multiprocess
https://developer.android.com/training/testing/espresso/recipes
https://developer.android.com/training/testing/espresso/web
https://developer.android.com/training/testing/espresso/accessibility-checking
https://developer.android.com/training/testing/espresso/additional-resources

Библиотека для UI-тестирования Android-приложений, предоставляющая API для написания тестов, взаимодействующих с элементами интерфейса пользователя. Она позволяет имитировать пользовательские действия, проверять состояние UI-компонентов и обеспечивать синхронное выполнение тестов.

@Test
fun testButtonClick() {
    // Найти кнопку и кликнуть по ней
    onView(withId(R.id.my_button)).perform(click())
    
    // Проверить текст на экране после нажатия
    onView(withId(R.id.text_view)).check(matches(withText("Hello World!")))
}
Kotest

Мощная библиотека для тестирования на языке Kotlin, которая предоставляет различные стили для написания тестов и дополнительные утилиты для упрощения тестирования.

class SampleTest: FunSpec({
    test("simple test") {
        1 + 1 shouldBe 2
    }
})
Kakao

Kotlin DSL для библиотеки Espresso, созданная для упрощения написания UI-тестов в Android. Kakao предоставляет удобный и читаемый синтаксис, благодаря Kotlin DSL, что делает тесты более лаконичными и простыми в поддержке.

class MainTest: KTestCase() {
    
    @Test
    fun testButtonClick() {
        // Поиск кнопки и клик
        KButton { withId(R.id.my_button) }.click()
        
        // Проверка текста на экране после нажатия
        KTextView { withId(R.id.text_view) }.hasText("Hello World!")
    }
}
Kaspresso

Инструмент для UI-тестирования Android-приложений, который предоставляет удобный и мощный API на основе Espresso и Kakao. Он расширяет возможности стандартного Espresso, добавляя удобные функции для написания стабильных и читаемых тестов, а также упрощая работу с нестабильными элементами интерфейса.

class SimpleTest: KaspressoTestCase() {

    @Test
    fun testSimpleUI() = run {
        step("Open the main screen") {
            MainScreen {
                someButton {
                    isVisible()
                    click()
                }
            }
        }
        
        step("Verify the next screen") {
            NextScreen {
                someText {
                    isVisible()
                    hasText("Expected Text")
                }
            }
        }
    }
}
Roborazzi

Библиотека для тестирования пользовательского интерфейса (UI) в Android, разработанная для упрощения и улучшения процесса визуального тестирования. Она позволяет автоматически захватывать изображения пользовательских интерфейсов приложений и сравнивать их с эталонными изображениями, что помогает выявлять изменения в интерфейсе при внесении правок в код.

class MyUITest {
    
    @Test
    fun testMyScreen() {
        // Открыть экран
        launchActivity<MyActivity>()

        // Захватить изображение
        Roborazzi.takeSnapshot("my_screen")

        // Сравнить с эталоном
        Roborazzi.compareSnapshot("my_screen")
    }
}
Mockito

Популярная библиотека для создания моков и стаба в Java, широко используемая в тестировании. Она позволяет разработчикам имитировать поведение объектов, что упрощает тестирование бизнес-логики, обеспечивая при этом изоляцию тестируемых классов от их зависимостей.

public class UserServiceTest {
    
    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Before
    public void setUp() {
        MockitoAnnotations.openMocks(this); // Инициализация моков
    }

    @Test
    public void testGetUser() {
        // Настройка поведения мока
        when(userRepository.findById("123")).thenReturn(new User("123", "John Doe"));

        // Выполнение тестируемого метода
        User user = userService.getUser("123");

        // Проверка результата
        assertNotNull(user);
        assertEquals("John Doe", user.getName());

        // Верификация взаимодействий
        verify(userRepository).findById("123");
    }
}
MockK

Библиотека для создания моков и стаба в Kotlin, используемая в тестировании. Она предоставляет мощные возможности для упрощения написания тестов, позволяя разработчикам легко имитировать поведение объектов и проверять взаимодействия между ними.

class UserService(private val userRepository: UserRepository) {
    fun getUser(id: String): User? {
        return userRepository.findById(id)
    }
}

class UserServiceTest {
    private val userRepository = mockk<UserRepository>()
    private val userService = UserService(userRepository)

    @Test
    fun testGetUser() {
        // Устанавливаем поведение мока
        every { userRepository.findById("123") } returns User("123", "John Doe")

        // Выполняем тестируемый метод
        val user = userService.getUser("123")

        // Проверяем результат
        assertNotNull(user)
        assertEquals("John Doe", user?.name)

        // Проверяем взаимодействие с мок-объектом
        verify { userRepository.findById("123") }
    }
}
AssertJ

Библиотека для тестирования, предоставляющая удобный и выразительный API для написания ассертов в Java и Kotlin. Она значительно упрощает проверку ожидаемых результатов в тестах, делая код более читаемым и поддерживаемым.

public class ExampleTest {
    
    @Test
    public void testPerson() {
        Person person = new Person("John", 25);
        
        assertThat(person)
            .isNotNull()
            .hasFieldOrPropertyWithValue("name", "John")
            .hasFieldOrPropertyWithValue("age", 25);
    }
}
Shot

Библиотека для Android, предназначенная для создания и проверки снапшот-тестов пользовательского интерфейса.

@Test
fun myTest() {
    val activity = launchActivity<MyActivity>()
    activity.onView(withId(R.id.my_view)).check(matches(isDisplayed()))
    shot().screenshot(activity, "my_view_snapshot")
}
Turbine

Библиотека для тестирования Kotlin Flow. Она упрощает написание тестов для Flow-потоков, предоставляя DSL для проверки эмиссий, завершений и исключений в потоках.

class ExampleTest {

    @Test
    fun testFlow() = runBlocking {
        val flow = flow {
            emit(1)
            emit(2)
            emit(3)
        }

        flow.test {
            assert(awaitItem() == 1)
            assert(awaitItem() == 2)
            assert(awaitItem() == 3)
            awaitComplete()  // Ожидаем завершения потока
        }
    }
}
runTest

Функция из библиотеки kotlinx.coroutines, предназначенная для упрощения тестирования кода, использующего корутины. runTest позволяет запускать корутины в тестовом окружении, автоматически обрабатывая их задержки и выполнение, делая тесты быстрыми и надежными. Это особенно полезно для unit-тестов, где нужно протестировать функции с асинхронными операциями.

class CoroutineTest {
    
    // Функция, которую нужно протестировать
    suspend fun fetchData(): String {
        delay(1000)
        return "Data received"
    }

    @Test
    fun testFetchData() = runTest {
        val result = fetchData()
        assertEquals("Data received", result) // Проверяем результат
    }
}
Вопросы на собесе (6)
  1. Что такое Unit-тестирование, и почему оно важно в разработке Android приложений?

    Unit-тестирование проверяет отдельные компоненты кода на корректность работы. Оно важно в Android-разработке, так как помогает выявлять ошибки на ранних этапах, улучшает качество кода и упрощает его поддержку.

  1. Чем интеграционные тесты отличаются от Unit-тестов?

    Интеграционные тесты проверяют взаимодействие нескольких компонентов системы, тогда как Unit-тесты тестируют отдельные модули в изоляции. Интеграционные тесты помогают выявить проблемы на уровне взаимодействия, а Unit-тесты фокусируются на логике отдельных частей кода.

  1. Разница между Mock и Stub?

    Mock создает объект для тестирования, который имитирует поведение реального объекта и проверяет взаимодействия. Stub просто возвращает предопределенные ответы, не проверяя вызовы.

  1. Что такое синтетические тесты?

    Синтетические тесты — это тесты, которые измеряют производительность системы или приложения в специально созданных условиях, используя искусственные данные. Они помогают оценить эффективность отдельных компонентов, но не всегда отражают реальные сценарии использования.

  1. Какую функциональность приложения покрывать Unit-тестами?

    Бизнес-логика.

    Проверки данных.

    Вызовы API.

    Мапперы и форматтеры.

  1. Какую функциональность приложения покрывать UI-тестами?

    Навигацию.

    Отображение интерактивных элементов.

    Ошибки и уведомления.

    Адаптивное отображение.