Локальный тест выполняется непосредственно на вашей рабочей станции, а не на устройстве Android или в эмуляторе. Таким образом, для запуска тестов он использует вашу локальную виртуальную машину Java (JVM), а не устройство Android. Локальные тесты позволяют быстрее оценить логику вашего приложения. Однако невозможность взаимодействия с платформой Android создает ограничение на типы тестов, которые вы можете запускать.
Модульный тест проверяет поведение небольшого участка кода — тестируемого модуля . Это делается путем выполнения этого кода и проверки результата.
Модульные тесты обычно просты, но их настройка может быть проблематичной, если тестируемый модуль не спроектирован с учетом тестируемости:
- Код, который вы хотите проверить, должен быть доступен из теста. Например, вы не можете протестировать частный метод напрямую. Вместо этого вы тестируете класс, используя его общедоступные API.
- Чтобы запустить модульные тесты изолированно , зависимости тестируемого модуля должны быть заменены компонентами, которые вы контролируете, такими как подделки или другие тестовые двойники . Это особенно проблематично, если ваш код зависит от платформы Android.
Чтобы узнать об распространенных стратегиях модульного тестирования в Android, прочтите «Что тестировать» .
Место проведения локальных испытаний
По умолчанию исходные файлы для локальных модульных тестов помещаются в module-name/src/test/
. Этот каталог уже существует, когда вы создаете новый проект с помощью Android Studio.
Добавление зависимостей тестирования
Вам также необходимо настроить зависимости тестирования для вашего проекта, чтобы использовать стандартные API, предоставляемые платформой тестирования JUnit .
Для этого откройте файл build.gradle
модуля вашего приложения и укажите следующие библиотеки в качестве зависимостей. Используйте функцию testImplementation
чтобы указать, что они применяются к локальному набору исходных текстов тестов, а не к приложению:
dependencies {
// Required -- JUnit 4 framework
testImplementation "junit:junit:$jUnitVersion"
// Optional -- Robolectric environment
testImplementation "androidx.test:core:$androidXTestVersion"
// Optional -- Mockito framework
testImplementation "org.mockito:mockito-core:$mockitoVersion"
// Optional -- mockito-kotlin
testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
// Optional -- Mockk framework
testImplementation "io.mockk:mockk:$mockkVersion"
}
Создайте локальный класс модульного теста.
Вы пишете свой локальный класс модульного теста как тестовый класс JUnit 4 .
Для этого создайте класс, содержащий один или несколько методов тестирования, обычно в module-name/src/test/
. Метод тестирования начинается с аннотации @Test
и содержит код для тестирования и проверки отдельного аспекта компонента, который вы хотите протестировать.
В следующем примере показано, как реализовать класс локального модульного теста. Тестовый метод emailValidator_correctEmailSimple_returnsTrue()
пытается проверить isValidEmail()
, который является методом внутри приложения. Тестовая функция вернет true, если isValidEmail()
также вернет true.
Котлин
import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test class EmailValidatorTest { @Test fun emailValidator_CorrectEmailSimple_ReturnsTrue() { assertTrue(EmailValidator.isValidEmail("name@email.com")) } }
Ява
import org.junit.Test; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; class EmailValidatorTest { @Test public void emailValidator_CorrectEmailSimple_ReturnsTrue() { assertTrue(EmailValidator.isValidEmail("name@email.com")); } }
Вам следует создать читаемые тесты, которые проверят, возвращают ли компоненты вашего приложения ожидаемые результаты. Мы рекомендуем вам использовать библиотеку утверждений, такую как junit.Assert , Hamcrest или Truth . Фрагмент выше представляет собой пример использования junit.Assert
.
Мокабельная библиотека Android
Когда вы выполняете локальные модульные тесты, подключаемый модуль Android Gradle включает библиотеку, содержащую все API-интерфейсы платформы Android, соответствующие версии, используемой в вашем проекте. Библиотека содержит все общедоступные методы и классы этих API, но код внутри методов был удален. Если осуществляется доступ к какому-либо из методов, тест выдает исключение.
Это позволяет создавать локальные тесты при ссылке на классы в платформе Android, такие как Context
. Что еще более важно, он позволяет вам использовать макетную структуру с классами Android.
Издевательство над зависимостями Android
Типичная проблема — обнаружить, что класс использует строковый ресурс. Вы можете получить строковые ресурсы, вызвав метод getString()
в классе Context
. Однако локальный тест не может использовать Context
или любой из его методов, поскольку они принадлежат платформе Android. В идеале вызов getString()
должен быть вынесен из класса, но это не всегда практично. Решение состоит в том, чтобы создать макет или заглушку Context
, который всегда возвращает одно и то же значение при вызове метода getString()
.
С помощью библиотеки Mockable Android и фреймворков макетирования, таких как Mockito или MockK , вы можете программировать поведение макетов классов Android в своих модульных тестах.
Чтобы добавить макет объекта в локальный модульный тест с помощью Mockito, следуйте этой модели программирования:
- Включите зависимость библиотеки Mockito в файл
build.gradle
, как описано в разделе Настройка среды тестирования . - В начале определения класса модульного теста добавьте аннотацию
@RunWith(MockitoJUnitRunner.class)
. Эта аннотация сообщает средству запуска тестов Mockito, что нужно проверить правильность использования вами платформы, и упрощает инициализацию ваших фиктивных объектов. - Чтобы создать макет объекта для зависимости Android, добавьте аннотацию
@Mock
перед объявлением поля. - Чтобы заглушить поведение зависимости, вы можете указать условие и возвращаемое значение, когда условие выполняется, используя методы
when()
иthenReturn()
.
В следующем примере показано, как можно создать модульный тест, использующий макет объекта Context
в Kotlin, созданный с помощью Mockito-Kotlin .
import android.content.Context
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.junit.MockitoJUnitRunner
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
private const val FAKE_STRING = "HELLO WORLD"
@RunWith(MockitoJUnitRunner::class)
class MockedContextTest {
@Mock
private lateinit var mockContext: Context
@Test
fun readStringFromContext_LocalizedString() {
// Given a mocked Context injected into the object under test...
val mockContext = mock<Context> {
on { getString(R.string.name_label) } doReturn FAKE_STRING
}
val myObjectUnderTest = ClassUnderTest(mockContext)
// ...when the string is returned from the object under test...
val result: String = myObjectUnderTest.getName()
// ...then the result should be the expected one.
assertEquals(result, FAKE_STRING)
}
}
Дополнительные сведения об использовании платформы Mockito см. в справочнике по API Mockito и классе SharedPreferencesHelperTest
в примере кода . Также попробуйте Android Testing Codelab .
Ошибка: «Метод... не осмеян»
Библиотека Mockable Android выдает исключение, если вы пытаетесь получить доступ к любому из ее методов с Error: "Method ... not mocked
.
Если выдаваемые исключения создают проблемы для ваших тестов, вы можете изменить поведение так, чтобы вместо этого методы возвращали либо значение NULL, либо ноль, в зависимости от типа возвращаемого значения. Для этого добавьте следующую конфигурацию в файл build.gradle
верхнего уровня вашего проекта в Groovy:
android {
...
testOptions {
unitTests.returnDefaultValues = true
}