Ausführen von Kotlin-Tests mit Gradle
Wenn wir ein neues Projekt mit Kotlin starten, müssen wir als Erstes ein Gradle-Projekt erstellen, das unsere Anwendung kompilieren und ausführen kann. Unsere Arbeit ist jedoch noch nicht getan. Wir müssen noch einen Weg finden, unsere automatisierten Tests zu kompilieren und auszuführen. Dieser Blogbeitrag hilft uns bei der Erstellung eines Gradle-Projekts, das sowohl Unit- als auch Integrationstests kompilieren und ausführen kann, die JUnit 5 verwenden.
Nachdem wir diesen Blogbeitrag fertiggestellt haben, werden wir:
- Kann ein Gradle-Projekt erstellen, das Komponenten- und Integrationstests kompilieren kann, die Kotlin verwenden.
- Wissen, wie wir benutzerdefinierte Testsätze zu unserem Gradle-Build hinzufügen können.
- Verstehen, wie wir die Abhängigkeiten unserer Integrationstests deklarieren können.
- Wissen, wie wir die aufgerufenen Tests mit JUnit 5-Tags filtern können.
- Kann sowohl Einheiten- als auch Integrationstests mit Gradle ausführen.
Beginnen wir damit, einen Blick auf die Anforderungen unseres Gradle-Builds zu werfen.
Die Anforderungen unseres Gradle-Builds
Die Anforderungen unseres Gradle-Builds sind:
- Der gesamte Code (Anwendung und Tests) muss Kotlin verwenden.
- Einheiten- und Integrationstests müssen separate Quell- und Ressourcenverzeichnisse haben.
- Es muss möglich sein, nur Einheiten- oder Integrationstests auszuführen.
- Es muss möglich sein, sowohl Unit- als auch Integrationstests auszuführen.
- Wenn ein Integrationstest fehlschlägt, muss unser Build ebenfalls fehlschlagen.
- Integration und Komponententests müssen unterschiedliche HTML-Berichtsverzeichnisse haben.
Als nächstes werfen wir einen kurzen Blick auf das zu testende System.
Einführung in das zu testende System
In diesem Blogbeitrag werden wir sowohl Unit- als auch Integrationstests für MessageService
schreiben Klasse. Diese Klasse hat eine Methode namens getMessage()
was die Nachricht zurückgibt:'Hello World!'.
Der Quellcode von MessageService
Klasse sieht wie folgt aus:
class MessageService { fun getMessage(): String { return "Hello World!" } }
Lassen Sie uns weitermachen und herausfinden, wie wir ein Gradle-Projekt erstellen können, das nur Einheitentests ausführen kann.
Einheitentests mit Gradle ausführen
Wenn wir ein Gradle-Projekt erstellen möchten, das nur Komponententests ausführen kann, müssen wir die folgenden Schritte ausführen:
Zuerst , da wir JVM verwenden, müssen wir das Kotlin JVM Gradle-Plugin anwenden. Nachdem wir dieses Plugin angewendet haben, wird unser build.gradle Datei sieht wie folgt aus:
plugins { id 'org.jetbrains.kotlin.jvm' version '1.3.31' }
Zweiter haben wir sichergestellt, dass Gradle das zentrale Maven-Repository verwendet, wenn es die Abhängigkeiten unseres Gradle-Projekts auflöst. Nachdem wir das verwendete Repository konfiguriert haben, wird der Quellcode unserer build.gradle Datei sieht wie folgt aus:
plugins { id 'org.jetbrains.kotlin.jvm' version '1.3.31' } repositories { mavenCentral() }
Dritter , müssen wir die Abhängigkeiten unserer Anwendung angeben. Da unsere Anwendung Kotlin verwendet, müssen wir die Abhängigkeit der Kotlin-Standardbibliothek zu implementation
hinzufügen Abhängigkeitskonfiguration.
Nachdem wir dies getan haben, wird unsere build.gradle Datei sieht wie folgt aus:
plugins { id 'org.jetbrains.kotlin.jvm' version '1.3.31' } repositories { mavenCentral() } dependencies { implementation('org.jetbrains.kotlin:kotlin-stdlib:1.3.31') }
Vierter , müssen wir die Testabhängigkeiten angeben. Da wir Tests für eine Kotlin-Anwendung schreiben möchten, indem wir Kotlin und JUnit 5 verwenden, können wir die Testabhängigkeiten angeben, indem wir diesen Schritten folgen:
- Fügen Sie die (nicht obligatorische) AssertJ Core-Abhängigkeit zu
testImplementation
hinzu Abhängigkeitskonfiguration. - Fügen Sie die JUnit Jupiter API-Abhängigkeit zu
testImplementation
hinzu Abhängigkeitskonfiguration. - Fügen Sie die JUnit Jupiter Engine-Abhängigkeit zu
testRuntime
hinzu Abhängigkeitskonfiguration.
Nachdem wir die Testabhängigkeiten angegeben haben, wird unsere build.gradle Datei sieht wie folgt aus:
plugins { id 'org.jetbrains.kotlin.jvm' version '1.3.31' } repositories { mavenCentral() } dependencies { implementation('org.jetbrains.kotlin:kotlin-stdlib:1.3.31') testImplementation( 'org.assertj:assertj-core:3.12.2', 'org.junit.jupiter:junit-jupiter-api:5.4.2' ) testRuntime('org.junit.jupiter:junit-jupiter-engine:5.4.2') }
Fünfter , müssen wir sicherstellen, dass Gradle unsere Unit-Tests mit JUnit 5 ausführt. Nachdem wir die test
konfiguriert haben Aufgabe, unser build.gradle Datei sieht wie folgt aus:
plugins { id 'org.jetbrains.kotlin.jvm' version '1.3.31' } repositories { mavenCentral() } dependencies { implementation('org.jetbrains.kotlin:kotlin-stdlib:1.3.31') testImplementation( 'org.assertj:assertj-core:3.12.2', 'org.junit.jupiter:junit-jupiter-api:5.4.2' ) testRuntime('org.junit.jupiter:junit-jupiter-engine:5.4.2') } test { useJUnitPlatform() }
Wir haben jetzt unseren Gradle-Build konfiguriert. Bevor wir jedoch unsere Unit-Tests ausführen können, müssen wir eine Testklasse schreiben und diese Klasse in das src/test/kotlin-Verzeichnis legen . Der Quellcode unserer Testklasse sieht wie folgt aus:
import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test class MessageServiceTest { private lateinit var service: MessageService @BeforeEach fun configureSystemUnderTest() { service = MessageService() } @Test @DisplayName("Should return the correct message") fun shouldReturnCorrectMessage() { val message = service.getMessage() assertThat(message).isEqualTo("Hello World!") } }
Wir können jetzt unsere Komponententests mit dem folgenden Befehl ausführen:gradle clean test . Wenn wir diesen Befehl ausführen, sehen wir, dass Gradle unsere Anwendung kompiliert und unsere Komponententests kompiliert und ausführt:
> Task :clean > Task :compileKotlin > Task :compileJava NO-SOURCE > Task :processResources NO-SOURCE > Task :classes UP-TO-DATE > Task :compileTestKotlin > Task :compileTestJava NO-SOURCE > Task :processTestResources NO-SOURCE > Task :testClasses UP-TO-DATE > Task :test
Wir haben also gerade ein Gradle-Projekt erstellt, das unsere Komponententests kompilieren und ausführen kann. Unser Build bietet jedoch keine Unterstützung für Integrationstests. Als Nächstes werden wir herausfinden, wie wir sowohl Unit- als auch Integrationstests unterstützen können.
Einheiten- und Integrationstests mit Gradle ausführen
Da wir mit Gradle sowohl Unit- als auch Integrationstests durchführen wollen, müssen wir einige Änderungen an unserem Gradle-Build vornehmen. Wir können diese Änderungen vornehmen, indem wir diesen Schritten folgen:
Zuerst , da wir unserem Gradle-Build neue Test- und Ressourcenverzeichnisse hinzufügen möchten, müssen wir das Gradle TestSets-Plugin anwenden. Nachdem wir dieses Plugin angewendet haben, wird unser build.gradle Datei sieht wie folgt aus:
plugins { id 'org.jetbrains.kotlin.jvm' version '1.3.31' id 'org.unbroken-dome.test-sets' version '2.1.1' } repositories { mavenCentral() } dependencies { implementation('org.jetbrains.kotlin:kotlin-stdlib:1.3.31') testImplementation( 'org.assertj:assertj-core:3.12.2', 'org.junit.jupiter:junit-jupiter-api:5.4.2' ) testRuntime('org.junit.jupiter:junit-jupiter-engine:5.4.2') }
Zweiter müssen wir die Quell- und Ressourcenverzeichnisse unserer Integrationstests konfigurieren. Wir können diese Verzeichnisse konfigurieren, indem wir diesen Schritten folgen:
- Fügen Sie eine neue Testreihe namens
integrationTest
hinzu zu unserem Gradle-Build. - Ändern Sie den Namen des Stammverzeichnisses der Testreihe von
integrationTest
bisintegration-test
.
Nachdem wir diese Verzeichnisse konfiguriert haben, wird unsere build.gradle Datei sieht wie folgt aus:
plugins { id 'org.jetbrains.kotlin.jvm' version '1.3.31' id 'org.unbroken-dome.test-sets' version '2.1.1' } repositories { mavenCentral() } dependencies { implementation('org.jetbrains.kotlin:kotlin-stdlib:1.3.31') testImplementation( 'org.assertj:assertj-core:3.12.2', 'org.junit.jupiter:junit-jupiter-api:5.4.2' ) testRuntime('org.junit.jupiter:junit-jupiter-engine:5.4.2') } testSets { integrationTest { dirName = 'integration-test' } } test { useJUnitPlatform() }
Diese Konfiguration fügt einen Quellsatz namens integrationTest
hinzu zu unserem Gradle-Build. Das bedeutet:
- Der src/integration-test/kotlin Verzeichnis enthält den Quellcode unserer Integrationstests.
- Die src/integration-test/resources Verzeichnis enthält die Ressourcen unserer Integrationstests.
Außerdem erstellt diese Konfiguration Abhängigkeitskonfigurationen, die es uns ermöglichen, die Abhängigkeiten unserer Integrationstests zu deklarieren. Diese Abhängigkeitskonfigurationen sind:
- Der
integrationTestImplementation
Die Abhängigkeitskonfiguration enthält die Abhängigkeiten, die zum Kompilieren unserer Integrationstests erforderlich sind. Diese Konfiguration erweitert dentestImplementation
Abhängigkeitskonfiguration. - Die
integrationTestRuntimeOnly
Abhängigkeitskonfiguration enthält nur die Abhängigkeiten, die erforderlich sind, wenn wir unsere Integrationstests ausführen. Diese Konfiguration erweitert dentestRuntimeOnly
Abhängigkeitskonfiguration.
Dritter , müssen wir sicherstellen, dass Unit-Tests vor Integrationstests ausgeführt werden. Nachdem wir die erforderliche Konfiguration zu unserer build.gradle hinzugefügt haben Datei sieht sie wie folgt aus:
plugins { id 'org.jetbrains.kotlin.jvm' version '1.3.31' id 'org.unbroken-dome.test-sets' version '2.1.1' } repositories { mavenCentral() } dependencies { implementation('org.jetbrains.kotlin:kotlin-stdlib:1.3.31') testImplementation( 'org.assertj:assertj-core:3.12.2', 'org.junit.jupiter:junit-jupiter-api:5.4.2' ) testRuntime('org.junit.jupiter:junit-jupiter-engine:5.4.2') } testSets { integrationTest { dirName = 'integration-test' } } integrationTest.mustRunAfter test test { useJUnitPlatform() }
Vierter müssen wir sicherstellen, dass Integrationstests ausgeführt werden, wenn wir build
aufrufen Aufgabe. Außerdem müssen wir sicherstellen, dass unser Build fehlschlägt, wenn ein Integrationstest fehlschlägt. Nachdem wir die erforderliche Konfiguration zu unserer build.gradle hinzugefügt haben Datei sieht sie wie folgt aus:
plugins { id 'org.jetbrains.kotlin.jvm' version '1.3.31' id 'org.unbroken-dome.test-sets' version '2.1.1' } repositories { mavenCentral() } dependencies { implementation('org.jetbrains.kotlin:kotlin-stdlib:1.3.31') testImplementation( 'org.assertj:assertj-core:3.12.2', 'org.junit.jupiter:junit-jupiter-api:5.4.2' ) testRuntime('org.junit.jupiter:junit-jupiter-engine:5.4.2') } testSets { integrationTest { dirName = 'integration-test' } } check.dependsOn integrationTest integrationTest.mustRunAfter test test { useJUnitPlatform() }
Fünfter , müssen wir sicherstellen, dass Gradle unsere Integrationstests mit JUnit 5 ausführt. Nachdem wir die integrationTest
konfiguriert haben Aufgabe, unser build.gradle Datei sieht wie folgt aus:
plugins { id 'org.jetbrains.kotlin.jvm' version '1.3.31' id 'org.unbroken-dome.test-sets' version '2.1.1' } repositories { mavenCentral() } dependencies { implementation('org.jetbrains.kotlin:kotlin-stdlib:1.3.31') testImplementation( 'org.assertj:assertj-core:3.12.2', 'org.junit.jupiter:junit-jupiter-api:5.4.2' ) testRuntime('org.junit.jupiter:junit-jupiter-engine:5.4.2') } testSets { integrationTest { dirName = 'integration-test' } } check.dependsOn integrationTest integrationTest.mustRunAfter test integrationTest { useJUnitPlatform() } test { useJUnitPlatform() }
Sechster , müssen wir die aufgerufenen Tests mithilfe von JUnit 5-Tags filtern. Wir können dies tun, indem wir diesen Schritten folgen:
- Stellen Sie sicher, dass JUnit 5 nur die Tests mit dem Tag:
unitTest
ausführt wenn wir unsere Einheitentests ausführen. - Stellen Sie sicher, dass JUnit 5 nur die Tests mit dem Tag:
integrationTest
ausführt wenn wir unsere Integrationstests durchführen.
Nachdem wir die aufgerufenen Tests konfiguriert haben, wird unsere build.gradle Datei sieht wie folgt aus:
plugins { id 'org.jetbrains.kotlin.jvm' version '1.3.31' id 'org.unbroken-dome.test-sets' version '2.1.1' } repositories { mavenCentral() } dependencies { implementation('org.jetbrains.kotlin:kotlin-stdlib:1.3.31') testImplementation( 'org.assertj:assertj-core:3.12.2', 'org.junit.jupiter:junit-jupiter-api:5.4.2' ) testRuntime('org.junit.jupiter:junit-jupiter-engine:5.4.2') } testSets { integrationTest { dirName = 'integration-test' } } check.dependsOn integrationTest integrationTest.mustRunAfter test integrationTest { useJUnitPlatform { includeTags 'integrationTest' } } test { useJUnitPlatform { includeTags 'unitTest' } }
Wir haben jetzt einen Gradle-Build erstellt, der unsere Unit- und Integrationstests kompilieren und ausführen kann. Lassen Sie uns weitermachen und herausfinden, wie wir Einheiten- und Integrationstests schreiben können, die von Gradle und JUnit 5 ausgeführt werden.
Einheiten- und Integrationstests schreiben
Wir können unsere Einheiten- und Integrationstests schreiben, indem wir diesen Schritten folgen:
Zuerst , da wir unsere Unit-Test-Klasse bereits geschrieben haben, müssen wir nur noch das Tag hinzufügen:unitTest
zu unserer Unit-Test-Klasse.
Nachdem wir dieses Tag zu unserer Unit-Test-Klasse hinzugefügt haben, sieht sein Quellcode wie folgt aus:
import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test @Tag("unitTest") class MessageServiceTest { private lateinit var service: MessageService @BeforeEach fun configureSystemUnderTest() { service = MessageService() } @Test @DisplayName("Should return the correct message") fun shouldReturnCorrectMessage() { val message = service.getMessage() assertThat(message).isEqualTo("Hello World!") } }
Zweiter , müssen wir eine Integrationstestklasse schreiben, die sicherstellt, dass das zu testende System die richtige Nachricht zurückgibt. Außerdem müssen wir das Tag hinzufügen:integrationTest
zu unserem Integrationstestkurs.
Nachdem wir unsere Integrationstestklasse geschrieben haben, sieht ihr Quellcode wie folgt aus:
import org.assertj.core.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Tag import org.junit.jupiter.api.Test @Tag("integrationTest") class GetMessageTest { private lateinit var service: MessageService @BeforeEach fun configureSystemUnderTest() { service = MessageService() } @Test @DisplayName("Should return the correct message") fun shouldReturnCorrectMessage() { val message = service.getMessage() Assertions.assertThat(message).isEqualTo("Hello World!") } }
Wir haben jetzt unsere Unit- und Integrationstests geschrieben. Als nächstes werden wir herausfinden, wie wir unsere Tests durchführen können.
Durchführung unserer Tests
Wenn wir nur Komponententests ausführen möchten, müssen wir den Befehl ausführen:gradle clean test . Wenn wir diesen Befehl an der Eingabeaufforderung ausführen, sehen wir, dass Gradle nur unsere Komponententests ausführt:
> Task :clean > Task :compileKotlin > Task :compileJava NO-SOURCE > Task :processResources NO-SOURCE > Task :classes UP-TO-DATE > Task :compileTestKotlin > Task :compileTestJava NO-SOURCE > Task :processTestResources NO-SOURCE > Task :testClasses UP-TO-DATE > Task :test
Wenn wir nur Integrationstests ausführen möchten, müssen wir den Befehl ausführen:gradle clean integrationTest . Wenn wir diesen Befehl an der Eingabeaufforderung ausführen, sehen wir, dass Gradle nur unsere Integrationstests ausführt:
> Task :clean > Task :compileKotlin > Task :compileJava NO-SOURCE > Task :processResources NO-SOURCE > Task :classes UP-TO-DATE > Task :compileIntegrationTestKotlin > Task :compileIntegrationTestJava NO-SOURCE > Task :processIntegrationTestResources NO-SOURCE > Task :integrationTestClasses UP-TO-DATE > Task :integrationTest
Wenn wir sowohl Unit- als auch Integrationstests ausführen möchten, müssen wir einen dieser beiden Befehle ausführen:gradle clean test integrationTest oder gradle clean build . Wenn wir build
ausführen Aufgabe sehen wir, dass Gradle sowohl Komponenten- als auch Integrationstests ausführt:
> Task :clean > Task :compileKotlin > Task :compileJava NO-SOURCE > Task :processResources NO-SOURCE > Task :classes UP-TO-DATE > Task :inspectClassesForKotlinIC > Task :jar > Task :assemble > Task :compileTestKotlin > Task :compileTestJava NO-SOURCE > Task :processTestResources NO-SOURCE > Task :testClasses UP-TO-DATE > Task :test > Task :compileIntegrationTestKotlin > Task :compileIntegrationTestJava NO-SOURCE > Task :processIntegrationTestResources NO-SOURCE > Task :integrationTestClasses UP-TO-DATE > Task :integrationTest > Task :check > Task :build
Wir können jetzt einen Gradle-Build erstellen, der Einheiten- und Integrationstests ausführen kann, die Kotlin und JUnit 5 verwenden. Fassen wir zusammen, was wir aus diesem Blogbeitrag gelernt haben.
Zusammenfassung
Dieser Blogpost hat uns sechs Dinge beigebracht:
- Da wir JVM verwenden, müssen wir das Kotlin JVM Gradle-Plugin anwenden.
- Wir müssen die Kotlin-Standardbibliothek (
kotlin-stdlib
) Abhängigkeit vonimplementation
Abhängigkeitskonfiguration. - Wir können unserem Gradle-Build neue Test- und Ressourcenverzeichnisse hinzufügen, indem wir das Gradle TestSets-Plugin verwenden.
- Das Gradle TestSets-Plugin erstellt Abhängigkeitskonfigurationen, mit denen wir die Abhängigkeiten unserer Integrationstests konfigurieren können.
- Wenn wir Tests ausführen wollen, die JUnit 5 verwenden, müssen wir die eingebaute JUnit 5-Unterstützung von Gradle aktivieren.
- Wir können die aufgerufenen Tests filtern, indem wir JUnit 5-Tags verwenden.
Quellcode von Github abrufen .