Тестирование мультиплатформенного приложения − руководство
В этом руководстве вы узнаете, как создавать, настраивать и запускать тесты в приложениях Kotlin Multiplatform.
Тесты в мультиплатформенных проектах можно разделить на две категории:
Тесты для общего кода. Эти тесты можно запускать на любой платформе с помощью любого поддерживаемого фреймворка.
Тесты для платформозависимого кода. Они необходимы для проверки платформозависимой логики. Для них используется платформозависимый фреймворк, который может предоставить дополнительные возможности, например более богатый API и широкий набор проверок.
В мультиплатформенных проектах поддерживаются обе категории. Сначала в этом руководстве вы узнаете, как настроить, создать и запустить модульные тесты для общего кода в простом проекте Kotlin Multiplatform. Затем вы рассмотрите более сложный пример, для которого нужны тесты как для общего, так и для платформозависимого кода.
Тестирование простого мультиплатформенного проекта
Создание проекта
В кратком руководстве выполните инструкции по настройке среды для разработки Kotlin Multiplatform.
В IntelliJ IDEA выберите Файл | Создать | Проект.
На панели слева выберите Kotlin Multiplatform.
-
В окне Новый проект укажите следующие значения:
Имя: KMP testing
Идентификатор проекта: kmp.project.testing
Выберите целевую платформу Android. Если вы используете Mac, выберите также iOS. Обязательно выберите параметр Не делиться пользовательским интерфейсом.
-
Снимите флажок Добавить тесты и нажмите Создать.

Написание кода
В каталоге sharedLogic/src/commonMain/kotlin создайте пакет common.example.search. В этом пакете создайте файл Kotlin Grep.kt со следующей функцией:
fun grep(lines: List<String>, pattern: String, action: (String) -> Unit) {
val regex = pattern.toRegex()
lines.filter(regex::containsMatchIn)
.forEach(action)
}
Эта функция имитирует команду grep в UNIX. Функция принимает строки текста, шаблон в виде регулярного выражения и функцию, которая вызывается при каждом совпадении строки с шаблоном.
Добавление тестов
Теперь протестируем общий код. Важную роль в этом играет набор исходного кода для общих тестов, у которого в качестве зависимости подключена библиотека API kotlin.test.
-
Убедитесь, что в файле
sharedLogic/build.gradle.ktsесть зависимость от библиотекиkotlin.test:sourceSets { //... commonTest.dependencies { implementation(libs.kotlin.test) } } -
В наборе исходного кода
commonTestхранятся все общие тесты. Создайте в проекте каталог с таким же именем:Щёлкните правой кнопкой мыши каталог
sharedLogic/srcи выберите Создать | Каталог. В IDE появится список вариантов.Начните вводить путь
commonTest/kotlin, чтобы сузить список вариантов, а затем выберите его:
В каталоге
commonTest/kotlinсоздайте пакетcommon.example.search.-
В этом пакете создайте файл
Grep.ktи добавьте в него следующий модульный тест:import kotlin.test.Test import kotlin.test.assertContains import kotlin.test.assertEquals class GrepTest { companion object { val sampleData = listOf( "123 abc", "abc 123", "123 ABC", "ABC 123" ) } @Test fun shouldFindMatches() { val results = mutableListOf<String>() grep(sampleData, "[a-z]+") { results.add(it) } assertEquals(2, results.size) for (result in results) { assertContains(result, "abc") } } }
Как видите, импортируемые аннотации и проверки не зависят ни от платформы, ни от фреймворка. При запуске этого теста платформозависимый фреймворк предоставит средство запуска тестов.
Знакомство с API kotlin.test
Библиотека kotlin.test предоставляет не зависящие от платформы аннотации и проверки, которые можно использовать в тестах. Такие аннотации, как Test, соответствуют аннотациям выбранного фреймворка или их ближайшим аналогам.
Проверки выполняются с помощью реализации интерфейса Asserter. Этот интерфейс определяет различные проверки, которые обычно выполняются при тестировании. API предоставляет реализацию по умолчанию, но обычно используется реализация, специфичная для конкретного фреймворка.
Например, на JVM поддерживаются фреймворки JUnit 4, JUnit 5 и TestNG. На Android вызов assertEquals() может привести к вызову asserter.assertEquals(), где объект asserter является экземпляром JUnit4Asserter. На iOS реализация типа Asserter по умолчанию используется вместе со средством запуска тестов Kotlin/Native.
Запуск тестов
Запустить тест можно следующими способами:
Запустить тестовую функцию
shouldFindMatches()с помощью значка Запустить на полосе рядом с кодом.Запустить файл теста через его контекстное меню.
Запустить тестовый класс
GrepTestс помощью значка Запустить на полосе рядом с кодом.
Также можно воспользоваться сочетанием клавиш ⌃ ⇧ F10/Ctrl+Shift+F10. Независимо от выбранного способа, вы увидите список целевых платформ для запуска теста:
Для варианта android тесты запускаются с помощью JUnit 4. Для варианта iosSimulatorArm64 компилятор Kotlin обнаруживает аннотации для тестирования и создаёт тестовый бинарный файл, который запускается собственным средством запуска тестов Kotlin/Native.
Пример вывода после успешного запуска теста:

Работа с более сложными проектами
Написание тестов для общего кода
Вы уже создали тест для общего кода с помощью функции grep(). Теперь рассмотрим более сложный тест общего кода с классом CurrentRuntime. Этот класс содержит сведения о платформе, на которой выполняется код. Например, при локальном запуске модульных тестов Android на JVM в нём могут быть значения «OpenJDK» и «17.0».
Экземпляр CurrentRuntime нужно создать, указав название платформы и её версию в виде строк; версия является необязательной. Если версия указана, достаточно привести начальное число строки, если оно есть.
В каталоге
commonMain/kotlinсоздайте пакетorg.kmp.testing.-
В этом пакете создайте файл
CurrentRuntime.ktи добавьте в него следующую реализацию:class CurrentRuntime(val name: String, rawVersion: String?) { companion object { val versionRegex = Regex("^[0-9]+(\\.[0-9]+)?") } val version = parseVersion(rawVersion) override fun toString() = "$name version $version" private fun parseVersion(rawVersion: String?): String { val result = rawVersion?.let { versionRegex.find(it) } return result?.value ?: "unknown" } } В каталоге
commonTest/kotlinсоздайте пакетorg.kmp.testing.-
В этом пакете создайте файл
CurrentRuntimeTest.ktи добавьте в него следующий тест, не зависящий от платформы и фреймворка:import kotlin.test.Test import kotlin.test.assertEquals class CurrentRuntimeTest { @Test fun shouldDisplayDetails() { val runtime = CurrentRuntime("MyRuntime", "1.1") assertEquals("MyRuntime version 1.1", runtime.toString()) } @Test fun shouldHandleNullVersion() { val runtime = CurrentRuntime("MyRuntime", null) assertEquals("MyRuntime version unknown", runtime.toString()) } @Test fun shouldParseNumberFromVersionString() { val runtime = CurrentRuntime("MyRuntime", "1.2 Alpha Experimental") assertEquals("MyRuntime version 1.2", runtime.toString()) } @Test fun shouldHandleMissingVersion() { val runtime = CurrentRuntime("MyRuntime", "Alpha Experimental") assertEquals("MyRuntime version unknown", runtime.toString()) } }
Этот тест можно запустить любым из доступных в IDE способов.
Добавление платформозависимых тестов
Теперь, когда вы научились писать тесты для общего кода, рассмотрим написание платформозависимых тестов для Android и iOS.
Чтобы создать экземпляр CurrentRuntime, объявите функцию в общем файле CurrentRuntime.kt следующим образом:
expect fun determineCurrentRuntime(): CurrentRuntime
Для каждой поддерживаемой платформы нужно предоставить отдельную реализацию функции. В противном случае сборка завершится с ошибкой. Помимо реализации этой функции на каждой платформе, следует добавить тесты. Давайте создадим их для Android и iOS.
Для Android
В каталоге
androidMain/kotlinсоздайте пакетorg.kmp.testing.-
В этом пакете создайте файл
AndroidRuntime.ktи добавьте в него фактическую реализацию ожидаемой функцииdetermineCurrentRuntime():actual fun determineCurrentRuntime(): CurrentRuntime { val name = System.getProperty("java.vm.name") ?: "Android" val version = System.getProperty("java.version") return CurrentRuntime(name, version) } -
Создайте каталог для тестов внутри каталога
sharedLogic/src:Щёлкните правой кнопкой мыши каталог
sharedLogic/srcи выберите Создать | Каталог. В IDE появится список вариантов.-
Начните вводить путь
androidHostTest/kotlin, чтобы сузить список вариантов, а затем выберите его:
В каталоге
androidHostTest/kotlinсоздайте пакетorg.kmp.testing.-
В этом пакете создайте файл
AndroidRuntimeTest.ktи добавьте в него следующий тест Android. Чтобы тест прошёл, укажите фактическое имя и версию среды выполнения (но также полезно посмотреть, как тест завершается с ошибкой):import kotlin.test.Test import kotlin.test.assertContains import kotlin.test.assertEquals class AndroidRuntimeTest { @Test fun shouldDetectAndroid() { val runtime = determineCurrentRuntime() assertContains(runtime.name, "OpenJDK") assertEquals(runtime.version, "21.0") } }
Может показаться странным, что тест Android запускается на локальной JVM. Это объясняется тем, что такие тесты выполняются на текущем компьютере как локальные модульные тесты. Как описано в документации Android Studio, они отличаются от инструментированных тестов, которые запускаются на устройстве или эмуляторе.
В проект можно добавить и другие типы тестов. Чтобы узнать об инструментированных тестах, ознакомьтесь с этим руководством Touchlab.
Для iOS
В каталоге
iosMain/kotlinсоздайте каталогorg.kmp.testing.-
В этом каталоге создайте файл
IOSRuntime.ktи добавьте в него фактическую реализацию ожидаемой функцииdetermineCurrentRuntime():import kotlin.experimental.ExperimentalNativeApi import kotlin.native.Platform @OptIn(ExperimentalNativeApi::class) actual fun determineCurrentRuntime(): CurrentRuntime { val name = Platform.osFamily.name.lowercase() return CurrentRuntime(name, null) } -
Создайте новый каталог в каталоге
sharedLogic/src:Щёлкните правой кнопкой мыши каталог
sharedLogic/srcи выберите Создать | Каталог. В IDE появится список вариантов.Начните вводить путь
iosTest/kotlin, чтобы сузить список вариантов, а затем выберите его:
В каталоге
iosTest/kotlinсоздайте каталогorg.kmp.testing.-
В этом каталоге создайте файл
IOSRuntimeTest.ktи добавьте в него следующий тест iOS:import kotlin.test.Test import kotlin.test.assertEquals class IOSRuntimeTest { @Test fun shouldDetectOS() { val runtime = determineCurrentRuntime() assertEquals(runtime.name, "ios") assertEquals(runtime.version, "unknown") } }
Запуск нескольких тестов и анализ отчётов
Теперь у вас есть код для общего кода, реализаций Android и iOS, а также соответствующие тесты. Структура каталогов проекта должна выглядеть примерно так:

Отдельные тесты можно запускать из контекстного меню или с помощью сочетания клавиш. Ещё один способ — использовать задачи Gradle. Например, если запустить задачу Gradle allTests, все тесты проекта будут выполнены соответствующими средствами запуска:

При запуске тестов, помимо вывода в IDE, создаются HTML-отчёты. Их можно найти в каталоге sharedLogic/build/reports/tests:
Запустите задачу allTests и изучите созданные отчёты:
Файл
allTests/index.htmlсодержит объединённые отчёты об общих тестах и тестах iOS (тесты iOS зависят от общих тестов и выполняются после них).Папки
testDebugUnitTestиtestReleaseUnitTestсодержат отчёты для обоих вариантов сборки Android по умолчанию. (В настоящее время отчёты о тестах Android не объединяются автоматически с отчётомallTests.)

Правила использования тестов в мультиплатформенных проектах
Теперь вы умеете создавать, настраивать и запускать тесты в приложениях Kotlin Multiplatform. При работе с тестами в будущих проектах помните о следующем:
При написании тестов для общего кода используйте только мультиплатформенные библиотеки, например kotlin.test. Добавляйте зависимости в набор исходного кода
commonTest.Тип
Asserterиз APIkotlin.testследует использовать только косвенно. Хотя экземплярAsserterдоступен, в тестах его использовать не нужно.Всегда используйте только API библиотеки тестирования. К счастью, компилятор и IDE не позволяют использовать функциональность, специфичную для фреймворка.
Для запуска тестов в
commonTestневажно, какой фреймворк вы используете, однако рекомендуется запускать тесты с каждым предполагаемым фреймворком, чтобы убедиться в правильности настройки среды разработки.Учитывайте физические различия. Например, инерция прокрутки и значения трения отличаются в зависимости от платформы и устройства, поэтому одинаковая скорость прокрутки может привести к разным положениям прокрутки. Всегда тестируйте компоненты на целевой платформе, чтобы убедиться в ожидаемом поведении.
При написании тестов для платформозависимого кода можно использовать возможности соответствующего фреймворка, например аннотации и расширения.
Тесты можно запускать как из IDE, так и с помощью задач Gradle.
При запуске тестов HTML-отчёты о тестировании создаются автоматически.
Что дальше?
Изучите структуру мультиплатформенных проектов в разделе «Знакомство со структурой мультиплатформенного проекта».
Познакомьтесь с Kotest — ещё одним мультиплатформенным фреймворком для тестирования из экосистемы Kotlin. Kotest позволяет писать тесты в разных стилях и поддерживает дополнительные подходы к обычному тестированию, включая тестирование на основе данных и свойств.
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/multiplatform/multiplatform-run-tests.html