[JAVA] Probieren Sie HiveRunner aus

Motivation

Ich möchte Hive-Abfragen testen.

Mit MySQL können Sie Docker-Compose relativ einfach testen, aber ich möchte Hive-Abfragen auf die gleiche Weise testen, aber was soll ich tun? (Es scheint ein wenig schmerzhaft, mit Docker verrückt zu werden ..)

Deshalb habe ich ein Plug-In ausgewählt, das gut aussieht, und es ausprobiert.

Ich habe den Git-Star unter den [einigen offiziell eingeführten Tools] ausgewählt (https://cwiki.apache.org/confluence/display/Hive/Unit+Testing+Hive+SQL). Es gab viele HiveRunner. (Version ist 4.1.0)

Vorbereitung

HiveRunner testet die Abfrage grundsätzlich als Test von Junit.

Es benötigt keine externen Abhängigkeiten, es sieht aus wie ein Bild von "HiveServer" auf "JVM" und "Junit", das "Hive SQL" auf diesem "HiveServer" ausführt.

Dieses Mal werden wir ein Projekt mit maven erstellen. Das Folgende ist der "Pom", wenn diese Zeit ausgeführt wird. Es gibt keinen besonderen Grund, aber ich habe den BEELINE-Emulator angegeben.

<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.21.0</version>
            <configuration>
                <forkMode>always</forkMode>
                <systemProperties>
                    <!-- Defaults to HIVE_CLI, other options include BEELINE and HIVE_CLI_PRE_V200 -->
                    <commandShellEmulator>BEELINE</commandShellEmulator>
                </systemProperties>
            </configuration>
        </plugin>
    </plugins>
</build>

<dependencies>
    <dependency>
        <groupId>com.klarna</groupId>
        <artifactId>hiverunner</artifactId>
        <version>4.1.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Ich werde es vorerst versuchen


@RunWith(StandaloneHiveRunner.class)
public class TestHiveRunner {
    @HiveSQL(files = {})
    private HiveShell shell;

    /*
     *Erstellen Sie eine Datenbank und eine Tabelle
     */
    @Before
    public void setupSourceDatabase() {
        shell.execute(
                "CREATE DATABASE source_db; " +
                "CREATE TABLE source_db.test_table (year STRING, value INT);");

        shell.execute(
                "CREATE DATABASE my_schema; " +
                "CREATE EXTERNAL TABLE my_schema.result " +
                "(year STRING, value INT) " +
                "STORED AS PARQUET " +
                "TBLPROPERTIES (\"parquet.compress\"=\"snappy\")");
    }

    @Test
    public void testMaxValueByYear() {
        /*
         *Speichern Sie die Testdaten in der zu aggregierenden Tabelle
         */
        shell.insertInto("source_db", "test_table")
                .withColumns("year", "value")
                .addRow("2014", 3)
                .addRow("2014", 4)
                .addRow("2015", 2)
                .addRow("2015", 5)
                .commit();

        /*
         *Führen Sie eine aggregierte Abfrage aus(INSERT-Abfrage)
         */
        shell.executeStatement("INSERT INTO my_schema.result " +
                "SELECT " +
                "   year, " +
                "   MAX(value) " +
                "FROM " +
                "   source_db.test_table " +
                "GROUP BY year");

        /*
         *Rufen Sie das Ergebnis aus der Tabelle ab, in der das aggregierte Ergebnis INSERTed ist
         */
        List<Object[]> result = shell.executeStatement("SELECT * FROM my_schema.result");

        assertEquals(2, result.size());
        assertArrayEquals(new Object[]{"2014",4}, result.get(0));
        assertArrayEquals(new Object[]{"2015",5}, result.get(1));
    }
}

Dies ist eine leicht umgeschriebene Version des Codes in den meisten der oben genannten Beispiele.

Es sieht so aus, als wäre es sehr einfach zu testen.

Es ist auch möglich, die extrahierte Abfrage zu lesen oder wenn die Anzahl der Testdateneinfügungen zunimmt und die Testdaten separat auf "tsv" usw. ausgeschnitten werden.

Werfen wir einen Blick auf jeden

@HiveSQL


//Standardmäßig Src/test/Sie verweisen auf das Ressourcenverzeichnis.
@HiveSQL(files = {"create_test_table.sql", "create_max.sql"})
private HiveShell shell;

Durch Angabe einer SQL-Datei in files = {} wird diese automatisch ausgeführt, nachdem die Instanz erstellt wurde.

Durch Setzen von "@HiveSQL (files = {...}, autoStart = false)" kann es nach ** beliebiger Einrichtung ** gestartet werden. (Rufen Sie die Methode start () auf.)

Übrigens, die Elemente, die in ** Arbitrary Setup ** eingestellt werden können, sind wie folgt. (Es gibt viele überladene Methoden.)


//Stellen Sie HiveConf ein
void setProperty(String key, String value);
void setHiveConfValue(String key, String value);

//Kopieren Sie die Testdaten nach HDFS
void addResource(String targetFile, File sourceFile);

//Registrierung des Skripts, das ausgeführt werden soll, wenn HiveShell gestartet wird
// @Das Gleiche gilt für HiveSetupScript, aber das Folgende ist eine garantierte Reihenfolge der Skriptausführung.
void addSetupScript(String script);
void addSetupScripts(Charset charset, File... scripts);

//Es scheint, dass es den Stream öffnen und die Testdaten in HDFS schreiben wird
OutputStream getResourceOutputStream(String targetFile);

execute

//Direktes Schreiben
shell.execute("CREATE DATABASE source_db; " +
        "CREATE TABLE source_db.test_table (year STRING, value INT);");


//Es ist auch möglich, das ausgeschnittene SQL zu lesen
shell.execute(Paths.get("src/test/resources/calculate_max.sql"));

Führen Sie ein Skript (eine Abfrage) ohne Rückgabewert aus.

Mehrere Abfragen können ausgeführt werden, indem sie durch ; getrennt werden.

Bedeutet das, dass es keinen Rückgabewert gibt, da Sie mehrere Abfragen ausführen können?

executeQuery & executeStatement


//Sie können es auch mit executeQuery ausführen.
shell.executeStatement("INSERT INTO my_schema.result " +
        "SELECT " +
        "   year, " +
        "   MAX(value) " +
        "FROM " +
        "   source_db.test_table " +
        "GROUP BY year");

//Nur executeQuery kann das ausgeschnittene SQL lesen
shell.execute(Paths.get("src/test/resources/calculate_max.sql"));

Im Gegensatz zu "Ausführen" können nicht mehrere Abfragen gleichzeitig ausgeführt werden, und es tritt ein Fehler auf, wenn ";" am Ende des Satzes enthalten ist.

Stattdessen gibt List <String> die Ergebnisse der Abfrage zurück.

insertInto


shell.insertInto("source_db", "test_table")
        .withColumns("year", "value")
        .addRow("2014", 3)
        .addRow("2014", 4)
        .addRow("2015", 2)
        .addRow("2015", 5)
        .commit();

//Sie können auch Daten von tsv usw. einfügen.
shell.insertInto("source_db", "test_table")
        .withColumns("year", "value")
        .addRowsFromTsv(new File("src/test/resources/insert_data_of_test_table.tsv"))
        .commit();

Diese Methode wird nicht ohne "commit ()" ausgeführt.

Das Vorbereiten der Testdaten ist mühsam, aber es ist sehr praktisch, sie mit "tsv" einzufügen.

Zusammenfassung

Es scheint nützlich zu sein (obwohl es sich etwas schwer anfühlt), wenn Sie eine Abfrage testen oder eine kleine Abfrage versuchen möchten.

In einer Tabelle mit einer großen Anzahl von Spalten, einem Test bei großer Testdatenmenge, einem Test einer sehr komplizierten Abfrage usw. scheint dies in Bezug auf Speicher und Ausführungsgeschwindigkeit schwierig zu sein, aber was passiert (README)? Es gibt Anweisungen zum Umgang damit ..

Es ist jedoch attraktiv, "sql" von "hive" testen zu können, indem man "hiverunner" einfach in "pom" setzt.

Recommended Posts

Probieren Sie HiveRunner aus
Versuchen Sie es mit Mockito
Versuchen Sie es mit Selen
Versuchen Sie es mit DbUnit
Versuchen Sie es mit Lombok
Versuchen Sie es mit libGDX
Versuchen Sie zuerst ~ catch
Versuchen Sie es mit Maven
Versuchen Sie es mit powermock-mockito2-2.0.2
Versuchen Sie es mit GraalVM
Probieren Sie Java 8 Stream aus
Versuchen Sie es mit jmockit 1.48
Versuchen Sie es mit SwiftLint
Versuchen Sie es mit Log4j 2.0
Versuchen Sie Ruby Minitest
Versuchen Sie es mit Java 9