web-dev-qa-db-fra.com

Android Studio 3.0 Canary 1: les tests Kotlin ou Java faisant référence aux classes Kotlin échouent)

[~ # ~] mise à jour [~ # ~]

Un bogue a été déposé pour ce problème ici: https://youtrack.jetbrains.com/issue/KT-17951

MISE À JOUR 2

Le bug a été corrigé dans Android Studio 3.0 Canary 3

Message d'origine

Je viens de commencer à jouer avec Android Studio 3.0. J'ai activé la prise en charge de kotlin dès le départ. J'ai écrit une classe Kotlin très simple dans mon projet:

data class Wallet(val coins: Int) {
    fun add(value: Int): Wallet = Wallet(coins + value)
    fun substract(value: Int): Wallet = if (coins > value) Wallet(coins + value) else throw InsufficientFundsException()
}

Maintenant, je voulais tester la classe, j'ai d'abord écrit un test unitaire local (répertoire de test) dans Kotlin:

class WalletTestKotlin {

    @Throws(Exception::class)
    @Test
    fun add() {
        Assert.assertEquals(22, Wallet(20).add(2).coins.toLong())
        Assert.assertNotEquals(5, Wallet(2).add(13).coins.toLong())
    }
}

Il se compile et s'exécute mais avec le message d'erreur:

Classe introuvable: "com.agentknopf.hachi.repository.model.WalletTestKotlin" Suite de tests vide.

J'ai donc réécrit le test en Java:

public class WalletTest {

    @Throws(exceptionClasses = Exception.class)
    @Test
    public void add() {
        Assert.assertEquals(22, new Wallet(20).add(2).getCoins());
        Assert.assertNotEquals(5, new Wallet(2).add(13).getCoins());
    }
}

Cependant, ce test a également échoué - cette fois, la classe Kotlin "Wallet" n'a pas été trouvée:

Java.lang.NoClassDefFoundError: com/example/repository/model/Wallet

Je me demande si je manque quelque chose ... L'exécution d'un test Java, qui ne fait pas référence aux classes Kotlin, mais à Java se terminent uniquement avec succès).

Mon fichier build.gradle de projet est celui par défaut:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext.kotlin_version = '1.1.2-4'
    repositories {
        maven { url 'https://maven.google.com' }
        jcenter()
    }
    dependencies {
        classpath 'com.Android.tools.build:gradle:3.0.0-alpha1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
        maven { url 'https://maven.google.com' }
        mavenCentral()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

Les dépendances de mon build.gradle spécifique au module:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    //Kotlin support
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    //Testing libraries
    androidTestCompile('com.Android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.Android.support', module: 'support-annotations'
    })
    testCompile 'junit:junit:4.12'
    testCompile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
}
37
AgentKnopf

Solution (pour l'instant):

Mettez ceci dans votre build.gradle (au niveau de l'application):

task copyTestClasses(type: Copy) {
    from "build/tmp/kotlin-classes/debugUnitTest"
    into "build/intermediates/classes/debug"
}

Ensuite, modifiez la configuration de test JUnit Run/Debug dans le bas vers le bas 'avant le lancement', il y a 'Gradle-aware make' dedans, + une autre section, sélectionnez gradle task, sélectionnez le projet build.gradle fichier dans lequel il se trouve et tapez copyTestClasses. Cliquez ici pour les captures d'écran de cadre de test différent, mais où la plomberie fonctionne de la même manière.

Vous devrez peut-être modifier/ajouter plus de plomberie de répertoire en fonction de votre type de build. La façon dont vous trouvez ces endroits étranges est par recherche brute dans l'arborescence du projet pour les fichiers .class pertinents.

15
kat

Remarque: le problème a été résolu avec Android Studio 3.3 Canary

Merci à @kat de m'avoir montré dans la bonne direction. Tout d'abord - un n bug a été déposé pour le problème mentionné dans l'OP.

Ma configuration est la suivante: Les tests Kotlin sont dans le même répertoire que Java tests. Pour que les deux cas d'utilisation fonctionnent:

  • Reportez-vous aux classes kotlin dans les tests Java
  • Se référer aux classes kotlin dans les tests kotlin

Supprimez d'abord toutes les autres configurations de test que vous pourriez avoir. J'ai ensuite ajouté ces deux tâches de construction gradle dans mon build.gradle au niveau de l'application:

Android {
    ...

    task copyTestClasses(type: Copy) {
        from "build/tmp/kotlin-classes/debugUnitTest"
        into "build/intermediates/classes/debug"
    }

    task copySdkClasses(type: Copy) {
        from "build/tmp/kotlin-classes/debug"
        into "build/intermediates/classes/debug"
    }
}

J'ai ensuite ouvert le menu de configuration de l'exécution via Exécuter> Modifier les configurations. Là, à gauche, j'ai supprimé les configurations de haut niveau Android JUnit. J'ai ensuite cliqué sur Paramètres par défaut> Android JUnit et j'ai modifié la configuration comme suit:

  • Type de test = Tout dans l'emballage
  • Mode formulaire = aucun
  • Répéter = une fois
  • Package = mon package de base comme com.yourname
  • Recherche de tests = dans un module unique
  • J'ai laissé la section centrale intacte (options VM, etc.)
  • Dans la section "Avant le lancement", ajoutez deux entrées en cliquant sur l'icône plus:
  • Exécuter la tâche gradle: sélectionnez votre build.gradle de votre module d'application, puis dans les tâches, entrez le nom copyTestClasses et cliquez sur OK
  • Ajoutez une deuxième tâche Run Gradle comme précédemment, mais cette fois comme nom de tâche, entrez copySdkClasses et cliquez sur OK
  • Cliquez sur Appliquer dans la configuration et lancez maintenant vos tests

Voici à quoi ça ressemble au final: enter image description here

12
AgentKnopf

@AgentKnopf est parfait, mais vous devez ajouter des tâches à chaque nouveau scénario de test comme celui-ci

enter image description here

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile("com.Android.support.test.espresso:espresso-core:$espresso_version", {
        exclude group: 'com.Android.support', module: 'support-annotations'
    })
    testCompile "junit:junit:$junit_version"
    // kotlin
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    ...............
}
// add 2 task in run config to make kotlin test working
// for junit
task copyTestClasses(type: Copy) {
    from "build/tmp/kotlin-classes/debugUnitTest"
    into "build/intermediates/classes/debug"
}
// for instrumented test
task copySdkClasses(type: Copy) {
    from "build/tmp/kotlin-classes/debug"
    into "build/intermediates/classes/debug"
}

afterEvaluate {
    compileDebugUnitTestSources.dependsOn copyTestClasses
    compileReleaseUnitTestSources.dependsOn copyTestClasses

    compileDebugAndroidTestSources.dependsOn copySdkClasses
}

ajouter des tâches automatiquement pour vous

4
vuhung3990