Optimieren Sie Java-Tests mit Spock

Einführung

Der Beispielcode in diesem Text wurde in der folgenden Umgebung validiert:


Was ist Spock?

Spock ist ein Test- und Spezifikationsframework für Java- und Groovy-Anwendungen. Im Vergleich zu anderen Tools bietet es eine schöne und ausdrucksstarke Spezifikationsbeschreibungssprache. https://spock-framework-reference-documentation-ja.readthedocs.io/ja/latest/introduction.html


Was unterscheidet sich von JUnit?

Der Umfang der Testcodierung ist überwiegend geringer als bei JUnit! Mit anderen Worten, der Codierungsaufwand wird reduziert, sodass Sie die Effizienz von Unit-Tests einfach steigern können.

Wie können Sie den Umfang der Testcodierung reduzieren?


Tests können mit groovy codiert werden

Spock schreibt Tests in Groovy. Die groovigen Sprachmerkmale ermöglichen eine leichtere Codierung als Java. Wenn der Build gradle ist, werden beide groovig sein, also denke ich, dass es schnell zu lernen sein wird.

Groovy ist eine dynamische Programmiersprache, die auf der Java-Plattform ausgeführt wird. https://ja.wikipedia.org/wiki/Groovy

Für diejenigen, die Groovy noch nie benutzt haben, können die Lernkosten eine Belastung sein. Da groovy Java-Code jedoch fast so schreiben kann, wie er ist, können Sie ihn in Java schreiben, wenn Sie den schlechtesten groovy-Code nicht kennen.

Wie unterschiedlich ist der gleiche Test in JUnit und Spock (groovig) codiert? Auf Spocks Github wurde Beispielcode veröffentlicht. Hier ist ein Beispiel für die Codierung desselben Tests in JUnit.

JUnit


import static org.junit.Assert.assertEquals;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.h2.Driver;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class DatabaseDrivenTest {

	private static Connection con;

	@BeforeClass
	public static void setup() throws Exception {
		Driver.load();
		con = DriverManager.getConnection("jdbc:h2:mem:");

		Statement stmt = con.createStatement();
		stmt.execute("create table maxdata (id int primary key, a int, b int, c int)");
		stmt.execute("insert into maxdata values (1, 3, 7, 7), (2, 5, 4, 5), (3, 9, 9, 9)");
		stmt.close();
	}

	@Test
	public void testMaximumOfTwoNumbers() throws Exception {
		// Math.max(a, b) == c;
		Statement stmt = con.createStatement();
		ResultSet rs = stmt.executeQuery("select a, b, c from maxdata");
		rs.next();
		rs.getInt("a");
		assertEquals(Math.max(rs.getInt("a"), rs.getInt("b")), rs.getInt("c"));

		stmt.close();
	}

	@AfterClass
	public static void after() throws SQLException {
		con.close();
	}
}

Hier ist der Spock-Code. https://github.com/spockframework/spock-example/blob/master/src/test/groovy/DatabaseDrivenSpec.groovy

Sie werden feststellen, dass Groovy überwiegend einfach ist.


Optimieren Sie Kombinationstests mit datengesteuerten Tests

Ein weiterer leistungsfähiger Mechanismus ist der Datenstarttest. Das iterative Testen von Parameter- und Ergebniskombinationen kann leicht erreicht werden.

import spock.lang.*

@Unroll
class DataDrivenSpec extends Specification {
  def "minimum of #a and #b is #c"() {
    expect:
    Math.min(a, b) == c //Testausführung und Ergebnisüberprüfung

    where:
    a | b || c    //Parameter 1|Parameter 2||Ergebnis
    3 | 7 || 3
    5 | 4 || 4
    9 | 9 || 9
  }
}

Dieser Code ist ein Test mit folgendem Inhalt: Das Ergebnis der Ausführung von Math.min (a, b) mit a = 3 und b = 7 ist 3 Das Ergebnis der Ausführung von Math.min (a, b) mit a = 5 und b = 3 ist 4 Das Ergebnis der Ausführung von Math.min (a, b) mit a = 9 und b = 9 ist 9

Wenn Sie mehr Variationen bei Parametern und Ergebnissen wünschen, können Sie sich vorstellen, wo ein Muster hinzuzufügen. Es ist ein Formular, das einfach aus der Mustertabelle des in Excel erstellten Kombinationstests konvertiert werden kann.


Fehlermeldung

Wenn der Test fehlschlägt, wird ein Fehlerbericht auf der Konsole gedruckt. Es ist freundlicher als Javas Fehlerstapel-Trace.

Condition not satisfied:

validator.validate() == true
|         |          |
|         false      false
<Validator@5aa9e4eb>

	at ValidatorSpec.validate test(ValidatorSpec.groovy:40)


Leicht zu verspotten

Spock hat auch eine Spottfunktion.

Verspotten Sie HttpServletRequest und schreiben Sie den Rückgabewert von getRequestURI in "/some/path.html".

def request = Mock(HttpServletRequest)
request.getRequestURI() >> "/some/path.html"

Es gibt jedoch verschiedene Einschränkungen beim Verspotten, so dass dieser Punkt später beschrieben wird.


Einführungsmethode

Es kann mit Gradle oder Maven installiert werden. Bitte beachten Sie, dass es eine Versionsabhängigkeit mit groovy gibt.

gradle


testCompile group: 'org.spockframework', name: 'spock-core', version: '1.3-groovy-2.5'
testCompile group: 'org.objenesis', name: 'objenesis', version: '3.0.1'
testCompile group: 'cglib', name: 'cglib', version: '3.2.10'

Maven


<dependency>
    <groupId>org.spockframework</groupId>
    <artifactId>spock-core</artifactId>
    <version>1.3-groovy-2.5</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.objenesis</groupId>
    <artifactId>objenesis</artifactId>
    <version>3.0.1</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.10</version>
</dependency>


Gradle-Setup-Beispiel

build.gradle


apply plugin: 'java'
apply plugin: 'groovy'

sourceSets {
	test {
		java {
			srcDir 'src/test/groovy'
		}
	}
}

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'org.spockframework', name: 'spock-core', version: '1.3-groovy-2.5'
    testCompile group: 'org.objenesis', name: 'objenesis', version: '3.0.1'
    testCompile group: 'cglib', name: 'cglib', version: '3.2.10'
}

Bitte beachten Sie, dass das Quellverzeichnis auf 'rc / test / groovy' gesetzt sein muss.


Eclipse Plugins Um es mit Eclipse zu verwenden, müssen Sie das folgende Plug-In installieren. Bitte installieren Sie vom Marktplatz.

Spock Plugin http://marketplace.eclipse.org/content/spock-plugin

Groovy Development Tools http://marketplace.eclipse.org/content/groovy-development-tools


Spock Grundlagen

Die Grundform des Tests sieht so aus.

class ValidatorSpec extends Specification {
    @Unroll
    def "Beispieltestparameter1=#param1 param2=#param2" () {
       setup: // 1.Vorverarbeitung
            def target =neue getestete Klasse()
            def mockTarget = Mock(Klasse, die du verspotten willst)
            mockTarget.method() >>Wert, den Sie neu schreiben möchten
            target.mockTarget = mockTarget //Weisen Sie einer Mitgliedsvariablen der zu testenden Klasse einen Mock zu
        expect: // 2.Ausführung des Testziels
            def returnObj = target.targetMethod(param1, param2)
        then: // 3.Überprüfung der Ergebnisse
            returnObj == result
            1 * mockTarget.method()
        where: // 4
.Kombination von Parametern und Ergebnissen
            | param1 | param2 || result
            | "a"    | 1      || "ok"
            | "b"    | 20     || "ng"
    }
}
  1. In der Vorverarbeitung wird die Testzielklasse generiert und der Mock generiert.
  2. Führen Sie hier die Testzielmethode der Testzielklasse aus.
  3. Überprüfen Sie das Ausführungsergebnis der Testbehandlungsmethode. Validierung Die Validierung wird auf dem Booleschen Wert ausgewertet.
  4. Definieren Sie eine Kombination von Parametern und Ergebnissen mit einem Rohrspleiß. Der Punkt ist, dass param1, param2 und result keine Variablendeklarationen haben.

Blocktyp

Es gibt folgende Arten von Blöcken:

Block Erläuterung
expect Testausführung und Ergebnisüberprüfung(when + then)
where Parameter und Ergebnisse
when Führen Sie das Testziel aus
then Überprüfung der Ergebnisse
setup(given) Vorverarbeitung
cleanup Nachbearbeitung

Unterstützt Legacy-Code-Tests in Kombination mit JMockit

Es gibt Tests, die Spock allein nicht durchführen kann, z. B. statische, endgültige und private Konstruktoren, die in Legacy-Code verwendet werden. Wenn Sie diese Tests benötigen, empfehlen wir die Verwendung von JMockit.

 setup:
    new MockUp<LegacyUtil>() {
        @Mock
        public boolean check() {
            return true
        }
    }

Fälle, in denen die Wirkung von Spock nicht zu erwarten ist

Eine 100% ige Testabdeckung ist erforderlich

Das Streben nach 100% Testabdeckung ist sehr schwierig, und das Erreichen von 100% bedeutet keine hohe Qualität. Es gibt jedoch tatsächlich Entwicklungsprojekte, die als einer der Qualitätsindexwerte erforderlich sind. Es ist schwierig, nur mit Spock zu erreichen. Nutzen Sie jMockit daher vollständig oder verwenden Sie JUnit zusammen.

Klassen, die selbst mit JUnit schwer zu testen sind

Das Prinzip besteht darin, eine Klasse zu entwerfen, die leicht zu testen ist, aber ich denke, dass es viele Möglichkeiten gibt, auf Spaghetti-Code am eigentlichen Entwicklungsstandort zu stoßen. Bitte umgestalten, um den Test zu vereinfachen.

Referenzseite

Spock http://spockframework.org

Spock Framework-Referenzdokument https://spock-framework-reference-documentation-ja.readthedocs.io/ja/latest/

Spock-Beispielcode https://github.com/spockframework/spock-example

Recommended Posts

Optimieren Sie Java-Tests mit Spock
Testen mit com.google.testing.compile
Installieren Sie Java mit Homebrew
Wechseln Sie die Plätze mit Java
Installieren Sie Java mit Ansible
Bequemer Download mit JAVA
Schalten Sie Java mit direnv
Java-Download mit Ansible
Lass uns mit Java kratzen! !!
Erstellen Sie Java mit Wercker
Endian-Konvertierung mit JAVA
(Java) Einfache BDD mit Spektrum?
Verwenden Sie Lambda-Ebenen mit Java
Erstellen Sie mit Gradle ein Java-Multiprojekt
Erste Schritte mit Java Collection
Java-Konfiguration mit Spring MVC
Grundlegende Authentifizierung mit Java 11 HttpClient
Experimentieren wir mit der Java-Inline-Erweiterung
Führen Sie Batch mit Docker-Compose mit Java-Batch aus
[Vorlage] MySQL-Verbindung mit Java
Schreiben Sie Java Try-Catch mit Optional neu
Installieren Sie Java 7 mit Homebrew (Fass)
[Java] JSON-Kommunikation mit Jackson
Java zum Spielen mit Function
Aktivieren Sie Java EE mit NetBeans 9
[Java] JavaConfig mit statischer innerer Klasse
Lassen Sie uns Excel mit Java betreiben! !!
Java-Versionsverwaltung mit SDKMAN
RSA-Verschlüsselung / Entschlüsselung mit Java 8
Paging PDF mit Java + PDFBox.jar
[Java] Inhaltserfassung mit HttpCliient
Java-Versionsverwaltung mit jenv
Fehlerbehebung mit Java Flight Recorder
Stellen Sie mit Java eine Verbindung zur Datenbank her
Stellen Sie mit Java eine Verbindung zu MySQL 8 her
Fehler beim Spielen mit Java
Verwenden von Mapper mit Java (Spring)
Java Study Memo 2 mit Progate
REST-API-Test mit REST Assured
Erste Schritte mit Java Basics
Wenn Sie Java-Bibliothekstests mit Spock in mehreren Modulen mit Gradle in Android Studio 3 implementieren möchten
Saisonale Anzeige mit Java-Schalter
Verwenden Sie SpatiaLite mit Java / JDBC
Lernen von Java mit Progate Note 1
Vergleichen Sie Java 8 Optional mit Swift
HTML-Analyse (Scraping) mit JAVA
Führen Sie Java VM mit Web Assembly aus
Bildschirmübergang mit Swing, Java
Java Unit Test mit Mockito
Eine Geschichte über die Schwierigkeit, ein Testframework an Java 6 auszurichten
[Java 8] Doppelte Löschung (& doppelte Überprüfung) mit Stream
Java-Lambda-Ausdruck, der mit Comparator gelernt wurde
Erstellen eines Java-Projekts mit Gradle
Installieren Sie Java mit Ubuntu 16.04 Docker
Java mit Ramen lernen [Teil 1]
Morphologische Analyse in Java mit Kuromoji
Verwenden Sie Java mit MSYS und Cygwin
Verteilte Ablaufverfolgung mit OpenCensus und Java
100% reines Java BDD mit JGiven (Einführung)
Automatischer API-Test mit Selen + REST-Assured