Query File Test(qtest)
Query File Test is a JUnit-based integration test suite for Apache Hive. Developers write any SQL; the testing framework runs it and verifies the result and output.
Tutorial: How to run a specific test case
Preparation
You have to compile Hive’s source codes ahead of time.
$ mvn clean install -Dmaven.javadoc.skip=true -DskipTests -Pitests
Run a test case
Let’s try to run alter1.q.
$ mvn test -Pitests -pl itests/qtest -Dtest=TestMiniLlapLocalCliDriver -Dqfile=alter1.q
The test should successfully finish.
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
Tutorial: How to add a new test case
Add a QFile
A QFile includes a set of SQL statements that you want to test. Typically, we should put a new file in ql/src/test/queries/clientpositive
.
Let’s say you created the following file.
$ cat ql/src/test/queries/clientpositive/aaa.q
SELECT 1;
Generate a result file
You can generate the expected output with -Dtest.output.overwrite=true
.
$ mvn test -Pitests -pl itests/qtest -Dtest=TestMiniLlapLocalCliDriver -Dtest.output.overwrite=true -Dqfile=aaa.q
...
$ cat ql/src/test/results/clientpositive/llap/aaa.q.out
PREHOOK: query: SELECT 1
PREHOOK: type: QUERY
PREHOOK: Input: _dummy_database@_dummy_table
#### A masked pattern was here ####
POSTHOOK: query: SELECT 1
POSTHOOK: type: QUERY
POSTHOOK: Input: _dummy_database@_dummy_table
#### A masked pattern was here ####
1
Verify the new result file
You can ensure the generated result file is correct by rerunning the test case without -Dtest.output.overwrite=true
.
$ mvn test -Pitests -pl itests/qtest -Dtest=TestMiniLlapLocalCliDriver -Dqfile=aaa.q
Commandline options
Test options
Option | Description | Example |
---|---|---|
test | The class name of the test driver | -Dtest=TestMiniLlapLocalCliDriver |
qfile | The name(s) of Query Files | -Dqfile=alter1.q , -Dqfile=alter1.q,alter2.q |
qfile_regex | The pattern to list Query Files | -Dqfile_regex=alter[0-9] |
test.output.overwrite | Whether you want to (re)generate result files or not | -Dtest.output.overwrite=true |
test.metastore.db | Which RDBMS to be used as a metastore backend | See How to use PostgreSQL/MySQL/Oracle as a backend database for Hive Metastore |
Test Iceberg, Accumulo, or Kudu
Most test drivers are available in the itest/qtest
project. However, there are some exceptional ones.
Driver | Project |
---|---|
TestAccumuloCliDriver | itest/qtest-accumulo |
TestIcebergCliDriver | itest/qtest-iceberg |
TestIcebergLlapLocalCliDriver | itest/qtest-iceberg |
TestIcebergLlapLocalCompactorCliDriver | itest/qtest-iceberg |
TestIcebergNegativeCliDriver | itest/qtest-iceberg |
TestKuduCliDriver | itest/qtest-kudu |
TestKuduNegativeCliDriver | itest/qtest-kudu |
When you use TestIcebergLlapLocalCliDriver
, you have to specify -pl itest/qtest-iceberg
.
$ mvn test -Pitests -pl itests/qtest-iceberg -Dtest=TestIcebergLlapLocalCliDriver -Dqfile_regex=iceberg_bucket_map_join_8
QTestOptionHandler: pre/post-processor
We extend JUnit by implementing QTestOptionHandlers, which are custom pre-processors and post-processors. This section explains a couple of typical processors.
Using test data
Adding --! qt:dataset:{table name}
, QTestDatasetHandler automatically sets up a test table. You can find the table definitions here.
--! qt:dataset:src
SELECT * FROM src;
Mask non-deterministic outputs
Some test cases generate random results. QTestReplaceHandler masks such a non-deterministic part. You can use it with a special comment prefixed with --! qt:replace:
.
For example, the result of CURRENT_DATE
changes every day. Using the comment, the output will be non-deterministic-output #Masked#
, which is stable across executions.
--! qt:replace:/(non-deterministic-output\s)[0-9]{4}-[0-9]{2}-[0-9]{2}/$1#Masked#/
SELECT 'non-deterministic-output', CURRENT_DATE();
Advanced
Locations of log files
The Query File Test framework outputs log files in the following paths.
itests/{qtest, qtest-accumulo, qtest-iceberg, qtest-kudu}/target/surefire-reports
- From the root of the source tree:
find . -name hive.log
Negative tests
Negative drivers allow us to make sure that a test case fails expectedly. For example, the query in strict_timestamp_to_numeric.q must fail based on Hive’s specifications. We can use TestNegativeLlapLocalCliDriver
, TestIcebergNegativeCliDriver
, and so on.
$ mvn -Pitests -pl itests/qtest test -Dtest=TestNegativeLlapLocalCliDriver -Dqfile=strict_timestamp_to_numeric.q
How to specify drivers
We define the default mapping of Query Files and test drivers using testconfiguration.properties and CliConfigs. For example, TestMiniLlapLocalCliDriver
is the default driver for query files stored in ql/src/test/queries/clientpositive
. The hive-precommit Jenkins job also follows the mapping.
You can override the mapping through testconfiguration.properties. For example, if you want to test ql/src/test/queries/clientpositive/aaa.q
not by LLAP but by Tez, you must include the file name in minitez.query.files
and generate the result file with -Dtest=TestMiniTezCliDriver
.
In most cases, we should use TestMiniLlapLocalCliDriver
for positive tests and TestNegativeLlapLocalCliDriver
for negative tests.
How to use PostgreSQL/MySQL/Oracle as a backend database for Hive Metastore
To run a test with a specified DB, it is possible by adding the “-Dtest.metastore.db” parameter like in the following commands:
$ mvn test -Pitests -pl itests/qtest -Dtest=TestCliDriver -Dqfile=partition_params_postgres.q -Dtest.metastore.db=postgres
$ mvn test -Pitests -pl itests/qtest -Dtest=TestCliDriver -Dqfile=partition_params_postgres.q -Dtest.metastore.db=mssql
$ mvn test -Pitests -pl itests/qtest -Dtest=TestCliDriver -Dqfile=partition_params_postgres.q -Dtest.metastore.db=mysql
$ mvn test -Pitests -pl itests/qtest -Dtest=TestCliDriver -Dqfile=partition_params_postgres.q -Dtest.metastore.db=oracle -Ditest.jdbc.jars=/path/to/your/god/damn/oracle/jdbc/driver/ojdbc6.jar
Remote debug
Remote debugging with Query File Test is a potent tool for debugging Hive. With the following command, Query File Test listens to port 5005 and waits for a debugger to be attached.
$ mvn -Pitests -pl itests/qtest -Dmaven.surefire.debug test -Dtest=TestMiniLlapLocalCliDriver -Dqfile=alter1.q