Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revamp failure testing with query assertions #20509

Merged
merged 6 commits into from
Jan 31, 2024
Merged

Conversation

findepi
Copy link
Member

@findepi findepi commented Jan 30, 2024

Before the introduction of query assertions (the QueryAssert class),
assertQueryFails was used to verify that a query fails with expected
error message AND the failure exception type is TrinoException.

With query assertions, the typical pattern for testing query failures
became:

assertThatThrownBy(() -> query(...))
    ....

This unfortunately does not verify that the exception type is the
TrinoException. The existing alternative:

assertTrinoExceptionThrownBy(() -> query(...))
    ...

is rarely used, perhaps because it's longer and the
established shorter pattern is followed.

Both above methods share the disadvantage of basing on the QueryAssert
construction side-effect of evaluating the query eagerly.

This commit revamps QueryAssert to make failures first class citizen
from QueryAssert perspective, on par with query results. Expected
failures are verified to be TrinoException type. The result is more
fluent API, as both success and failures assertions are available on the
same query assert object, and thus can be auto-completed by an IDE.

From code updating perspective, most of the code updates fall into two
categories:

  • failure testing. This functionality is available from query assert via
    .failure() accessor. Code was updated with regular expression

    • search for: (assertThatThrownBy|assertTrinoExceptionThrownBy)\(\(\) -> (assertions\.)?query\(
    • replace with: assertThat($2query(
    • add .failure() to access assertions on the failure exception.
      (use nonTrinoExceptionFailure() for cases where query incorrectly
      fails without a proper TrinoException)
  • detailed inspection of MaterializedResult objects. This lower-level
    functionality is available from query assert via .result()
    accessor.

@findepi findepi added test no-release-notes This pull request does not require release notes entry labels Jan 30, 2024
@cla-bot cla-bot bot added the cla-signed label Jan 30, 2024
@findepi findepi marked this pull request as draft January 30, 2024 16:16
@findepi findepi marked this pull request as ready for review January 30, 2024 16:16
@github-actions github-actions bot added tests:hive iceberg Iceberg connector delta-lake Delta Lake connector hive Hive connector bigquery BigQuery connector mongodb MongoDB connector labels Jan 30, 2024
@findepi
Copy link
Member Author

findepi commented Jan 30, 2024

cc @trinodb/maintainers

@findepi
Copy link
Member Author

findepi commented Jan 30, 2024

currently based on #20506

@@ -38,22 +37,22 @@ public void teardown()
@Test
public void testQuantifiedComparison()
{
assertThatThrownBy(() -> assertions.query("SELECT v > ALL (VALUES 1) FROM (VALUES (1, 1), (1, 2)) t(k, v) GROUP BY k"))
.hasMessageContaining("must be an aggregate expression or appear in GROUP BY clause");
assertThat(assertions.query("SELECT v > ALL (VALUES 1) FROM (VALUES (1, 1), (1, 2)) t(k, v) GROUP BY k"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the new API :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you!

Copy link
Contributor

@wendigo wendigo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@findepi Can we extract changes to the QueryAssertions in the last commit to the separate commit as you are mixing mechanical (regex) changes and manual ones in a single commit?

@wendigo
Copy link
Contributor

wendigo commented Jan 30, 2024

There are related failures

@findepi
Copy link
Member Author

findepi commented Jan 30, 2024

Can we extract changes to the QueryAssertions in the last commit to the separate commit as you are mixing mechanical (regex) changes and manual ones in a single commit?

The changes are tightly related, I don't see a way to split them.

`ensureOrdering` was always false, so effectively unused.
Previously, the `QueryAssert.query` could represent original SQL query,
or a description (in case of column projections). This commit separates
those duties. Original query is not available in case of projections
because it would not produce the current (projected) result.
@findepi findepi force-pushed the findepi/assert-failure branch 3 times, most recently from b09982c to 86afd6b Compare January 30, 2024 21:56
Copy link
Contributor

@wendigo wendigo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM % failures

@findepi
Copy link
Member Author

findepi commented Jan 31, 2024

The new API requires that failures are a TrinoException (and has an scape hatch for cases where they are not).
When migrating from to the new API, i opted to expected TrinoException everywhere and this is the cause of all the test failures noticed so far. In so many tests we were testing for a failure, but the actual exception is wrong.

No plan to fix these in this PR, but they will now be easy to spot (any usages of nonTrinoExceptionFailure()).

Update places that depended on `query(...)` query assert constructor
executing the query. These should use `execute`, `assertUpdate`, etc.
Copy link
Member

@losipiuk losipiuk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks nice

@wendigo
Copy link
Contributor

wendigo commented Jan 31, 2024

BigQuery related:

TestBigQueryAvroConnectorTest>BaseBigQueryConnectorTest.testDateYearOfEraPredicate:607 Expected TrinoException or wrapper, but got: io.trino.testing.QueryFailedException io.trino.testing.QueryFailedException: io.grpc.StatusRuntimeException: INVALID_ARGUMENT: request failed: Query error: Could not cast literal "-1996-09-14" to type DATE at [1:372]
Error:    TestBigQueryAvroConnectorTest>BaseBigQueryConnectorTest.testMissingWildcardTable:799 Expected TrinoException or wrapper, but got: io.trino.testing.QueryFailedException io.trino.testing.QueryFailedException: sep-bq-cicd:test.test_missing_wildcard_table_* does not match any table.
Error:    TestBigQueryAvroConnectorTest>BaseBigQueryConnectorTest.testNativeQuerySelectUnsupportedType:938 Expected TrinoException or wrapper, but got: io.trino.testing.QueryFailedException io.trino.testing.QueryFailedException: Unsupported type: BIGNUMERIC

Before the introduction of query assertions (the `QueryAssert` class),
`assertQueryFails` was used to verify that a query fails with expected
error message AND the failure exception type is `TrinoException`.

With query assertions, the typical pattern for testing query failures
became:

    assertThatThrownBy(() -> query(...))
        ....

This unfortunately does not verify that the exception type is the
`TrinoException`. The existing alternative:

    assertTrinoExceptionThrownBy(() -> query(...))
        ...

is rarely used, perhaps because it's longer and the
established shorter pattern is followed.

Both above methods share the disadvantage of basing on the `QueryAssert`
construction side-effect of evaluating the query eagerly.

This commit revamps `QueryAssert` to make failures first class citizen
from `QueryAssert` perspective, on par with query results. Expected
failures are verified to be `TrinoException` type. The result is more
fluent API, as both success and failures assertions are available on the
same query assert object, and thus can be auto-completed by an IDE.

From code updating perspective, most of the code updates fall into two
categories:

* failure testing. This functionality is available from query assert via
  `.failure()` accessor. Code was updated with regular expression
  - search for: `(assertThatThrownBy|assertTrinoExceptionThrownBy)\(\(\) -> (assertions\.)?query\(`
  - replace with: `assertThat($2query(`
  - add `.failure()` to access assertions on the failure exception
    (use `nonTrinoExceptionFailure()` for cases where query incorrectly
    fails without a proper `TrinoException`)

* detailed inspection of `MaterializedResult` objects. This lower-level
  functionality is available from query assert via `.result()`
  accessor.
@findepi findepi merged commit 1da9822 into master Jan 31, 2024
100 checks passed
@findepi findepi deleted the findepi/assert-failure branch January 31, 2024 13:29
@github-actions github-actions bot added this to the 438 milestone Jan 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bigquery BigQuery connector cla-signed delta-lake Delta Lake connector hive Hive connector iceberg Iceberg connector mongodb MongoDB connector no-release-notes This pull request does not require release notes entry test
Development

Successfully merging this pull request may close these issues.

3 participants