6
votes

Kotlin-multiplatform: Comment exécuter des tests unitaires iOS

Je travaille sur une bibliothèque multiplateforme Kotlin pour Android et iOS. Je veux écrire un test unitaire spécifique à la plate-forme. Les tests s'exécutent comme prévu pour le code partagé et Android mais pas pour iOS.

Sous le fichier build.gradle du module de code partagé.

└── src
    ├── commonMain
    │   └── kotlin
    ├── commonTest
    │   └── kotlin
    ├── androidMain
    │   └── kotlin
    ├── androidTest
    │   └── kotlin
    ├── iOSMain
    │   └── kotlin
    └── iOSTest
        └── kotlin

et la structure du module SharedCode est:

apply plugin: "kotlin-multiplatform"

kotlin {
    targets {
        final def iOSTarget = System.getenv('SDK_NAME')?.startsWith("iphoneos") \
                              ? presets.iosArm64 : presets.iosX64

        fromPreset(iOSTarget, 'iOS') {
            compilations.main.outputKinds('FRAMEWORK')
        }

        fromPreset(presets.jvm, 'android')
    }

    sourceSets {
        commonMain.dependencies {
            implementation "org.jetbrains.kotlin:kotlin-stdlib-common"
        }
        commonTest.dependencies {
            implementation 'org.jetbrains.kotlin:kotlin-test'
            implementation 'org.jetbrains.kotlin:kotlin-test-junit'
        }
        androidMain.dependencies {
            implementation "org.jetbrains.kotlin:kotlin-stdlib"
        }
        androidTest {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-test'
                implementation 'org.jetbrains.kotlin:kotlin-test-junit'
            }
        }
        iOSMain.dependencies {
        }
        iOSTest.dependencies {
            implementation 'org.jetbrains.kotlin:kotlin-test'
            implementation 'org.jetbrains.kotlin:kotlin-test-junit'
        }
    }
}

// workaround for https://youtrack.jetbrains.com/issue/KT-27170
configurations {
    compileClasspath
}

task packForXCode(type: Sync) {
    final File frameworkDir = new File(buildDir, "xcode-frameworks")
    final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG'

    inputs.property "mode", mode
    dependsOn kotlin.targets.iOS.compilations.main.linkTaskName("FRAMEWORK", mode)

    from { kotlin.targets.iOS.compilations.main.getBinary("FRAMEWORK", mode).parentFile }
    into frameworkDir

    doLast {
        new File(frameworkDir, 'gradlew').with {
            text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$@\n"
            setExecutable(true)
        }
    }
}

tasks.build.dependsOn packForXCode

Les tests ajoutés dans androidTest et commonTest fonctionnent comme prévu, mais ceux ajoutés dans iOSTest ne fonctionnent pas.

Cependant, si je remplace la ligne fromPreset (iOSTarget , 'iOS') {compilations.main.outputKinds ('FRAMEWORK')} pour fromPreset (presets.macosX64, 'macos') et mettez à jour les noms de répertoires en conséquence, les tests dans le Le dossier macosTest s'exécute comme prévu.

Pourquoi n'est-il pas possible d'exécuter un test iOS lors de la création de frameworks iOS? Une idée de ce que je fais mal ou comment je peux faire en sorte que cela fonctionne? :)


0 commentaires

3 Réponses :


4
votes

Actuellement, le plugin kotlin-multiplatform ne prend en charge que l'exécution de tests pour les plates-formes hôtes (par exemple macOS ou Windows). Mais vous pouvez ajouter manuellement une tâche pour exécuter des tests iOS sur un simualtor:

task iosTest {
    def device = project.findProperty("iosDevice")?.toString() ?: "iPhone 8"
    dependsOn 'linkTestDebugExecutableIos'
    group = JavaBasePlugin.VERIFICATION_GROUP
    description = "Runs tests for target 'ios' on an iOS simulator"

    doLast {
        def binary = kotlin.targets.ios.binaries.getExecutable('test', 'DEBUG').outputFile
        exec {
            commandLine 'xcrun', 'simctl', 'spawn', device, binary.absolutePath
        }
    }
}

Voir le script de construction complet ici .


3 commentaires

Génial, @IlyaMatveev c'est ce que je cherchais. Merci! :RÉ


Ouvre-t-il le simulateur ios et exécute des tests? Dans mon cas, il n'ouvre pas le simulateur ios comme il le fait lorsque j'exécute un test dans un projet xcode.


@mkkrolik, non, cela n'ouvre pas le simulateur de périphérique mais les tests sont exécutés dans le processus du simulateur.



2
votes

La réponse de @IlyaMatveev fonctionne parfaitement pour moi. Mais j'ai dû mettre à jour deux lignes en utilisant Kotlin Version 1.3.41:

dependOn 'linkTestDebugExecutableIos' est maintenant dependOn 'linkDebugTestIos'

def binary = kotlin.targets.ios.binaries.getExecutable ('test', 'DEBUG'). outputFile est maintenant def binary = kotlin.targets.ios.binaries.getTest ("DEBUG"). outputFile


0 commentaires

3
votes

Comme je rencontrais des problèmes, je publierai ma solution ici.

Avec Kotlin 1.3.50 et XCode 11 j'ai dû changer ma ligne de commande arguments:

val iosTest: Task by tasks.creating {
    val device = project.findProperty("iosDevice")?.toString() ?: "iPhone 8"
    val testExecutable = kotlin.targets.getByName<KotlinNativeTarget>("iosX64").binaries.getTest("DEBUG")
    dependsOn(testExecutable.linkTaskName)
    group = JavaBasePlugin.VERIFICATION_GROUP
    description = "Runs tests for target 'ios' on an iOS simulator"

    doLast {
        exec {
            println(testExecutable.outputFile.absolutePath)
            commandLine( "xcrun", "simctl", "spawn", "--standalone", device, testExecutable.outputFile.absolutePath)
        }
    }
}

tasks.getByName("allTests").dependsOn(iosTest)


1 commentaires

cela devrait être marqué comme réponse pour la dernière version de kotlin et xcode