testing

Effizientes Software Testing mit KoTest, JUnit, Karate und Gatling

Qualitätssicherung, also Testing einer Anwendung ist ein entscheidender Bestandteil des  Software Developments. Hier werden wir verschiedene Frameworks für das Software Testing vorstellen und Beispiele für deine Application bieten. Wir werden KoTest und JUnit für das Unit Testing, Karate für API-/E2E-Tests und Gatling für die Load Tests behandeln.

Unit Testing

In unseren Beispielen testen wir eine einfache Addition zweier Integer-Zahlen mit dem Taschenrechner. Beide Beispiel-Frameworks, bieten hier eine klare und ausdrucksstarke Syntax für die Testfallbeschreibung.

KoTest: Unit Testing mit Kotlin

KoTest ist ein modernes Framework, das sich ideal für das Testen von Kotlin-Anwendungen eignet. Es ermöglicht das einfache Schreiben von Unit Tests.
Hier ist ein Beispiel für die Verwendung von KoTest:

				
					import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe

class CalculatorSpec : StringSpec({
    "Adding two numbers should return the correct sum" {
        val result = Calculator.add(2, 3)
        result shouldBe 5
    }
})
				
			

JUnit: Klassisches Unit Testing für Java

JUnit ist ein bewährtes Framework für das Unit Testing von Java-Anwendungen. Es bietet eine breite Unterstützung und wird in vielen Projekten verwendet.
Hier ist ein Beispiel:

				
					import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

class CalculatorTest {

    @Test
    void testAddition() {
        int result = Calculator.add(2, 3);
        assertEquals(5, result);
    }
}
				
			

An diesen illustrativen Taschenrechner-Beispielen zeigt sich die Mächtigkeit der Unit Tests. Wichtig ist hier anzumerken dass es, gerade im Unit und auch später beim E2E-Testing, diverse Tests auszuführen gibt um viele mögliche Edge-cases (also Randbedingungen) zu überprüfen. Bspw.:

  • Keine negativen Zahlen oder Fließkommazahlen werden überprüft.
  • Der Umgang mit Buchstaben oder anderen Sonderzeichen wird auch nicht getestet.
  • Mathematische Gesetze finden ebenfalls keine Berücksichtigung, wie:
    • Klammerregelen
    • Genauigkeit der Exponential-Funktion oder Logarithmen
  • Nicht-funktionale Anforderungen sollten auch auch Gegenstand des Testings sein:
    • Copy & Paste
    • Tausender-/Dezimaltrennzeichens (“.” vs. “,” ; auch “locale” genannt)


Erst wenn alle diese Genannten, und noch viele weitere Tests, zusammen kommen findet sich eine zufriedenstellende Testabdeckung. Des Weiteren, lohnt es sich auch hier schon sich bestimmten Fragestellungen zu widmen um auch ggf. Software Requirements zu challengen oder schärfen, z.B.

  • Wie viele Zeichen/Ziffern soll der Taschenrechner abbilden/darstellen können?
  • Welche für “Rundungsbedingungen” / Präzision dürfen / darf hier gelten?


Solche Fragen müssen auf jeder Ebene des Testings berücksichtigt werden.

End-to-End-Testing mit Karate: API-Tests in natürlicher Sprache

Karate ist ein Framework, das sich auf API-Tests und End-to-End-Tests von Webanwendungen spezialisiert hat. Es ermöglicht das Schreiben von Tests in einer natürlichen Sprachsyntax.
Hier ist ein Beispiel für die Verwendung von Karate:

				
					Feature: Testing a REST API

Scenario: Retrieve a user by ID
  Given url 'https://api.example.com'
  When path '/users/123'
  Then status 200
  And match response == { id: 123, name: 'John Doe' }
				
			

In diesem Beispiel testen wir das Abrufen eines Benutzers von einer REST-API anhand der leicht verständlichen Gehrkin-Syntax.

Gatling: Load Testing für Skalierbarkeit

Gatling ist ein leistungsstarkes Framework für die Durchführung von Load Testing. Es eignet sich hervorragend, um die Skalierbarkeit Ihrer Anwendungen zu überprüfen.
Hier ist ein Beispiel für Gatling-Testcode:

				
					import io.gatling.core.Predef._
import io.gatling.http.Predef._

class LoadTest extends Simulation {

    val httpProtocol = http.baseUrl("https://example.com")

    val scn = scenario("Load Test")
        .exec(http("request_1")
        .get("/api/resource"))

    setUp(scn.inject(atOnceUsers(10))).protocols(httpProtocol)
}
				
			

In diesem Beispiel führen wir einen Gatling-Test aus, um die Anfrageleistung für eine API-Ressource bei 10 gleichzeitigen User-Zugriffen zu überprüfen.

Testautomatisierung und Integration

Die Integration dieser Frameworks in den Entwicklungsprozess ermöglicht eine effiziente Testautomatisierung. So kann man Test-Suiten erstellen, die automatisch ausgeführt werden, wenn Codeänderungen vorgenommen werden, um sicherzustellen, dass die Anwendung weiterhin einwandfrei funktioniert.

				
					// Kotest Test-Suite
class AllTests : StringSpec({
    include(CalculatorSpec)
})

// JUnit Test-Suite
@RunWith(JUnitPlatform.class)
@SelectPackages("com.example")
public class AllTests {}

// Karate Test-Suite
class AllTestsRunner {
    public static void main(String[] args) {
        Results results = Runner.path("classpath:my/api/tests").tags("~@ignore").parallel(5);
        generateReport(results.getReportDir());
}

// Gatling Test-Suite
class LoadTestRunner {
    public static void main(String[] args) {
        GatlingSimulation.runGatling()
    }
}
				
			

Tests sind nur so gut wie Ihre Developer:innen

Die Verwendung von Kotest, JUnit, Karate und Gatling im Software Development ermöglicht es, die Qualität und Leistung einer Anwendungen effektiv zu überwachen und sicherzustellen. Unit-Tests, API/E2E-Tests und Load Tests werden abgedeckt und bieten somit eine hohe Testabdeckung. Die Testautomatisierung mit diesen Frameworks erleichtert die Integration von Tests in Ihren Entwicklungsprozess und trägt zur kontinuierlichen Qualitätssicherung bei.

In diesem Artikel haben wir einen Einblick in die Verwendung von Kotest, JUnit, Karate und Gatling für das Software Testing gegeben und Beispiele für alle vier Frameworks bereitgestellt. Mit diesen leistungsstarken Werkzeugen kann man sicherstellen, dass eine Anwendungen zuverlässig, fehlerfrei und skalierbar ist.

Auf jeden Fall ist es sinnvoll im Vorfeld sich auch Gedanken zu der umliegenden Architektur zum machen, bevor eine Application live gestellt wird.
Zum Thema Software Architecture haben wir uns hier schon gedanken gemacht.

Eine hohe Softwarequalität ist uns bei enableYou wichtig und darum praktizieren wir auch sorgfältige Überprüfung unseres Codes. Nur so können potentielle Fehlerquellen frühzeitig erkannt werden und auch mögliche produktive Ausfälle umgangen werden. Gleichzeitig bedarf es auch bei guten Tests einer hohen qualitativen Güte. Diese schreiben zu können verlangt ein umfassendes und tiefes Verständnis des zu testenden Systems / der zu testenden Application.

Ein hier nicht beleuchteter Aspekt ist die Bewertung der Notwenigkeit eines Tests. Hier kann der Testaufand erheblich reduziert werden, wenn das Vertrauen in eine validierte Umgebung da ist. Bspw.:

  • Muss überprüft werden ob Java oder eine JVM korrekt addieren kann?
  • Muss man ein im Unit Test getestetes Enum auch nochmal im E2E-Test validieren, wenn es einen fachlich oder operativ sehr wichtigen Inhalt kommuniziert?


Am Ende stellt diese Praxis nicht nur den (End-)Kund-/Benutzer:innen zufrieden sondern kann auch wirtschaftlichen Schaden abwenden.

Language Learning Assistant
EverydAI

Language Learning Assistant

Das Erlernen von Fremdsprachen ist heutzutage zugänglicher denn je – ein KI-basierter Sprachlernassistent kann dein Lernerlebnis auf verschiedene Weisen verbessern.

AI Interviewer
EverydAI

AI Interviewer

Dieser Beitrag untersucht nützliche Eingabeaufforderungen, die KI befähigen, alltägliche Aufgaben zu optimieren. Heute: Vorstellungsgespräche

How-to Guide
EverydAI

How-to Guide

Dieser How-To Guide bildet den Hauptleitfaden für die Artikel Reihe “EverydAI – Essential Prompts for Everyday Use” und schafft das nötige Werkzeug.