Java >> Java Tutorial >  >> Java

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:

  1. Fügen Sie die (nicht obligatorische) AssertJ Core-Abhängigkeit zu testImplementation hinzu Abhängigkeitskonfiguration.
  2. Fügen Sie die JUnit Jupiter API-Abhängigkeit zu testImplementation hinzu Abhängigkeitskonfiguration.
  3. 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:

  1. Fügen Sie eine neue Testreihe namens integrationTest hinzu zu unserem Gradle-Build.
  2. Ändern Sie den Namen des Stammverzeichnisses der Testreihe von integrationTest bis integration-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 den testImplementation Abhängigkeitskonfiguration.
  • Die integrationTestRuntimeOnly Abhängigkeitskonfiguration enthält nur die Abhängigkeiten, die erforderlich sind, wenn wir unsere Integrationstests ausführen. Diese Konfiguration erweitert den testRuntimeOnly 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:

  1. Stellen Sie sicher, dass JUnit 5 nur die Tests mit dem Tag:unitTest ausführt wenn wir unsere Einheitentests ausführen.
  2. 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 von implementation 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 .


Java-Tag