HiveQLUnitを使ってhiveの単体テストを実施する手順
hiveのクエリーの単体テストのやり方を調べてみると、
単体検査用のhive実行環境の立ち上げを含めてまるっとやってくれる、
HiveQLUnitというフレームワークがあったので、試してみました。
このエントリでは、
HiveQLUnitを使って単体テストを実施する手順を説明します。
HiveQLUnit
http://finraos.github.io/HiveQLUnit/
全体の流れは、以下の通りです。
- テスト用プロジェクト作成
- テストコードとテストデータの準備
- テストの実行 (コマンドラインから)
- テストの実行 (IntelliJから)
jdkとmaven3はセットアップ済みの前提です。
私が使ったバージョンは以下の通り。
- JDK 1.8.0_71
- Apache Maven 3.3.9
このエントリで作成したgithubリポジトリ:
https://github.com/takemikami/hiveqlunit-sample
# このリポジトリをcloneして、
# mvn test
ってすればとりあえずテストは動くはず。
テスト用プロジェクト作成
まずは、テスト用プロジェクトのディレクトリ作成とpom.xmlを準備します。
以下のように、プロジェクトとテストコード用のディレクトリを作成します。
$ mkdir hiveqlunit-sample && cd $_
$ mkdir -p src/test/{java,resources}
以下のとおり、pomファイルを作成します。
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.takemikami</groupId>
<artifactId>hiveqlunit-sample</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>hiveqlunit sample</name>
<url>https://github.com/takemikami/hiveqlunit-sample</url>
<dependencies>
<dependency>
<groupId>org.finra.hiveqlunit</groupId>
<artifactId>hiveQLUnit</artifactId>
<version>1.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<argLine>-XX:MaxPermSize=128m -Dhive.metastore.warehouse.dir=${project.basedir}/target/hive-warehouse</argLine>
</configuration>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<filesets>
<fileset>
<directory>metastore_db</directory>
</fileset>
</filesets>
</configuration>
</plugin>
</plugins>
</build>
</project>
テストコードとテストデータの準備
以下の通り、テスト対象のHQLコードを用意します。
src/main/resources/sample.hql
create table sales_by_shop
as select shop, sum(amount) amount
from sales
group by shop
以下の通り、テストコードを用意します。
このコードでは以下の処理を実施します。
- 入力テーブルに、テスト用データを読み込む
- HQLを読み込んで実行する
- 出力テーブルの内容に対するテストを実行する
src/test/java/SampleTest.java
import static org.junit.Assert.assertEquals;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.hive.HiveContext;
import org.finra.hiveqlunit.resources.LocalFileResource;
import org.finra.hiveqlunit.resources.TextLiteralResource;
import org.finra.hiveqlunit.rules.SetUpHql;
import org.finra.hiveqlunit.rules.TestDataLoader;
import org.finra.hiveqlunit.rules.TestHiveServer;
import org.finra.hiveqlunit.script.MultiExpressionScript;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import java.io.*;
public class SampleTest {
@ClassRule
public static TestHiveServer hiveServer = new TestHiveServer();
@Rule
public static TestDataLoader loader = new TestDataLoader(hiveServer);
@Test
public void testA() throws Exception {
HiveContext sqlContext = hiveServer.getHiveContext();
sqlContext.sql("drop table if exists sales");
sqlContext.sql("create table sales(saletime timestamp, shop string, amount int) row format delimited fields terminated by '\t' lines terminated by '\n'");
loader.loadDataIntoTable("sales", new LocalFileResource("src/test/resources/testdata.txt"), "");
sqlContext.sql("drop table if exists sales_by_shop");
sqlContext.sql(readHql("sample.hql"));
Row[] results = sqlContext.sql("SELECT shop,amount FROM sales_by_shop").collect();
assertEquals(3, results.length);
Row[] resultsA = sqlContext.sql("SELECT sum(amount) FROM sales_by_shop").collect();
Row[] resultsB = sqlContext.sql("SELECT sum(amount) FROM sales").collect();
}
public static String readHql(String fname) throws IOException {
StringBuffer buf = new StringBuffer();
BufferedReader br = new BufferedReader(new FileReader(new File("src/main/resources/" + fname)));
String str = br.readLine();
while(str != null) {
buf.append(str).append("\n");
str = br.readLine();
}
br.close();
return buf.toString();
}
}
以下の通り、テストデータを用意します。(タブ区切りです)
src/test/resources/testdata.txt
2012-11-20 10:35:00 東京店 1000
2012-12-05 19:07:00 大阪店 1200
2012-12-07 12:42:00 京都店 2200
2012-12-10 13:05:00 東京店 1800
テストの実行 (コマンドラインから)
以下のように、テストを実行します。
$ mvn clean test
初回は関連するjarをダウンロードするのでかなり時間がかかります。
二回目以降も、HadoopやHiveの初期化で結構時間がかかります。
テストの実行 (IntelliJから)
テストの実行はIntellJからも実行出来るので、
作成したテスト用プロジェクトをIntellJに取り込みます。
プロジェクトの取り込み
IntellJのメニューから、File→Openを選び、
作成したテスト用プロジェクトのフォルダを選択してOKを押下します。
しばらく待つとプロジェクトがIntelliJniインポートされます.
テストの実行
左側プロジェクトのツリーから「src/test/java/SampleTest.java」を選び、
コンテキストメニューから「Run SampleTest」を選択します。
テストが実行されて、以下のように結果が表示されます。