This is an automated email from the ASF dual-hosted git repository.

etudenhoefner pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iceberg.git


The following commit(s) were added to refs/heads/master by this push:
     new a0b1df2866 Spark: Remove Usage of deprecated AssertHelpers in 
spark-sql (#7486)
a0b1df2866 is described below

commit a0b1df28665abc2156dd22d5c5c49161afd10e01
Author: Liu Xiao <[email protected]>
AuthorDate: Mon May 1 17:51:45 2023 +0800

    Spark: Remove Usage of deprecated AssertHelpers in spark-sql (#7486)
---
 .../apache/iceberg/spark/sql/TestAlterTable.java   |  37 +++--
 .../apache/iceberg/spark/sql/TestCreateTable.java  |  27 ++--
 .../apache/iceberg/spark/sql/TestDeleteFrom.java   |  11 +-
 .../apache/iceberg/spark/sql/TestDropTable.java    |  11 +-
 .../apache/iceberg/spark/sql/TestNamespaceSQL.java |  10 +-
 .../org/apache/iceberg/spark/sql/TestSelect.java   |  99 ++++++------
 .../iceberg/spark/sql/TestSparkBucketFunction.java | 166 ++++++++++-----------
 .../iceberg/spark/sql/TestSparkDaysFunction.java   |  38 +++--
 .../iceberg/spark/sql/TestSparkHoursFunction.java  |  39 +++--
 .../iceberg/spark/sql/TestSparkMonthsFunction.java |  38 +++--
 .../spark/sql/TestSparkTruncateFunction.java       | 160 ++++++++++----------
 .../iceberg/spark/sql/TestSparkYearsFunction.java  |  38 +++--
 .../spark/sql/TestTimestampWithoutZone.java        |  14 +-
 .../spark/sql/UnpartitionedWritesTestBase.java     |  29 ++--
 14 files changed, 336 insertions(+), 381 deletions(-)

diff --git 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestAlterTable.java
 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestAlterTable.java
index e347cde7ba..92d917e0ca 100644
--- 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestAlterTable.java
+++ 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestAlterTable.java
@@ -19,7 +19,6 @@
 package org.apache.iceberg.spark.sql;
 
 import java.util.Map;
-import org.apache.iceberg.AssertHelpers;
 import org.apache.iceberg.catalog.Namespace;
 import org.apache.iceberg.catalog.TableIdentifier;
 import org.apache.iceberg.hadoop.HadoopCatalog;
@@ -28,6 +27,7 @@ import org.apache.iceberg.types.Types;
 import org.apache.iceberg.types.Types.NestedField;
 import org.apache.spark.SparkException;
 import org.apache.spark.sql.AnalysisException;
+import org.assertj.core.api.Assertions;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Assume;
@@ -55,11 +55,10 @@ public class TestAlterTable extends SparkCatalogTestBase {
 
   @Test
   public void testAddColumnNotNull() {
-    AssertHelpers.assertThrows(
-        "Should reject adding NOT NULL column",
-        SparkException.class,
-        "Incompatible change: cannot add required column",
-        () -> sql("ALTER TABLE %s ADD COLUMN c3 INT NOT NULL", tableName));
+    Assertions.assertThatThrownBy(() -> sql("ALTER TABLE %s ADD COLUMN c3 INT 
NOT NULL", tableName))
+        .isInstanceOf(SparkException.class)
+        .hasMessage(
+            "Unsupported table change: Incompatible change: cannot add 
required column: c3");
   }
 
   @Test
@@ -156,11 +155,9 @@ public class TestAlterTable extends SparkCatalogTestBase {
         validationCatalog.loadTable(tableIdent).schema().asStruct());
 
     // should not allow changing map key column
-    AssertHelpers.assertThrows(
-        "Should reject changing key of the map column",
-        SparkException.class,
-        "Unsupported table change: Cannot add fields to map keys:",
-        () -> sql("ALTER TABLE %s ADD COLUMN data2.key.y int", tableName));
+    Assertions.assertThatThrownBy(() -> sql("ALTER TABLE %s ADD COLUMN 
data2.key.y int", tableName))
+        .isInstanceOf(SparkException.class)
+        .hasMessageStartingWith("Unsupported table change: Cannot add fields 
to map keys:");
   }
 
   @Test
@@ -253,11 +250,10 @@ public class TestAlterTable extends SparkCatalogTestBase {
         expectedSchema,
         validationCatalog.loadTable(tableIdent).schema().asStruct());
 
-    AssertHelpers.assertThrows(
-        "Should reject adding NOT NULL constraint to an optional column",
-        AnalysisException.class,
-        "Cannot change nullable column to non-nullable: data",
-        () -> sql("ALTER TABLE %s ALTER COLUMN data SET NOT NULL", tableName));
+    Assertions.assertThatThrownBy(
+            () -> sql("ALTER TABLE %s ALTER COLUMN data SET NOT NULL", 
tableName))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith("Cannot change nullable column to 
non-nullable: data");
   }
 
   @Test
@@ -323,9 +319,10 @@ public class TestAlterTable extends SparkCatalogTestBase {
         "Should not have the removed table property",
         validationCatalog.loadTable(tableIdent).properties().get("prop"));
 
-    AssertHelpers.assertThrows(
-        "Cannot specify the 'sort-order' because it's a reserved table 
property",
-        UnsupportedOperationException.class,
-        () -> sql("ALTER TABLE %s SET TBLPROPERTIES ('sort-order'='value')", 
tableName));
+    Assertions.assertThatThrownBy(
+            () -> sql("ALTER TABLE %s SET TBLPROPERTIES 
('sort-order'='value')", tableName))
+        .isInstanceOf(UnsupportedOperationException.class)
+        .hasMessageStartingWith(
+            "Cannot specify the 'sort-order' because it's a reserved table 
property");
   }
 }
diff --git 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
index 1411c83ddc..01b8b99062 100644
--- 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
+++ 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestCreateTable.java
@@ -20,7 +20,6 @@ package org.apache.iceberg.spark.sql;
 
 import java.io.File;
 import java.util.Map;
-import org.apache.iceberg.AssertHelpers;
 import org.apache.iceberg.BaseTable;
 import org.apache.iceberg.PartitionSpec;
 import org.apache.iceberg.Schema;
@@ -33,6 +32,7 @@ import org.apache.iceberg.types.Types;
 import org.apache.iceberg.types.Types.NestedField;
 import org.apache.iceberg.types.Types.StructType;
 import org.apache.spark.sql.connector.catalog.TableCatalog;
+import org.assertj.core.api.Assertions;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Assume;
@@ -121,14 +121,13 @@ public class TestCreateTable extends SparkCatalogTestBase 
{
         "parquet",
         table.properties().get(TableProperties.DEFAULT_FILE_FORMAT));
 
-    AssertHelpers.assertThrows(
-        "Should reject unsupported format names",
-        IllegalArgumentException.class,
-        "Unsupported format in USING: crocodile",
-        () ->
-            sql(
-                "CREATE TABLE %s.default.fail (id BIGINT NOT NULL, data 
STRING) USING crocodile",
-                catalogName));
+    Assertions.assertThatThrownBy(
+            () ->
+                sql(
+                    "CREATE TABLE %s.default.fail (id BIGINT NOT NULL, data 
STRING) USING crocodile",
+                    catalogName))
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessage("Unsupported format in USING: crocodile");
   }
 
   @Test
@@ -335,10 +334,10 @@ public class TestCreateTable extends SparkCatalogTestBase 
{
     TableOperations ops = ((BaseTable) table).operations();
     Assert.assertEquals("should create table using format v2", 2, 
ops.refresh().formatVersion());
 
-    AssertHelpers.assertThrowsCause(
-        "should fail to downgrade to v1",
-        IllegalArgumentException.class,
-        "Cannot downgrade v2 table to v1",
-        () -> sql("ALTER TABLE %s SET TBLPROPERTIES ('format-version'='1')", 
tableName));
+    Assertions.assertThatThrownBy(
+            () -> sql("ALTER TABLE %s SET TBLPROPERTIES 
('format-version'='1')", tableName))
+        .cause()
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessage("Cannot downgrade v2 table to v1");
   }
 }
diff --git 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestDeleteFrom.java
 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestDeleteFrom.java
index cae1901aa7..a4b1ef3b9d 100644
--- 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestDeleteFrom.java
+++ 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestDeleteFrom.java
@@ -20,7 +20,6 @@ package org.apache.iceberg.spark.sql;
 
 import java.util.List;
 import java.util.Map;
-import org.apache.iceberg.AssertHelpers;
 import org.apache.iceberg.Table;
 import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
 import org.apache.iceberg.relocated.com.google.common.collect.Iterables;
@@ -30,6 +29,7 @@ import org.apache.iceberg.spark.source.SimpleRecord;
 import org.apache.spark.sql.Dataset;
 import org.apache.spark.sql.Row;
 import org.apache.spark.sql.catalyst.analysis.NoSuchTableException;
+import org.assertj.core.api.Assertions;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Test;
@@ -86,11 +86,10 @@ public class TestDeleteFrom extends SparkCatalogTestBase {
 
     long snapshotId = 
validationCatalog.loadTable(tableIdent).currentSnapshot().snapshotId();
     String prefix = "snapshot_id_";
-    AssertHelpers.assertThrows(
-        "Should not be able to delete from a table at a specific snapshot",
-        IllegalArgumentException.class,
-        "Cannot delete from table at a specific snapshot",
-        () -> sql("DELETE FROM %s.%s WHERE id < 4", tableName, prefix + 
snapshotId));
+    Assertions.assertThatThrownBy(
+            () -> sql("DELETE FROM %s.%s WHERE id < 4", tableName, prefix + 
snapshotId))
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessageStartingWith("Cannot delete from table at a specific 
snapshot");
   }
 
   @Test
diff --git 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestDropTable.java
 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestDropTable.java
index 34b6899a1c..496e7a618b 100644
--- 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestDropTable.java
+++ 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestDropTable.java
@@ -24,12 +24,12 @@ import java.util.Map;
 import java.util.stream.Collectors;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
-import org.apache.iceberg.AssertHelpers;
 import org.apache.iceberg.MetadataTableType;
 import org.apache.iceberg.exceptions.ValidationException;
 import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
 import org.apache.iceberg.relocated.com.google.common.collect.Streams;
 import org.apache.iceberg.spark.SparkCatalogTestBase;
+import org.assertj.core.api.Assertions;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -119,11 +119,10 @@ public class TestDropTable extends SparkCatalogTestBase {
         "There totally should have 2 files for manifests and files", 2, 
manifestAndFiles.size());
     Assert.assertTrue("All files should be existed", 
checkFilesExist(manifestAndFiles, true));
 
-    AssertHelpers.assertThrows(
-        "Purge table is not allowed when GC is disabled",
-        ValidationException.class,
-        "Cannot purge table: GC is disabled (deleting files may corrupt other 
tables",
-        () -> sql("DROP TABLE %s PURGE", tableName));
+    Assertions.assertThatThrownBy(() -> sql("DROP TABLE %s PURGE", tableName))
+        .isInstanceOf(ValidationException.class)
+        .hasMessageContaining(
+            "Cannot purge table: GC is disabled (deleting files may corrupt 
other tables");
 
     Assert.assertTrue("Table should not been dropped", 
validationCatalog.tableExists(tableIdent));
     Assert.assertTrue("All files should not be deleted", 
checkFilesExist(manifestAndFiles, true));
diff --git 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestNamespaceSQL.java
 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestNamespaceSQL.java
index 6c29ea4442..5ee2526a71 100644
--- 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestNamespaceSQL.java
+++ 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestNamespaceSQL.java
@@ -23,13 +23,13 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
-import org.apache.iceberg.AssertHelpers;
 import org.apache.iceberg.catalog.Namespace;
 import org.apache.iceberg.catalog.TableIdentifier;
 import org.apache.iceberg.exceptions.NamespaceNotEmptyException;
 import org.apache.iceberg.relocated.com.google.common.collect.ImmutableSet;
 import org.apache.iceberg.relocated.com.google.common.collect.Iterables;
 import org.apache.iceberg.spark.SparkCatalogTestBase;
+import org.assertj.core.api.Assertions;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Assume;
@@ -103,11 +103,9 @@ public class TestNamespaceSQL extends SparkCatalogTestBase 
{
     Assert.assertTrue(
         "Table should exist", 
validationCatalog.tableExists(TableIdentifier.of(NS, "table")));
 
-    AssertHelpers.assertThrows(
-        "Should fail if trying to delete a non-empty namespace",
-        NamespaceNotEmptyException.class,
-        "Namespace db is not empty.",
-        () -> sql("DROP NAMESPACE %s", fullNamespace));
+    Assertions.assertThatThrownBy(() -> sql("DROP NAMESPACE %s", 
fullNamespace))
+        .isInstanceOf(NamespaceNotEmptyException.class)
+        .hasMessageStartingWith("Namespace db is not empty.");
 
     sql("DROP TABLE %s.table", fullNamespace);
   }
diff --git 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSelect.java 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSelect.java
index e08bc4574d..dacaee7d80 100644
--- 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSelect.java
+++ 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSelect.java
@@ -23,7 +23,6 @@ import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
-import org.apache.iceberg.AssertHelpers;
 import org.apache.iceberg.Table;
 import org.apache.iceberg.events.Listeners;
 import org.apache.iceberg.events.ScanEvent;
@@ -382,48 +381,44 @@ public class TestSelect extends SparkCatalogTestBase {
     sql("INSERT INTO %s VALUES (4, 'd', 4.0), (5, 'e', 5.0)", tableName);
 
     // using snapshot in table identifier and VERSION AS OF
-    AssertHelpers.assertThrows(
-        "Cannot do time-travel based on both table identifier and AS OF",
-        IllegalArgumentException.class,
-        "Cannot do time-travel based on both table identifier and AS OF",
-        () -> {
-          sql(
-              "SELECT * FROM %s.%s VERSION AS OF %s",
-              tableName, snapshotPrefix + snapshotId, snapshotId);
-        });
+    Assertions.assertThatThrownBy(
+            () -> {
+              sql(
+                  "SELECT * FROM %s.%s VERSION AS OF %s",
+                  tableName, snapshotPrefix + snapshotId, snapshotId);
+            })
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessage("Cannot do time-travel based on both table identifier and 
AS OF");
 
     // using snapshot in table identifier and TIMESTAMP AS OF
-    AssertHelpers.assertThrows(
-        "Cannot do time-travel based on both table identifier and AS OF",
-        IllegalArgumentException.class,
-        "Cannot do time-travel based on both table identifier and AS OF",
-        () -> {
-          sql(
-              "SELECT * FROM %s.%s VERSION AS OF %s",
-              tableName, timestampPrefix + timestamp, snapshotId);
-        });
+    Assertions.assertThatThrownBy(
+            () -> {
+              sql(
+                  "SELECT * FROM %s.%s VERSION AS OF %s",
+                  tableName, timestampPrefix + timestamp, snapshotId);
+            })
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessage("Cannot do time-travel based on both table identifier and 
AS OF");
 
     // using timestamp in table identifier and VERSION AS OF
-    AssertHelpers.assertThrows(
-        "Cannot do time-travel based on both table identifier and AS OF",
-        IllegalArgumentException.class,
-        "Cannot do time-travel based on both table identifier and AS OF",
-        () -> {
-          sql(
-              "SELECT * FROM %s.%s TIMESTAMP AS OF %s",
-              tableName, snapshotPrefix + snapshotId, timestamp);
-        });
+    Assertions.assertThatThrownBy(
+            () -> {
+              sql(
+                  "SELECT * FROM %s.%s TIMESTAMP AS OF %s",
+                  tableName, snapshotPrefix + snapshotId, timestamp);
+            })
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessage("Cannot do time-travel based on both table identifier and 
AS OF");
 
     // using timestamp in table identifier and TIMESTAMP AS OF
-    AssertHelpers.assertThrows(
-        "Cannot do time-travel based on both table identifier and AS OF",
-        IllegalArgumentException.class,
-        "Cannot do time-travel based on both table identifier and AS OF",
-        () -> {
-          sql(
-              "SELECT * FROM %s.%s TIMESTAMP AS OF %s",
-              tableName, timestampPrefix + timestamp, timestamp);
-        });
+    Assertions.assertThatThrownBy(
+            () -> {
+              sql(
+                  "SELECT * FROM %s.%s TIMESTAMP AS OF %s",
+                  tableName, timestampPrefix + timestamp, timestamp);
+            })
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessage("Cannot do time-travel based on both table identifier and 
AS OF");
   }
 
   @Test
@@ -437,21 +432,21 @@ public class TestSelect extends SparkCatalogTestBase {
     // create a second snapshot
     sql("INSERT INTO %s VALUES (4, 'd', 4.0), (5, 'e', 5.0)", tableName);
 
-    AssertHelpers.assertThrows(
-        "Should not be able to specify both snapshot id and timestamp",
-        IllegalArgumentException.class,
-        String.format(
-            "Can specify only one of snapshot-id (%s), as-of-timestamp (%s)",
-            snapshotId, timestamp),
-        () -> {
-          spark
-              .read()
-              .format("iceberg")
-              .option(SparkReadOptions.SNAPSHOT_ID, snapshotId)
-              .option(SparkReadOptions.AS_OF_TIMESTAMP, timestamp)
-              .load(tableName)
-              .collectAsList();
-        });
+    Assertions.assertThatThrownBy(
+            () -> {
+              spark
+                  .read()
+                  .format("iceberg")
+                  .option(SparkReadOptions.SNAPSHOT_ID, snapshotId)
+                  .option(SparkReadOptions.AS_OF_TIMESTAMP, timestamp)
+                  .load(tableName)
+                  .collectAsList();
+            })
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessageStartingWith(
+            String.format(
+                "Can specify only one of snapshot-id (%s), as-of-timestamp 
(%s)",
+                snapshotId, timestamp));
   }
 
   @Test
diff --git 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkBucketFunction.java
 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkBucketFunction.java
index c9c8c02b41..075bbbc2e0 100644
--- 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkBucketFunction.java
+++ 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkBucketFunction.java
@@ -21,7 +21,6 @@ package org.apache.iceberg.spark.sql;
 import java.math.BigDecimal;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
-import org.apache.iceberg.AssertHelpers;
 import org.apache.iceberg.expressions.Literal;
 import org.apache.iceberg.relocated.com.google.common.io.BaseEncoding;
 import org.apache.iceberg.spark.SparkTestBaseWithCatalog;
@@ -191,101 +190,92 @@ public class TestSparkBucketFunction extends 
SparkTestBaseWithCatalog {
 
   @Test
   public void testWrongNumberOfArguments() {
-    AssertHelpers.assertThrows(
-        "Function resolution should not work with zero arguments",
-        AnalysisException.class,
-        "Function 'bucket' cannot process input: (): Wrong number of inputs 
(expected numBuckets and value)",
-        () -> scalarSql("SELECT system.bucket()"));
-
-    AssertHelpers.assertThrows(
-        "Function resolution should not work with only one argument",
-        AnalysisException.class,
-        "Function 'bucket' cannot process input: (int): Wrong number of inputs 
(expected numBuckets and value)",
-        () -> scalarSql("SELECT system.bucket(1)"));
-
-    AssertHelpers.assertThrows(
-        "Function resolution should not work with more than two arguments",
-        AnalysisException.class,
-        "Function 'bucket' cannot process input: (int, bigint, int): Wrong 
number of inputs (expected numBuckets and value)",
-        () -> scalarSql("SELECT system.bucket(1, 1L, 1)"));
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.bucket()"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'bucket' cannot process input: (): Wrong number of 
inputs (expected numBuckets and value)");
+
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.bucket(1)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'bucket' cannot process input: (int): Wrong number of 
inputs (expected numBuckets and value)");
+
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.bucket(1, 1L, 
1)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'bucket' cannot process input: (int, bigint, int): Wrong 
number of inputs (expected numBuckets and value)");
   }
 
   @Test
   public void testInvalidTypesCannotBeUsedForNumberOfBuckets() {
-    AssertHelpers.assertThrows(
-        "Decimal type should not be coercible to the number of buckets",
-        AnalysisException.class,
-        "Function 'bucket' cannot process input: (decimal(9,2), int): Expected 
number of buckets to be tinyint, shortint or int",
-        () -> scalarSql("SELECT system.bucket(CAST('12.34' as DECIMAL(9, 2)), 
10)"));
-
-    AssertHelpers.assertThrows(
-        "Long type should not be coercible to the number of buckets",
-        AnalysisException.class,
-        "Function 'bucket' cannot process input: (bigint, int): Expected 
number of buckets to be tinyint, shortint or int",
-        () -> scalarSql("SELECT system.bucket(12L, 10)"));
-
-    AssertHelpers.assertThrows(
-        "String type should not be coercible to the number of buckets",
-        AnalysisException.class,
-        "Function 'bucket' cannot process input: (string, int): Expected 
number of buckets to be tinyint, shortint or int",
-        () -> scalarSql("SELECT system.bucket('5', 10)"));
-
-    AssertHelpers.assertThrows(
-        "Interval year to month  type should not be coercible to the number of 
buckets",
-        AnalysisException.class,
-        "Function 'bucket' cannot process input: (interval year to month, 
int): Expected number of buckets to be tinyint, shortint or int",
-        () -> scalarSql("SELECT system.bucket(INTERVAL '100-00' YEAR TO MONTH, 
10)"));
-
-    AssertHelpers.assertThrows(
-        "Interval day-time type should not be coercible to the number of 
buckets",
-        AnalysisException.class,
-        "Function 'bucket' cannot process input: (interval day to second, 
int): Expected number of buckets to be tinyint, shortint or int",
-        () -> scalarSql("SELECT system.bucket(CAST('11 23:4:0' AS INTERVAL DAY 
TO SECOND), 10)"));
+    Assertions.assertThatThrownBy(
+            () -> scalarSql("SELECT system.bucket(CAST('12.34' as DECIMAL(9, 
2)), 10)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'bucket' cannot process input: (decimal(9,2), int): 
Expected number of buckets to be tinyint, shortint or int");
+
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.bucket(12L, 
10)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'bucket' cannot process input: (bigint, int): Expected 
number of buckets to be tinyint, shortint or int");
+
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.bucket('5', 
10)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'bucket' cannot process input: (string, int): Expected 
number of buckets to be tinyint, shortint or int");
+
+    Assertions.assertThatThrownBy(
+            () -> scalarSql("SELECT system.bucket(INTERVAL '100-00' YEAR TO 
MONTH, 10)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'bucket' cannot process input: (interval year to month, 
int): Expected number of buckets to be tinyint, shortint or int");
+
+    Assertions.assertThatThrownBy(
+            () ->
+                scalarSql("SELECT system.bucket(CAST('11 23:4:0' AS INTERVAL 
DAY TO SECOND), 10)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'bucket' cannot process input: (interval day to second, 
int): Expected number of buckets to be tinyint, shortint or int");
   }
 
   @Test
   public void testInvalidTypesForBucketColumn() {
-    AssertHelpers.assertThrows(
-        "Double type should not be bucketable",
-        AnalysisException.class,
-        "Function 'bucket' cannot process input: (int, float): Expected column 
to be date, tinyint, smallint, int, bigint, decimal, timestamp, string, or 
binary",
-        () -> scalarSql("SELECT system.bucket(10, cast(12.3456 as float))"));
-
-    AssertHelpers.assertThrows(
-        "Double type should not be bucketable",
-        AnalysisException.class,
-        "Function 'bucket' cannot process input: (int, double): Expected 
column to be date, tinyint, smallint, int, bigint, decimal, timestamp, string, 
or binary",
-        () -> scalarSql("SELECT system.bucket(10, cast(12.3456 as double))"));
-
-    AssertHelpers.assertThrows(
-        "Boolean type should not be bucketable",
-        AnalysisException.class,
-        "Function 'bucket' cannot process input: (int, boolean)",
-        () -> scalarSql("SELECT system.bucket(10, true)"));
-
-    AssertHelpers.assertThrows(
-        "Map types should not be bucketable",
-        AnalysisException.class,
-        "Function 'bucket' cannot process input: (int, map<int,int>)",
-        () -> scalarSql("SELECT system.bucket(10, map(1, 1))"));
-
-    AssertHelpers.assertThrows(
-        "Array types should not be bucketable",
-        AnalysisException.class,
-        "Function 'bucket' cannot process input: (int, array<bigint>)",
-        () -> scalarSql("SELECT system.bucket(10, array(1L))"));
-
-    AssertHelpers.assertThrows(
-        "Interval year-to-month type should not be bucketable",
-        AnalysisException.class,
-        "Function 'bucket' cannot process input: (int, interval year to 
month)",
-        () -> scalarSql("SELECT system.bucket(10, INTERVAL '100-00' YEAR TO 
MONTH)"));
-
-    AssertHelpers.assertThrows(
-        "Interval day-time type should not be bucketable",
-        AnalysisException.class,
-        "Function 'bucket' cannot process input: (int, interval day to 
second)",
-        () -> scalarSql("SELECT system.bucket(10, CAST('11 23:4:0' AS INTERVAL 
DAY TO SECOND))"));
+    Assertions.assertThatThrownBy(
+            () -> scalarSql("SELECT system.bucket(10, cast(12.3456 as 
float))"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'bucket' cannot process input: (int, float): Expected 
column to be date, tinyint, smallint, int, bigint, decimal, timestamp, string, 
or binary");
+
+    Assertions.assertThatThrownBy(
+            () -> scalarSql("SELECT system.bucket(10, cast(12.3456 as 
double))"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'bucket' cannot process input: (int, double): Expected 
column to be date, tinyint, smallint, int, bigint, decimal, timestamp, string, 
or binary");
+
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.bucket(10, 
true)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith("Function 'bucket' cannot process input: (int, 
boolean)");
+
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.bucket(10, 
map(1, 1))"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith("Function 'bucket' cannot process input: (int, 
map<int,int>)");
+
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.bucket(10, 
array(1L))"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith("Function 'bucket' cannot process input: (int, 
array<bigint>)");
+
+    Assertions.assertThatThrownBy(
+            () -> scalarSql("SELECT system.bucket(10, INTERVAL '100-00' YEAR 
TO MONTH)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'bucket' cannot process input: (int, interval year to 
month)");
+
+    Assertions.assertThatThrownBy(
+            () ->
+                scalarSql("SELECT system.bucket(10, CAST('11 23:4:0' AS 
INTERVAL DAY TO SECOND))"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'bucket' cannot process input: (int, interval day to 
second)");
   }
 
   @Test
diff --git 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkDaysFunction.java
 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkDaysFunction.java
index ccba28735e..3efcc06ae7 100644
--- 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkDaysFunction.java
+++ 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkDaysFunction.java
@@ -19,9 +19,9 @@
 package org.apache.iceberg.spark.sql;
 
 import java.sql.Date;
-import org.apache.iceberg.AssertHelpers;
 import org.apache.iceberg.spark.SparkTestBaseWithCatalog;
 import org.apache.spark.sql.AnalysisException;
+import org.assertj.core.api.Assertions;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -69,31 +69,27 @@ public class TestSparkDaysFunction extends 
SparkTestBaseWithCatalog {
 
   @Test
   public void testWrongNumberOfArguments() {
-    AssertHelpers.assertThrows(
-        "Function resolution should not work with zero arguments",
-        AnalysisException.class,
-        "Function 'days' cannot process input: (): Wrong number of inputs",
-        () -> scalarSql("SELECT system.days()"));
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.days()"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith("Function 'days' cannot process input: (): 
Wrong number of inputs");
 
-    AssertHelpers.assertThrows(
-        "Function resolution should not work with more than one argument",
-        AnalysisException.class,
-        "Function 'days' cannot process input: (date, date): Wrong number of 
inputs",
-        () -> scalarSql("SELECT system.days(date('1969-12-31'), 
date('1969-12-31'))"));
+    Assertions.assertThatThrownBy(
+            () -> scalarSql("SELECT system.days(date('1969-12-31'), 
date('1969-12-31'))"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'days' cannot process input: (date, date): Wrong number 
of inputs");
   }
 
   @Test
   public void testInvalidInputTypes() {
-    AssertHelpers.assertThrows(
-        "Int type should not be coercible to date/timestamp",
-        AnalysisException.class,
-        "Function 'days' cannot process input: (int): Expected value to be 
date or timestamp",
-        () -> scalarSql("SELECT system.days(1)"));
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.days(1)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'days' cannot process input: (int): Expected value to be 
date or timestamp");
 
-    AssertHelpers.assertThrows(
-        "Long type should not be coercible to date/timestamp",
-        AnalysisException.class,
-        "Function 'days' cannot process input: (bigint): Expected value to be 
date or timestamp",
-        () -> scalarSql("SELECT system.days(1L)"));
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.days(1L)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'days' cannot process input: (bigint): Expected value to 
be date or timestamp");
   }
 }
diff --git 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkHoursFunction.java
 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkHoursFunction.java
index fc0d781318..9358df4153 100644
--- 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkHoursFunction.java
+++ 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkHoursFunction.java
@@ -18,9 +18,9 @@
  */
 package org.apache.iceberg.spark.sql;
 
-import org.apache.iceberg.AssertHelpers;
 import org.apache.iceberg.spark.SparkTestBaseWithCatalog;
 import org.apache.spark.sql.AnalysisException;
+import org.assertj.core.api.Assertions;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -51,31 +51,28 @@ public class TestSparkHoursFunction extends 
SparkTestBaseWithCatalog {
 
   @Test
   public void testWrongNumberOfArguments() {
-    AssertHelpers.assertThrows(
-        "Function resolution should not work with zero arguments",
-        AnalysisException.class,
-        "Function 'hours' cannot process input: (): Wrong number of inputs",
-        () -> scalarSql("SELECT system.hours()"));
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.hours()"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'hours' cannot process input: (): Wrong number of 
inputs");
 
-    AssertHelpers.assertThrows(
-        "Function resolution should not work with more than one argument",
-        AnalysisException.class,
-        "Function 'hours' cannot process input: (date, date): Wrong number of 
inputs",
-        () -> scalarSql("SELECT system.hours(date('1969-12-31'), 
date('1969-12-31'))"));
+    Assertions.assertThatThrownBy(
+            () -> scalarSql("SELECT system.hours(date('1969-12-31'), 
date('1969-12-31'))"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'hours' cannot process input: (date, date): Wrong number 
of inputs");
   }
 
   @Test
   public void testInvalidInputTypes() {
-    AssertHelpers.assertThrows(
-        "Int type should not be coercible to timestamp",
-        AnalysisException.class,
-        "Function 'hours' cannot process input: (int): Expected value to be 
timestamp",
-        () -> scalarSql("SELECT system.hours(1)"));
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.hours(1)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'hours' cannot process input: (int): Expected value to 
be timestamp");
 
-    AssertHelpers.assertThrows(
-        "Long type should not be coercible to timestamp",
-        AnalysisException.class,
-        "Function 'hours' cannot process input: (bigint): Expected value to be 
timestamp",
-        () -> scalarSql("SELECT system.hours(1L)"));
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.hours(1L)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'hours' cannot process input: (bigint): Expected value 
to be timestamp");
   }
 }
diff --git 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkMonthsFunction.java
 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkMonthsFunction.java
index b88bf00256..7d73b4578f 100644
--- 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkMonthsFunction.java
+++ 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkMonthsFunction.java
@@ -18,7 +18,6 @@
  */
 package org.apache.iceberg.spark.sql;
 
-import org.apache.iceberg.AssertHelpers;
 import org.apache.iceberg.spark.SparkTestBaseWithCatalog;
 import org.apache.iceberg.spark.functions.MonthsFunction;
 import org.apache.spark.sql.AnalysisException;
@@ -68,32 +67,29 @@ public class TestSparkMonthsFunction extends 
SparkTestBaseWithCatalog {
 
   @Test
   public void testWrongNumberOfArguments() {
-    AssertHelpers.assertThrows(
-        "Function resolution should not work with zero arguments",
-        AnalysisException.class,
-        "Function 'months' cannot process input: (): Wrong number of inputs",
-        () -> scalarSql("SELECT system.months()"));
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.months()"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'months' cannot process input: (): Wrong number of 
inputs");
 
-    AssertHelpers.assertThrows(
-        "Function resolution should not work with more than one argument",
-        AnalysisException.class,
-        "Function 'months' cannot process input: (date, date): Wrong number of 
inputs",
-        () -> scalarSql("SELECT system.months(date('1969-12-31'), 
date('1969-12-31'))"));
+    Assertions.assertThatThrownBy(
+            () -> scalarSql("SELECT system.months(date('1969-12-31'), 
date('1969-12-31'))"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'months' cannot process input: (date, date): Wrong 
number of inputs");
   }
 
   @Test
   public void testInvalidInputTypes() {
-    AssertHelpers.assertThrows(
-        "Int type should not be coercible to date/timestamp",
-        AnalysisException.class,
-        "Function 'months' cannot process input: (int): Expected value to be 
date or timestamp",
-        () -> scalarSql("SELECT system.months(1)"));
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.months(1)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'months' cannot process input: (int): Expected value to 
be date or timestamp");
 
-    AssertHelpers.assertThrows(
-        "Long type should not be coercible to date/timestamp",
-        AnalysisException.class,
-        "Function 'months' cannot process input: (bigint): Expected value to 
be date or timestamp",
-        () -> scalarSql("SELECT system.months(1L)"));
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.months(1L)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'months' cannot process input: (bigint): Expected value 
to be date or timestamp");
   }
 
   @Test
diff --git 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkTruncateFunction.java
 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkTruncateFunction.java
index f21544fcdf..7d3f360f88 100644
--- 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkTruncateFunction.java
+++ 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkTruncateFunction.java
@@ -20,7 +20,6 @@ package org.apache.iceberg.spark.sql;
 
 import java.math.BigDecimal;
 import java.nio.charset.StandardCharsets;
-import org.apache.iceberg.AssertHelpers;
 import org.apache.iceberg.relocated.com.google.common.io.BaseEncoding;
 import org.apache.iceberg.spark.SparkTestBaseWithCatalog;
 import org.apache.spark.sql.AnalysisException;
@@ -298,95 +297,92 @@ public class TestSparkTruncateFunction extends 
SparkTestBaseWithCatalog {
 
   @Test
   public void testWrongNumberOfArguments() {
-    AssertHelpers.assertThrows(
-        "Function resolution should not work with zero arguments",
-        AnalysisException.class,
-        "Function 'truncate' cannot process input: (): Wrong number of inputs 
(expected width and value)",
-        () -> scalarSql("SELECT system.truncate()"));
-
-    AssertHelpers.assertThrows(
-        "Function resolution should not work with only one argument",
-        AnalysisException.class,
-        "Function 'truncate' cannot process input: (int): Wrong number of 
inputs (expected width and value)",
-        () -> scalarSql("SELECT system.truncate(1)"));
-
-    AssertHelpers.assertThrows(
-        "Function resolution should not work with more than two arguments",
-        AnalysisException.class,
-        "Function 'truncate' cannot process input: (int, bigint, int): Wrong 
number of inputs (expected width and value)",
-        () -> scalarSql("SELECT system.truncate(1, 1L, 1)"));
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.truncate()"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'truncate' cannot process input: (): Wrong number of 
inputs (expected width and value)");
+
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.truncate(1)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'truncate' cannot process input: (int): Wrong number of 
inputs (expected width and value)");
+
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.truncate(1, 
1L, 1)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'truncate' cannot process input: (int, bigint, int): 
Wrong number of inputs (expected width and value)");
   }
 
   @Test
   public void testInvalidTypesCannotBeUsedForWidth() {
-    AssertHelpers.assertThrows(
-        "Decimal type should not be coercible to the width field",
-        AnalysisException.class,
-        "Function 'truncate' cannot process input: (decimal(9,2), int): 
Expected truncation width to be tinyint, shortint or int",
-        () -> scalarSql("SELECT system.truncate(CAST('12.34' as DECIMAL(9, 
2)), 10)"));
-
-    AssertHelpers.assertThrows(
-        "String type should not be coercible to the width field",
-        AnalysisException.class,
-        "Function 'truncate' cannot process input: (string, int): Expected 
truncation width to be tinyint, shortint or int",
-        () -> scalarSql("SELECT system.truncate('5', 10)"));
-
-    AssertHelpers.assertThrows(
-        "Interval year to month type should not be coercible to the width 
field",
-        AnalysisException.class,
-        "Function 'truncate' cannot process input: (interval year to month, 
int): Expected truncation width to be tinyint, shortint or int",
-        () -> scalarSql("SELECT system.truncate(INTERVAL '100-00' YEAR TO 
MONTH, 10)"));
-
-    AssertHelpers.assertThrows(
-        "Interval day-time type should not be coercible to the width field",
-        AnalysisException.class,
-        "Function 'truncate' cannot process input: (interval day to second, 
int): Expected truncation width to be tinyint, shortint or int",
-        () -> scalarSql("SELECT system.truncate(CAST('11 23:4:0' AS INTERVAL 
DAY TO SECOND), 10)"));
+    Assertions.assertThatThrownBy(
+            () -> scalarSql("SELECT system.truncate(CAST('12.34' as DECIMAL(9, 
2)), 10)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'truncate' cannot process input: (decimal(9,2), int): 
Expected truncation width to be tinyint, shortint or int");
+
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.truncate('5', 
10)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'truncate' cannot process input: (string, int): Expected 
truncation width to be tinyint, shortint or int");
+
+    Assertions.assertThatThrownBy(
+            () -> scalarSql("SELECT system.truncate(INTERVAL '100-00' YEAR TO 
MONTH, 10)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'truncate' cannot process input: (interval year to 
month, int): Expected truncation width to be tinyint, shortint or int");
+
+    Assertions.assertThatThrownBy(
+            () ->
+                scalarSql(
+                    "SELECT system.truncate(CAST('11 23:4:0' AS INTERVAL DAY 
TO SECOND), 10)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'truncate' cannot process input: (interval day to 
second, int): Expected truncation width to be tinyint, shortint or int");
   }
 
   @Test
   public void testInvalidTypesForTruncationColumn() {
-    AssertHelpers.assertThrows(
-        "FLoat type should not be truncatable",
-        AnalysisException.class,
-        "Function 'truncate' cannot process input: (int, float): Expected 
truncation col to be tinyint, shortint, int, bigint, decimal, string, or 
binary",
-        () -> scalarSql("SELECT system.truncate(10, cast(12.3456 as float))"));
-
-    AssertHelpers.assertThrows(
-        "Double type should not be truncatable",
-        AnalysisException.class,
-        "Function 'truncate' cannot process input: (int, double): Expected 
truncation col to be tinyint, shortint, int, bigint, decimal, string, or 
binary",
-        () -> scalarSql("SELECT system.truncate(10, cast(12.3456 as 
double))"));
-
-    AssertHelpers.assertThrows(
-        "Boolean type should not be truncatable",
-        AnalysisException.class,
-        "Function 'truncate' cannot process input: (int, boolean): Expected 
truncation col to be tinyint, shortint, int, bigint, decimal, string, or 
binary",
-        () -> scalarSql("SELECT system.truncate(10, true)"));
-
-    AssertHelpers.assertThrows(
-        "Map types should not be truncatable",
-        AnalysisException.class,
-        "Function 'truncate' cannot process input: (int, map<int,int>): 
Expected truncation col to be tinyint, shortint, int, bigint, decimal, string, 
or binary",
-        () -> scalarSql("SELECT system.truncate(10, map(1, 1))"));
-
-    AssertHelpers.assertThrows(
-        "Array types should not be truncatable",
-        AnalysisException.class,
-        "Function 'truncate' cannot process input: (int, array<bigint>): 
Expected truncation col to be tinyint, shortint, int, bigint, decimal, string, 
or binary",
-        () -> scalarSql("SELECT system.truncate(10, array(1L))"));
-
-    AssertHelpers.assertThrows(
-        "Interval year-to-month type should not be truncatable",
-        AnalysisException.class,
-        "Function 'truncate' cannot process input: (int, interval year to 
month): Expected truncation col to be tinyint, shortint, int, bigint, decimal, 
string, or binary",
-        () -> scalarSql("SELECT system.truncate(10, INTERVAL '100-00' YEAR TO 
MONTH)"));
-
-    AssertHelpers.assertThrows(
-        "Interval day-time type should not be truncatable",
-        AnalysisException.class,
-        "Function 'truncate' cannot process input: (int, interval day to 
second): Expected truncation col to be tinyint, shortint, int, bigint, decimal, 
string, or binary",
-        () -> scalarSql("SELECT system.truncate(10, CAST('11 23:4:0' AS 
INTERVAL DAY TO SECOND))"));
+    Assertions.assertThatThrownBy(
+            () -> scalarSql("SELECT system.truncate(10, cast(12.3456 as 
float))"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'truncate' cannot process input: (int, float): Expected 
truncation col to be tinyint, shortint, int, bigint, decimal, string, or 
binary");
+
+    Assertions.assertThatThrownBy(
+            () -> scalarSql("SELECT system.truncate(10, cast(12.3456 as 
double))"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'truncate' cannot process input: (int, double): Expected 
truncation col to be tinyint, shortint, int, bigint, decimal, string, or 
binary");
+
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.truncate(10, 
true)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'truncate' cannot process input: (int, boolean): 
Expected truncation col to be tinyint, shortint, int, bigint, decimal, string, 
or binary");
+
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.truncate(10, 
map(1, 1))"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'truncate' cannot process input: (int, map<int,int>): 
Expected truncation col to be tinyint, shortint, int, bigint, decimal, string, 
or binary");
+
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.truncate(10, 
array(1L))"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'truncate' cannot process input: (int, array<bigint>): 
Expected truncation col to be tinyint, shortint, int, bigint, decimal, string, 
or binary");
+
+    Assertions.assertThatThrownBy(
+            () -> scalarSql("SELECT system.truncate(10, INTERVAL '100-00' YEAR 
TO MONTH)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'truncate' cannot process input: (int, interval year to 
month): Expected truncation col to be tinyint, shortint, int, bigint, decimal, 
string, or binary");
+
+    Assertions.assertThatThrownBy(
+            () ->
+                scalarSql(
+                    "SELECT system.truncate(10, CAST('11 23:4:0' AS INTERVAL 
DAY TO SECOND))"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'truncate' cannot process input: (int, interval day to 
second): Expected truncation col to be tinyint, shortint, int, bigint, decimal, 
string, or binary");
   }
 
   @Test
diff --git 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkYearsFunction.java
 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkYearsFunction.java
index d4676716a6..32b9e6a27e 100644
--- 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkYearsFunction.java
+++ 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestSparkYearsFunction.java
@@ -18,7 +18,6 @@
  */
 package org.apache.iceberg.spark.sql;
 
-import org.apache.iceberg.AssertHelpers;
 import org.apache.iceberg.spark.SparkTestBaseWithCatalog;
 import org.apache.iceberg.spark.functions.YearsFunction;
 import org.apache.spark.sql.AnalysisException;
@@ -70,32 +69,29 @@ public class TestSparkYearsFunction extends 
SparkTestBaseWithCatalog {
 
   @Test
   public void testWrongNumberOfArguments() {
-    AssertHelpers.assertThrows(
-        "Function resolution should not work with zero arguments",
-        AnalysisException.class,
-        "Function 'years' cannot process input: (): Wrong number of inputs",
-        () -> scalarSql("SELECT system.years()"));
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.years()"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'years' cannot process input: (): Wrong number of 
inputs");
 
-    AssertHelpers.assertThrows(
-        "Function resolution should not work with more than one argument",
-        AnalysisException.class,
-        "Function 'years' cannot process input: (date, date): Wrong number of 
inputs",
-        () -> scalarSql("SELECT system.years(date('1969-12-31'), 
date('1969-12-31'))"));
+    Assertions.assertThatThrownBy(
+            () -> scalarSql("SELECT system.years(date('1969-12-31'), 
date('1969-12-31'))"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'years' cannot process input: (date, date): Wrong number 
of inputs");
   }
 
   @Test
   public void testInvalidInputTypes() {
-    AssertHelpers.assertThrows(
-        "Int type should not be coercible to date/timestamp",
-        AnalysisException.class,
-        "Function 'years' cannot process input: (int): Expected value to be 
date or timestamp",
-        () -> scalarSql("SELECT system.years(1)"));
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.years(1)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'years' cannot process input: (int): Expected value to 
be date or timestamp");
 
-    AssertHelpers.assertThrows(
-        "Long type should not be coercible to date/timestamp",
-        AnalysisException.class,
-        "Function 'years' cannot process input: (bigint): Expected value to be 
date or timestamp",
-        () -> scalarSql("SELECT system.years(1L)"));
+    Assertions.assertThatThrownBy(() -> scalarSql("SELECT system.years(1L)"))
+        .isInstanceOf(AnalysisException.class)
+        .hasMessageStartingWith(
+            "Function 'years' cannot process input: (bigint): Expected value 
to be date or timestamp");
   }
 
   @Test
diff --git 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestTimestampWithoutZone.java
 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestTimestampWithoutZone.java
index 51b8d255a9..d5061f4958 100644
--- 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestTimestampWithoutZone.java
+++ 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/TestTimestampWithoutZone.java
@@ -23,7 +23,6 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
-import org.apache.iceberg.AssertHelpers;
 import org.apache.iceberg.Schema;
 import org.apache.iceberg.Table;
 import org.apache.iceberg.catalog.TableIdentifier;
@@ -37,6 +36,7 @@ import org.apache.iceberg.spark.SparkUtil;
 import org.apache.iceberg.types.Type;
 import org.apache.iceberg.types.Types;
 import org.apache.spark.sql.util.CaseInsensitiveStringMap;
+import org.assertj.core.api.Assertions;
 import org.joda.time.DateTime;
 import org.junit.After;
 import org.junit.Assert;
@@ -95,14 +95,10 @@ public class TestTimestampWithoutZone extends 
SparkCatalogTestBase {
 
   @Test
   public void testWriteTimestampWithoutZoneError() {
-    AssertHelpers.assertThrows(
-        String.format(
-            "Write operation performed on a timestamp without timezone field 
while "
-                + "'%s' set to false should throw exception",
-            SparkSQLProperties.HANDLE_TIMESTAMP_WITHOUT_TIMEZONE),
-        IllegalArgumentException.class,
-        SparkUtil.TIMESTAMP_WITHOUT_TIMEZONE_ERROR,
-        () -> sql("INSERT INTO %s VALUES %s", tableName, 
rowToSqlValues(values)));
+    Assertions.assertThatThrownBy(
+            () -> sql("INSERT INTO %s VALUES %s", tableName, 
rowToSqlValues(values)))
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessage(SparkUtil.TIMESTAMP_WITHOUT_TIMEZONE_ERROR);
   }
 
   @Test
diff --git 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/UnpartitionedWritesTestBase.java
 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/UnpartitionedWritesTestBase.java
index 71089ebfd7..58918249d8 100644
--- 
a/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/UnpartitionedWritesTestBase.java
+++ 
b/spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/sql/UnpartitionedWritesTestBase.java
@@ -20,7 +20,6 @@ package org.apache.iceberg.spark.sql;
 
 import java.util.List;
 import java.util.Map;
-import org.apache.iceberg.AssertHelpers;
 import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
 import org.apache.iceberg.spark.SparkCatalogTestBase;
 import org.apache.iceberg.spark.source.SimpleRecord;
@@ -28,6 +27,7 @@ import org.apache.spark.sql.Dataset;
 import org.apache.spark.sql.Row;
 import org.apache.spark.sql.catalyst.analysis.NoSuchTableException;
 import org.apache.spark.sql.functions;
+import org.assertj.core.api.Assertions;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Assume;
@@ -97,11 +97,12 @@ public abstract class UnpartitionedWritesTestBase extends 
SparkCatalogTestBase {
     Assume.assumeTrue(tableName.equals(commitTarget()));
     long snapshotId = 
validationCatalog.loadTable(tableIdent).currentSnapshot().snapshotId();
     String prefix = "snapshot_id_";
-    AssertHelpers.assertThrows(
-        "Should not be able to insert into a table at a specific snapshot",
-        IllegalArgumentException.class,
-        "Cannot write to table at a specific snapshot",
-        () -> sql("INSERT INTO %s.%s VALUES (4, 'd'), (5, 'e')", tableName, 
prefix + snapshotId));
+
+    Assertions.assertThatThrownBy(
+            () ->
+                sql("INSERT INTO %s.%s VALUES (4, 'd'), (5, 'e')", tableName, 
prefix + snapshotId))
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessageStartingWith("Cannot write to table at a specific 
snapshot");
   }
 
   @Test
@@ -109,14 +110,14 @@ public abstract class UnpartitionedWritesTestBase extends 
SparkCatalogTestBase {
     Assume.assumeTrue(tableName.equals(commitTarget()));
     long snapshotId = 
validationCatalog.loadTable(tableIdent).currentSnapshot().snapshotId();
     String prefix = "snapshot_id_";
-    AssertHelpers.assertThrows(
-        "Should not be able to insert into a table at a specific snapshot",
-        IllegalArgumentException.class,
-        "Cannot write to table at a specific snapshot",
-        () ->
-            sql(
-                "INSERT OVERWRITE %s.%s VALUES (4, 'd'), (5, 'e')",
-                tableName, prefix + snapshotId));
+
+    Assertions.assertThatThrownBy(
+            () ->
+                sql(
+                    "INSERT OVERWRITE %s.%s VALUES (4, 'd'), (5, 'e')",
+                    tableName, prefix + snapshotId))
+        .isInstanceOf(IllegalArgumentException.class)
+        .hasMessageStartingWith("Cannot write to table at a specific 
snapshot");
   }
 
   @Test

Reply via email to