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

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


The following commit(s) were added to refs/heads/master by this push:
     new e0fed5bfefa [FLINK-40466][table] Refactor defining table arguments in 
PTF Test Harness for more complex table arguments (#29018)
e0fed5bfefa is described below

commit e0fed5bfefafa4ab732730494629184c00ee8b82
Author: Mika Naylor <[email protected]>
AuthorDate: Thu Sep 3 20:50:49 2026 +0200

    [FLINK-40466][table] Refactor defining table arguments in PTF Test Harness 
for more complex table arguments (#29018)
---
 docs/content.zh/docs/dev/table/functions/ptfs.md   | 111 +++-
 docs/content/docs/dev/table/functions/ptfs.md      | 111 +++-
 .../functions/ProcessTableFunctionTestHarness.java | 145 +++--
 .../ProcessTableFunctionTestHarnessTest.java       | 659 +++++++++++++++------
 4 files changed, 708 insertions(+), 318 deletions(-)

diff --git a/docs/content.zh/docs/dev/table/functions/ptfs.md 
b/docs/content.zh/docs/dev/table/functions/ptfs.md
index 96bd2dca353..5e7289e2ee7 100644
--- a/docs/content.zh/docs/dev/table/functions/ptfs.md
+++ b/docs/content.zh/docs/dev/table/functions/ptfs.md
@@ -2056,6 +2056,7 @@ import org.apache.flink.table.annotation.*;
 import org.apache.flink.table.api.DataTypes;
 import org.apache.flink.table.functions.ProcessTableFunction;
 import 
org.apache.flink.table.runtime.functions.ProcessTableFunctionTestHarness;
+import 
org.apache.flink.table.runtime.functions.ProcessTableFunctionTestHarness.TableArgument;
 import org.apache.flink.types.Row;
 import org.junit.jupiter.api.Test;
 
@@ -2077,7 +2078,10 @@ public class DoublePTF extends ProcessTableFunction<Row> 
{
 void testDoublePTF() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(DoublePTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<value INT>"))
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<value INT>"))
+            .build())
     .build()) {
 
     harness.processElement(Row.of(5));
@@ -2099,7 +2103,7 @@ void testDoublePTF() throws Exception {
 
 #### Testing Row-Semantic Tables
 
-Use `.withTableArgument()` to configure the input table schema:
+Use `TableArgument.forName(name).type(...)` to configure the input table 
schema:
 
 {{< tabs "row-semantic" >}}
 {{< tab "Java" >}}
@@ -2114,7 +2118,10 @@ public class PassthroughPTF extends 
ProcessTableFunction<Integer> {
 void testPassthrough() throws Exception {
   try (ProcessTableFunctionTestHarness<Integer> harness =
     ProcessTableFunctionTestHarness.ofClass(PassthroughPTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<value INT>"))
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<value INT>"))
+            .build())
     .build()) {
 
     harness.processElement(Row.of(42));
@@ -2130,7 +2137,7 @@ void testPassthrough() throws Exception {
 
 #### Testing Set-Semantic Tables with Partitioning
 
-For `SET_SEMANTIC_TABLE`, use `.withPartitionBy()` to configure partition 
columns:
+For `SET_SEMANTIC_TABLE`, use `TableArgument.Builder#partitionBy()` to 
configure partition columns:
 
 {{< tabs "set-semantic" >}}
 {{< tab "Java" >}}
@@ -2147,8 +2154,11 @@ public class PartitionedPTF extends 
ProcessTableFunction<Row> {
 void testPartitionedPTF() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(PartitionedPTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<key STRING, value INT>"))
-    .withPartitionBy("input", "key")
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<key STRING, value INT>"))
+            .partitionBy("key")
+            .build())
     .build()) {
 
     harness.processElement(Row.of("A", 10));
@@ -2188,10 +2198,16 @@ public class JoinPTF extends ProcessTableFunction<Row> {
 void testMultiTable() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(JoinPTF.class)
-    .withTableArgument("left", DataTypes.of("ROW<id INT, name STRING>"))
-    .withPartitionBy("left", "id")
-    .withTableArgument("right", DataTypes.of("ROW<id INT, city STRING>"))
-    .withPartitionBy("right", "id")
+    .withTableArgument(
+        TableArgument.forName("left")
+            .type(DataTypes.of("ROW<id INT, name STRING>"))
+            .partitionBy("id")
+            .build())
+    .withTableArgument(
+        TableArgument.forName("right")
+            .type(DataTypes.of("ROW<id INT, city STRING>"))
+            .partitionBy("id")
+            .build())
     .build()) {
 
     // Use processElementForTable() to target specific tables
@@ -2230,7 +2246,10 @@ public class FilterPTF extends ProcessTableFunction<Row> 
{
 void testFilter() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(FilterPTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<value INT>"))
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<value INT>"))
+            .build())
     .withScalarArgument("threshold", 50) // Configure scalar value
     .build()) {
 
@@ -2319,8 +2338,11 @@ public class StatefulPTF extends 
ProcessTableFunction<Row> {
 void testWithState() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(StatefulPTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<name STRING, value INT>"))
-    .withPartitionBy("input", "name")
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<name STRING, value INT>"))
+            .partitionBy("name")
+            .build())
     .build()) {
 
     harness.processElement(Row.of("Alice", 10));
@@ -2362,8 +2384,11 @@ void testWithInitialState() throws Exception {
 
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(StatefulPTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<name STRING, value INT>"))
-    .withPartitionBy("input", "name")
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<name STRING, value INT>"))
+            .partitionBy("name")
+            .build())
     // Initial state is set per partition key
     .withInitialStateForKey("valueState", Row.of("Alice"), initialValue)
     .withInitialStateForKey("rowState", Row.of("Alice"), initialRow)
@@ -2391,8 +2416,11 @@ inspect state during tests:
 void testStateIntrospection() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(StatefulPTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<name STRING, value INT>"))
-    .withPartitionBy("input", "name")
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<name STRING, value INT>"))
+            .partitionBy("name")
+            .build())
     .build()) {
 
     harness.processElement(Row.of("Alice", 10));
@@ -2439,8 +2467,11 @@ modify state during tests:
 void testStateMutation() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(StatefulPTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<name STRING, value INT>"))
-    .withPartitionBy("input", "name")
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<name STRING, value INT>"))
+            .partitionBy("name")
+            .build())
     .build()) {
 
     harness.processElement(Row.of("Alice", 10));
@@ -2496,9 +2527,11 @@ public class TimerPTF extends ProcessTableFunction<Row> {
 void testTimerRegistrationAndFiring() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
       ProcessTableFunctionTestHarness.ofClass(TimerPTF.class)
-          .withTableArgument("input",
-              DataTypes.of("ROW<partition STRING, name STRING, ts 
TIMESTAMP(3)>"))
-          .withPartitionBy("input", "partition")
+          .withTableArgument(
+              TableArgument.forName("input")
+                  .type(DataTypes.of("ROW<partition STRING, name STRING, ts 
TIMESTAMP(3)>"))
+                  .partitionBy("partition")
+                  .build())
           .withOnTimeColumn("ts")
           .build()) {
 
@@ -2562,9 +2595,11 @@ public class TimerWithStatePTF extends 
ProcessTableFunction<Row> {
 void testTimerWithState() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
       ProcessTableFunctionTestHarness.ofClass(TimerWithStatePTF.class)
-          .withTableArgument("input",
-              DataTypes.of("ROW<partition STRING, ts TIMESTAMP(3)>"))
-          .withPartitionBy("input", "partition")
+          .withTableArgument(
+              TableArgument.forName("input")
+                  .type(DataTypes.of("ROW<partition STRING, ts TIMESTAMP(3)>"))
+                  .partitionBy("partition")
+                  .build())
           .withOnTimeColumn("ts")
           .build()) {
 
@@ -2587,7 +2622,8 @@ void testTimerWithState() throws Exception {
 
 #### Optional Partitioning
 
-For PTFs with `OPTIONAL_PARTITION_BY`, you can omit `withPartitionBy()` during 
harness setup. The
+For PTFs with `OPTIONAL_PARTITION_BY`, you can omit `.partitionBy(...)` on 
`TableArgument.Builder`
+during harness setup. The
 harness executes the function as if it had a parallelism of 1, with the 
default `Row.of()` key,
 so all data is routed through the same function instance. Use `Row.of()` to 
access state:
 
@@ -2614,7 +2650,10 @@ public class GlobalCountPTF extends 
ProcessTableFunction<Row> {
 void testOptionalPartitionWithoutPartitionBy() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
       ProcessTableFunctionTestHarness.ofClass(GlobalCountPTF.class)
-      .withTableArgument("input", DataTypes.of("ROW<key STRING, value INT>"))
+      .withTableArgument(
+          TableArgument.forName("input")
+              .type(DataTypes.of("ROW<key STRING, value INT>"))
+              .build())
       .build()) {
 
       harness.processElement(Row.of("A", 10));
@@ -2652,7 +2691,10 @@ public static class DoublePTF extends 
ProcessTableFunction<Row> {
 void testBuilderType() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(DoublePTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<value INT>"))
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<value INT>"))
+            .build())
     .build()) {
 
     harness.processElement(Row.of(5));
@@ -2684,7 +2726,10 @@ public class CustomerPTF extends 
ProcessTableFunction<Customer> {
 void testPOJO() throws Exception {
   try (ProcessTableFunctionTestHarness<Customer> harness =
       ProcessTableFunctionTestHarness.ofClass(CustomerPTF.class)
-          .withTableArgument("c", DataTypes.of(Customer.class))
+          .withTableArgument(
+              TableArgument.forName("c")
+                  .type(DataTypes.of(Customer.class))
+                  .build())
           .build()) {
 
     harness.processElement(Row.of(30, "Alice"));
@@ -2725,9 +2770,11 @@ public class PartitionedAtomicPTF extends 
ProcessTableFunction<Integer> {
 void testAtomicOutputFunctionOutput() throws Exception {
   try (ProcessTableFunctionTestHarness<Integer> harness =
       ProcessTableFunctionTestHarness.ofClass(PartitionedAtomicPTF.class)
-          .withTableArgument("input",
-              DataTypes.of("ROW<key STRING, value INT, ts TIMESTAMP(3)>"))
-          .withPartitionBy("input", "key")
+          .withTableArgument(
+              TableArgument.forName("input")
+                  .type(DataTypes.of("ROW<key STRING, value INT, ts 
TIMESTAMP(3)>"))
+                  .partitionBy("key")
+                  .build())
           .withOnTimeColumn("ts")
           .build()) {
 
diff --git a/docs/content/docs/dev/table/functions/ptfs.md 
b/docs/content/docs/dev/table/functions/ptfs.md
index 6fd3efd8fa9..0939d1fdfb8 100644
--- a/docs/content/docs/dev/table/functions/ptfs.md
+++ b/docs/content/docs/dev/table/functions/ptfs.md
@@ -2059,6 +2059,7 @@ import org.apache.flink.table.annotation.*;
 import org.apache.flink.table.api.DataTypes;
 import org.apache.flink.table.functions.ProcessTableFunction;
 import 
org.apache.flink.table.runtime.functions.ProcessTableFunctionTestHarness;
+import 
org.apache.flink.table.runtime.functions.ProcessTableFunctionTestHarness.TableArgument;
 import org.apache.flink.types.Row;
 import org.junit.jupiter.api.Test;
 
@@ -2080,7 +2081,10 @@ public class DoublePTF extends ProcessTableFunction<Row> 
{
 void testDoublePTF() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(DoublePTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<value INT>"))
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<value INT>"))
+            .build())
     .build()) {
 
     harness.processElement(Row.of(5));
@@ -2102,7 +2106,7 @@ void testDoublePTF() throws Exception {
 
 #### Testing Row-Semantic Tables
 
-Use `.withTableArgument()` to configure the input table schema:
+Use `TableArgument.forName(name).type(...)` to configure the input table 
schema:
 
 {{< tabs "row-semantic" >}}
 {{< tab "Java" >}}
@@ -2117,7 +2121,10 @@ public class PassthroughPTF extends 
ProcessTableFunction<Integer> {
 void testPassthrough() throws Exception {
   try (ProcessTableFunctionTestHarness<Integer> harness =
     ProcessTableFunctionTestHarness.ofClass(PassthroughPTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<value INT>"))
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<value INT>"))
+            .build())
     .build()) {
 
     harness.processElement(Row.of(42));
@@ -2133,7 +2140,7 @@ void testPassthrough() throws Exception {
 
 #### Testing Set-Semantic Tables with Partitioning
 
-For `SET_SEMANTIC_TABLE`, use `.withPartitionBy()` to configure partition 
columns:
+For `SET_SEMANTIC_TABLE`, use `TableArgument.Builder#partitionBy()` to 
configure partition columns:
 
 {{< tabs "set-semantic" >}}
 {{< tab "Java" >}}
@@ -2150,8 +2157,11 @@ public class PartitionedPTF extends 
ProcessTableFunction<Row> {
 void testPartitionedPTF() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(PartitionedPTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<key STRING, value INT>"))
-    .withPartitionBy("input", "key")
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<key STRING, value INT>"))
+            .partitionBy("key")
+            .build())
     .build()) {
 
     harness.processElement(Row.of("A", 10));
@@ -2191,10 +2201,16 @@ public class JoinPTF extends ProcessTableFunction<Row> {
 void testMultiTable() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(JoinPTF.class)
-    .withTableArgument("left", DataTypes.of("ROW<id INT, name STRING>"))
-    .withPartitionBy("left", "id")
-    .withTableArgument("right", DataTypes.of("ROW<id INT, city STRING>"))
-    .withPartitionBy("right", "id")
+    .withTableArgument(
+        TableArgument.forName("left")
+            .type(DataTypes.of("ROW<id INT, name STRING>"))
+            .partitionBy("id")
+            .build())
+    .withTableArgument(
+        TableArgument.forName("right")
+            .type(DataTypes.of("ROW<id INT, city STRING>"))
+            .partitionBy("id")
+            .build())
     .build()) {
 
     // Use processElementForTable() to target specific tables
@@ -2233,7 +2249,10 @@ public class FilterPTF extends ProcessTableFunction<Row> 
{
 void testFilter() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(FilterPTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<value INT>"))
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<value INT>"))
+            .build())
     .withScalarArgument("threshold", 50) // Configure scalar value
     .build()) {
 
@@ -2322,8 +2341,11 @@ public class StatefulPTF extends 
ProcessTableFunction<Row> {
 void testWithState() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(StatefulPTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<name STRING, value INT>"))
-    .withPartitionBy("input", "name")
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<name STRING, value INT>"))
+            .partitionBy("name")
+            .build())
     .build()) {
 
     harness.processElement(Row.of("Alice", 10));
@@ -2365,8 +2387,11 @@ void testWithInitialState() throws Exception {
 
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(StatefulPTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<name STRING, value INT>"))
-    .withPartitionBy("input", "name")
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<name STRING, value INT>"))
+            .partitionBy("name")
+            .build())
     // Initial state is set per partition key
     .withInitialStateForKey("valueState", Row.of("Alice"), initialValue)
     .withInitialStateForKey("rowState", Row.of("Alice"), initialRow)
@@ -2394,8 +2419,11 @@ inspect state during tests:
 void testStateIntrospection() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(StatefulPTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<name STRING, value INT>"))
-    .withPartitionBy("input", "name")
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<name STRING, value INT>"))
+            .partitionBy("name")
+            .build())
     .build()) {
 
     harness.processElement(Row.of("Alice", 10));
@@ -2442,8 +2470,11 @@ modify state during tests:
 void testStateMutation() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(StatefulPTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<name STRING, value INT>"))
-    .withPartitionBy("input", "name")
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<name STRING, value INT>"))
+            .partitionBy("name")
+            .build())
     .build()) {
 
     harness.processElement(Row.of("Alice", 10));
@@ -2499,9 +2530,11 @@ public class TimerPTF extends ProcessTableFunction<Row> {
 void testTimerRegistrationAndFiring() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
       ProcessTableFunctionTestHarness.ofClass(TimerPTF.class)
-          .withTableArgument("input",
-              DataTypes.of("ROW<partition STRING, name STRING, ts 
TIMESTAMP(3)>"))
-          .withPartitionBy("input", "partition")
+          .withTableArgument(
+              TableArgument.forName("input")
+                  .type(DataTypes.of("ROW<partition STRING, name STRING, ts 
TIMESTAMP(3)>"))
+                  .partitionBy("partition")
+                  .build())
           .withOnTimeColumn("ts")
           .build()) {
 
@@ -2565,9 +2598,11 @@ public class TimerWithStatePTF extends 
ProcessTableFunction<Row> {
 void testTimerWithState() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
       ProcessTableFunctionTestHarness.ofClass(TimerWithStatePTF.class)
-          .withTableArgument("input",
-              DataTypes.of("ROW<partition STRING, ts TIMESTAMP(3)>"))
-          .withPartitionBy("input", "partition")
+          .withTableArgument(
+              TableArgument.forName("input")
+                  .type(DataTypes.of("ROW<partition STRING, ts TIMESTAMP(3)>"))
+                  .partitionBy("partition")
+                  .build())
           .withOnTimeColumn("ts")
           .build()) {
 
@@ -2590,7 +2625,8 @@ void testTimerWithState() throws Exception {
 
 #### Optional Partitioning
 
-For PTFs with `OPTIONAL_PARTITION_BY`, you can omit `withPartitionBy()` during 
harness setup. The
+For PTFs with `OPTIONAL_PARTITION_BY`, you can omit `.partitionBy(...)` on 
`TableArgument.Builder`
+during harness setup. The
 harness executes the function as if it had a parallelism of 1, with the 
default `Row.of()` key,
 so all data is routed through the same function instance. Use `Row.of()` to 
access state:
 
@@ -2617,7 +2653,10 @@ public class GlobalCountPTF extends 
ProcessTableFunction<Row> {
 void testOptionalPartitionWithoutPartitionBy() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
       ProcessTableFunctionTestHarness.ofClass(GlobalCountPTF.class)
-      .withTableArgument("input", DataTypes.of("ROW<key STRING, value INT>"))
+      .withTableArgument(
+          TableArgument.forName("input")
+              .type(DataTypes.of("ROW<key STRING, value INT>"))
+              .build())
       .build()) {
 
       harness.processElement(Row.of("A", 10));
@@ -2655,7 +2694,10 @@ public static class DoublePTF extends 
ProcessTableFunction<Row> {
 void testBuilderType() throws Exception {
   try (ProcessTableFunctionTestHarness<Row> harness =
     ProcessTableFunctionTestHarness.ofClass(DoublePTF.class)
-    .withTableArgument("input", DataTypes.of("ROW<value INT>"))
+    .withTableArgument(
+        TableArgument.forName("input")
+            .type(DataTypes.of("ROW<value INT>"))
+            .build())
     .build()) {
 
     harness.processElement(Row.of(5));
@@ -2687,7 +2729,10 @@ public class CustomerPTF extends 
ProcessTableFunction<Customer> {
 void testPOJO() throws Exception {
   try (ProcessTableFunctionTestHarness<Customer> harness =
       ProcessTableFunctionTestHarness.ofClass(CustomerPTF.class)
-          .withTableArgument("c", DataTypes.of(Customer.class))
+          .withTableArgument(
+              TableArgument.forName("c")
+                  .type(DataTypes.of(Customer.class))
+                  .build())
           .build()) {
 
     harness.processElement(Row.of(30, "Alice"));
@@ -2728,9 +2773,11 @@ public class PartitionedAtomicPTF extends 
ProcessTableFunction<Integer> {
 void testAtomicOutputFunctionOutput() throws Exception {
   try (ProcessTableFunctionTestHarness<Integer> harness =
       ProcessTableFunctionTestHarness.ofClass(PartitionedAtomicPTF.class)
-          .withTableArgument("input",
-              DataTypes.of("ROW<key STRING, value INT, ts TIMESTAMP(3)>"))
-          .withPartitionBy("input", "key")
+          .withTableArgument(
+              TableArgument.forName("input")
+                  .type(DataTypes.of("ROW<key STRING, value INT, ts 
TIMESTAMP(3)>"))
+                  .partitionBy("key")
+                  .build())
           .withOnTimeColumn("ts")
           .build()) {
 
diff --git 
a/flink-table/flink-table-test-utils/src/main/java/org/apache/flink/table/runtime/functions/ProcessTableFunctionTestHarness.java
 
b/flink-table/flink-table-test-utils/src/main/java/org/apache/flink/table/runtime/functions/ProcessTableFunctionTestHarness.java
index 00c4d8213c1..42034b08b69 100644
--- 
a/flink-table/flink-table-test-utils/src/main/java/org/apache/flink/table/runtime/functions/ProcessTableFunctionTestHarness.java
+++ 
b/flink-table/flink-table-test-utils/src/main/java/org/apache/flink/table/runtime/functions/ProcessTableFunctionTestHarness.java
@@ -93,7 +93,10 @@ import static org.apache.flink.util.Preconditions.checkState;
  * <pre>{@code
  * ProcessTableFunctionTestHarness<Row> harness =
  *     ProcessTableFunctionTestHarness.ofClass(MyPTF.class)
- *         .withTableArgument("input", DataTypes.of("ROW<id INT, name 
STRING>"))
+ *         .withTableArgument(
+ *             TableArgument.forName("input")
+ *                 .type(DataTypes.of("ROW<id INT, name STRING>"))
+ *                 .build())
  *         .withScalarArgument("threshold", 100)
  *         .build();
  *
@@ -1035,6 +1038,72 @@ public class ProcessTableFunctionTestHarness<OUT> 
implements AutoCloseable {
                 new RowType(structuredType.isNullable(), rowFields));
     }
 
+    /**
+     * Configuration for a single named table argument.
+     *
+     * @see 
ProcessTableFunctionTestHarness.Builder#withTableArgument(TableArgument)
+     */
+    @PublicEvolving
+    public static final class TableArgument {
+        private final String name;
+        @Nullable private final AbstractDataType<?> type;
+        @Nullable private final String[] partitionColumns;
+
+        private TableArgument(Builder builder) {
+            this.name = builder.name;
+            this.type = builder.type;
+            this.partitionColumns = builder.partitionColumns;
+        }
+
+        public static Builder forName(String argumentName) {
+            return new Builder(argumentName);
+        }
+
+        /** Builder for {@link TableArgument}. */
+        public static final class Builder {
+            private final String name;
+            @Nullable private AbstractDataType<?> type;
+            @Nullable private String[] partitionColumns;
+
+            private Builder(String argumentName) {
+                this.name = checkNotNull(argumentName, "argumentName must not 
be null");
+            }
+
+            /**
+             * Configures the schema of this table argument.
+             *
+             * <p>Use this for dynamic tables that receive elements during the 
test. Elements are
+             * provided via {@link 
ProcessTableFunctionTestHarness#processElement(Row)} or {@link
+             * ProcessTableFunctionTestHarness#processElementForTable(String, 
Row)}.
+             *
+             * <p>Omit for structured type arguments whose type can be 
inferred from the PTF's
+             * eval() signature.
+             *
+             * @param dataType The schema/structure of the table
+             */
+            public Builder type(AbstractDataType<?> dataType) {
+                this.type = checkNotNull(dataType, "dataType must not be 
null");
+                return this;
+            }
+
+            /**
+             * Specifies partition columns for a set semantic table.
+             *
+             * @param columnNames The partition column names
+             */
+            public Builder partitionBy(String... columnNames) {
+                checkNotNull(columnNames, "columnNames must not be null");
+                checkArgument(columnNames.length > 0, "Must specify at least 
one column");
+                this.partitionColumns = columnNames;
+                return this;
+            }
+
+            public TableArgument build() {
+                return new TableArgument(this);
+            }
+        }
+    }
+
     /**
      * Builder for {@link ProcessTableFunctionTestHarness}.
      *
@@ -1065,40 +1134,22 @@ public class ProcessTableFunctionTestHarness<OUT> 
implements AutoCloseable {
         // 
---------------------------------------------------------------------
 
         /**
-         * Configures a table argument with its schema (named argument).
-         *
-         * <p>Use this for dynamic tables that receive elements during the 
test. Elements are
-         * provided via {@link #processElement(Row)} or {@link 
#processElementForTable(String,
-         * Row)}.
+         * Configures a table argument.
          *
-         * @param argumentName The table argument name
-         * @param dataType The schema/structure of the table
+         * @param tableArgument The table argument configuration, built via 
{@link
+         *     TableArgument#forName(String)}
          */
-        public Builder<OUT> withTableArgument(String argumentName, 
AbstractDataType<?> dataType) {
-            checkNotNull(argumentName, "argumentName must not be null");
-            checkNotNull(dataType, "dataType must not be null");
+        public Builder<OUT> withTableArgument(TableArgument tableArgument) {
+            checkNotNull(tableArgument, "tableArgument must not be null");
 
-            validateArgumentNotYetConfigured(argumentName);
+            validateArgumentNotYetConfigured(tableArgument.name);
 
-            tableArgs.put(argumentName, new 
TableArgumentConfiguration(dataType));
-            return this;
-        }
-
-        /**
-         * Configures a table argument without an explicit schema.
-         *
-         * <p>Use this for structured type arguments where the type can be 
inferred from the PTF's
-         * eval() signature. For Row arguments, use {@link 
#withTableArgument(String,
-         * AbstractDataType)} with an explicit schema.
-         *
-         * @param argumentName The table argument name
-         */
-        public Builder<OUT> withTableArgument(String argumentName) {
-            checkNotNull(argumentName, "argumentName must not be null");
-
-            validateArgumentNotYetConfigured(argumentName);
-
-            tableArgs.put(argumentName, new TableArgumentConfiguration(null));
+            tableArgs.put(tableArgument.name, new 
TableArgumentConfiguration(tableArgument.type));
+            if (tableArgument.partitionColumns != null) {
+                partitionConfigs.put(
+                        tableArgument.name,
+                        new 
PartitionConfiguration(tableArgument.partitionColumns));
+            }
             return this;
         }
 
@@ -1135,32 +1186,6 @@ public class ProcessTableFunctionTestHarness<OUT> 
implements AutoCloseable {
             return this;
         }
 
-        // 
---------------------------------------------------------------------
-        // Partitioning
-        // 
---------------------------------------------------------------------
-
-        /**
-         * Specifies partition columns for a set semantic table.
-         *
-         * @param argumentName The table argument name
-         * @param columnNames The partition column names
-         * @return This builder
-         */
-        public Builder<OUT> withPartitionBy(String argumentName, String... 
columnNames) {
-            checkNotNull(argumentName, "argumentName must not be null");
-            checkNotNull(columnNames, "columnNames must not be null");
-            checkArgument(columnNames.length > 0, "Must specify at least one 
column");
-
-            if (partitionConfigs.containsKey(argumentName)) {
-                throw new IllegalArgumentException(
-                        "Partition config already exists for: " + 
argumentName);
-            }
-
-            PartitionConfiguration config = new 
PartitionConfiguration(columnNames);
-            partitionConfigs.put(argumentName, config);
-            return this;
-        }
-
         // 
---------------------------------------------------------------------
         // Timer & Watermark Configuration
         // 
---------------------------------------------------------------------
@@ -1855,7 +1880,8 @@ public class ProcessTableFunctionTestHarness<OUT> 
implements AutoCloseable {
                         throw new IllegalStateException(
                                 String.format(
                                         "Table argument '%s' requires explicit 
type configuration. "
-                                                + "Use 
.withTableArgument(\"%s\", DataTypes.of(\"ROW<...>\")) "
+                                                + "Use 
.withTableArgument(TableArgument.forName(\"%s\")"
+                                                + 
".type(DataTypes.of(\"ROW<...>\")).build()) "
                                                 + "to explicitly declare it.",
                                         name, name));
                     }
@@ -1906,7 +1932,8 @@ public class ProcessTableFunctionTestHarness<OUT> 
implements AutoCloseable {
                 throw new IllegalStateException(
                         String.format(
                                 "No partition configuration found for 
SET_SEMANTIC_TABLE argument '%s'. "
-                                        + "Use withPartitionBy(\"%s\", ...) to 
configure partitioning.",
+                                        + "Use 
TableArgument.forName(\"%s\").partitionBy(...) to "
+                                        + "configure partitioning.",
                                 name, name));
             }
 
diff --git 
a/flink-table/flink-table-test-utils/src/test/java/org/apache/flink/table/runtime/functions/ProcessTableFunctionTestHarnessTest.java
 
b/flink-table/flink-table-test-utils/src/test/java/org/apache/flink/table/runtime/functions/ProcessTableFunctionTestHarnessTest.java
index 5041911d051..ef124d2efca 100644
--- 
a/flink-table/flink-table-test-utils/src/test/java/org/apache/flink/table/runtime/functions/ProcessTableFunctionTestHarnessTest.java
+++ 
b/flink-table/flink-table-test-utils/src/test/java/org/apache/flink/table/runtime/functions/ProcessTableFunctionTestHarnessTest.java
@@ -30,6 +30,7 @@ import org.apache.flink.table.api.dataview.MapView;
 import org.apache.flink.table.connector.ChangelogMode;
 import org.apache.flink.table.functions.ProcessTableFunction;
 import org.apache.flink.table.functions.TableSemantics;
+import 
org.apache.flink.table.runtime.functions.ProcessTableFunctionTestHarness.TableArgument;
 import org.apache.flink.types.Row;
 import org.apache.flink.types.RowKind;
 
@@ -453,7 +454,10 @@ class ProcessTableFunctionTestHarnessTest {
                         IllegalArgumentException.class,
                         () -> {
                             
ProcessTableFunctionTestHarness.ofClass(FilterPTF.class)
-                                    .withTableArgument("input", 
DataTypes.of("ROW<value INT>"))
+                                    .withTableArgument(
+                                            TableArgument.forName("input")
+                                                    
.type(DataTypes.of("ROW<value INT>"))
+                                                    .build())
                                     .withScalarArgument("threshold", 50)
                                     .withScalarArgument("threshold", 100);
                         });
@@ -469,9 +473,13 @@ class ProcessTableFunctionTestHarnessTest {
                         () -> {
                             
ProcessTableFunctionTestHarness.ofClass(MultiTableUnionPTF.class)
                                     .withTableArgument(
-                                            "leftTable", DataTypes.of("ROW<id 
INT, name STRING>"))
+                                            TableArgument.forName("leftTable")
+                                                    .type(DataTypes.of("ROW<id 
INT, name STRING>"))
+                                                    .build())
                                     .withTableArgument(
-                                            "leftTable", DataTypes.of("ROW<id 
INT, value INT>"));
+                                            TableArgument.forName("leftTable")
+                                                    .type(DataTypes.of("ROW<id 
INT, value INT>"))
+                                                    .build());
                         });
 
         assertThat(exception.getMessage()).contains("leftTable");
@@ -484,7 +492,10 @@ class ProcessTableFunctionTestHarnessTest {
                         IllegalArgumentException.class,
                         () -> {
                             
ProcessTableFunctionTestHarness.ofClass(FilterPTF.class)
-                                    .withTableArgument("input", 
DataTypes.of("ROW<value INT>"))
+                                    .withTableArgument(
+                                            TableArgument.forName("input")
+                                                    
.type(DataTypes.of("ROW<value INT>"))
+                                                    .build())
                                     .withScalarArgument("input", 42);
                         });
 
@@ -496,7 +507,10 @@ class ProcessTableFunctionTestHarnessTest {
         // We should reject PTFs that use reserved argument name "on_time"
         ProcessTableFunctionTestHarness.Builder harnessBuilder =
                 
ProcessTableFunctionTestHarness.ofClass(InvalidReservedArgOnTimePTF.class)
-                        .withTableArgument("on_time", DataTypes.of("ROW<id 
INT>"));
+                        .withTableArgument(
+                                TableArgument.forName("on_time")
+                                        .type(DataTypes.of("ROW<id INT>"))
+                                        .build());
 
         ValidationException exception =
                 assertThrows(
@@ -515,7 +529,10 @@ class ProcessTableFunctionTestHarnessTest {
         // We should reject PTFs that use reserved argument name "uid"
         ProcessTableFunctionTestHarness.Builder harnessBuilder =
                 
ProcessTableFunctionTestHarness.ofClass(InvalidReservedArgUidPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<id 
INT>"))
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<id INT>"))
+                                        .build())
                         .withScalarArgument("uid", "my-id");
 
         ValidationException exception =
@@ -541,7 +558,10 @@ class ProcessTableFunctionTestHarnessTest {
 
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(ExplicitNamePTF.class)
-                        .withTableArgument("customName", 
DataTypes.of("ROW<value INT>"))
+                        .withTableArgument(
+                                TableArgument.forName("customName")
+                                        .type(DataTypes.of("ROW<value INT>"))
+                                        .build())
                         .build()) {
 
             harness.processElement(Row.of(42));
@@ -628,7 +648,10 @@ class ProcessTableFunctionTestHarnessTest {
         // Verify that invoke() rejects PTFs with table arguments
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(FilterPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<value 
INT>"))
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<value INT>"))
+                                        .build())
                         .withScalarArgument("threshold", 50)
                         .build()) {
 
@@ -648,7 +671,10 @@ class ProcessTableFunctionTestHarnessTest {
         // Test a PTF that uses a scalar parameter
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(FilterPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<value 
INT>"))
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<value INT>"))
+                                        .build())
                         .withScalarArgument("threshold", 50) // Scalar 
argument: threshold = 50
                         .build()) {
 
@@ -674,7 +700,10 @@ class ProcessTableFunctionTestHarnessTest {
                         IllegalStateException.class,
                         () -> {
                             
ProcessTableFunctionTestHarness.ofClass(FilterPTF.class)
-                                    .withTableArgument("input", 
DataTypes.of("ROW<value INT>"))
+                                    .withTableArgument(
+                                            TableArgument.forName("input")
+                                                    
.type(DataTypes.of("ROW<value INT>"))
+                                                    .build())
                                     .withScalarArgument("threshold", 
"not_an_integer")
                                     .build();
                         });
@@ -693,7 +722,10 @@ class ProcessTableFunctionTestHarnessTest {
         // Verify RowKind is preserved through processing (ROW_SEMANTIC_TABLE)
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(PassthroughPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<value 
INT>"))
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<value INT>"))
+                                        .build())
                         .build()) {
 
             harness.processElement(RowKind.INSERT, 10);
@@ -719,8 +751,11 @@ class ProcessTableFunctionTestHarnessTest {
         // Verify PASS_COLUMNS_THROUGH prepends ALL input columns (not just 
partition keys)
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PassColumnsThroughPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<key 
STRING, value INT>"))
-                        .withPartitionBy("input", "key")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<key STRING, 
value INT>"))
+                                        .partitionBy("key")
+                                        .build())
                         .build()) {
 
             harness.processElement(Row.of("A", 10));
@@ -739,7 +774,10 @@ class ProcessTableFunctionTestHarnessTest {
         // Verify OPTIONAL_PARTITION_BY allows omitting partition configuration
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(OptionalPartitionPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<key 
STRING, value INT>"))
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<key STRING, 
value INT>"))
+                                        .build())
                         .build()) {
 
             harness.processElement(Row.of("A", 10));
@@ -760,8 +798,11 @@ class ProcessTableFunctionTestHarnessTest {
         // Verify OPTIONAL_PARTITION_BY still works when partition is 
configured
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(OptionalPartitionPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<key 
STRING, value INT>"))
-                        .withPartitionBy("input", "key")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<key STRING, 
value INT>"))
+                                        .partitionBy("key")
+                                        .build())
                         .build()) {
 
             harness.processElement(Row.of("A", 10));
@@ -781,7 +822,10 @@ class ProcessTableFunctionTestHarnessTest {
     void testOptionalPartitionByWithStateNoPartition() throws Exception {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(StatefulOptionalPartitionPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<key 
STRING, value INT>"))
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<key STRING, 
value INT>"))
+                                        .build())
                         .build()) {
 
             harness.processElement(Row.of("A", 10));
@@ -804,8 +848,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testOptionalPartitionByWithStateAndPartition() throws Exception {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(StatefulOptionalPartitionPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<key 
STRING, value INT>"))
-                        .withPartitionBy("input", "key")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<key STRING, 
value INT>"))
+                                        .partitionBy("key")
+                                        .build())
                         .build()) {
 
             harness.processElement(Row.of("A", 10));
@@ -835,7 +882,10 @@ class ProcessTableFunctionTestHarnessTest {
 
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(StatefulOptionalPartitionPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<key 
STRING, value INT>"))
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<key STRING, 
value INT>"))
+                                        .build())
                         .withInitialStateForKey("state", Row.of(), 
initialState)
                         .build()) {
 
@@ -872,7 +922,10 @@ class ProcessTableFunctionTestHarnessTest {
         // Test what happens when Row field order differs from DataType schema 
order
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(UserValuePassthroughPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<user 
STRING, value INT>"))
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<user STRING, 
value INT>"))
+                                        .build())
                         .build()) {
 
             Row rowA = Row.withNames();
@@ -897,7 +950,10 @@ class ProcessTableFunctionTestHarnessTest {
         // Verify that type mismatches are caught when Row values don't match 
schema types
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(UserValuePassthroughPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<user 
STRING, value INT>"))
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<user STRING, 
value INT>"))
+                                        .build())
                         .build()) {
 
             Row wrongOrderRow = Row.of(10, "Alice");
@@ -919,7 +975,7 @@ class ProcessTableFunctionTestHarnessTest {
         // that type.
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(UserPTF.class)
-                        .withTableArgument("user")
+                        
.withTableArgument(TableArgument.forName("user").build())
                         .build()) {
 
             harness.processElement(Row.of("Alice", 25));
@@ -939,7 +995,7 @@ class ProcessTableFunctionTestHarnessTest {
         // Test PTF with structured type inputs and outputs
         try (ProcessTableFunctionTestHarness<User> harness =
                 ProcessTableFunctionTestHarness.ofClass(UserTransformPTF.class)
-                        .withTableArgument("user")
+                        
.withTableArgument(TableArgument.forName("user").build())
                         .build()) {
 
             harness.processElement(Row.of("Alice", 25));
@@ -980,7 +1036,10 @@ class ProcessTableFunctionTestHarnessTest {
         // types, the harness builds successfully
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(InlineTypePTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<value 
INT>"))
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<value INT>"))
+                                        .build())
                         .build()) {
 
             harness.processElement(Row.of(7));
@@ -1000,8 +1059,11 @@ class ProcessTableFunctionTestHarnessTest {
         // Verify set-semantic table with partition configuration by column 
name
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(PartitionedPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<key 
STRING, value INT>"))
-                        .withPartitionBy("input", "key") // Partition by "key" 
column name
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<key STRING, 
value INT>"))
+                                        .partitionBy("key")
+                                        .build())
                         .build()) {
 
             harness.processElement(Row.of("X", 10));
@@ -1022,9 +1084,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(PartitionedPTF.class)
                         .withTableArgument(
-                                "input",
-                                DataTypes.of("ROW<region STRING, country 
STRING, value INT>"))
-                        .withPartitionBy("input", "region", "country")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<region STRING, 
country STRING, value INT>"))
+                                        .partitionBy("region", "country")
+                                        .build())
                         .build()) {
 
             harness.processElement(Row.of("EU", "DE", 100));
@@ -1047,10 +1112,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(PartitionedPTF.class)
                         .withTableArgument(
-                                "input",
-                                DataTypes.of(
-                                        "ROW<id INT, region STRING, country 
STRING, city STRING, value INT>"))
-                        .withPartitionBy("input", "region")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<id INT, region 
STRING, country STRING, city STRING, value INT>"))
+                                        .partitionBy("region")
+                                        .build())
                         .build()) {
 
             harness.processElement(Row.of(1, "EU", "DE", "Berlin", 100));
@@ -1067,11 +1134,16 @@ class ProcessTableFunctionTestHarnessTest {
     void testMultipleSetSemanticTablesWithMatchingPartitionKeys() throws 
Exception {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(MultiTableUnionPTF.class)
-                        .withTableArgument("leftTable", DataTypes.of("ROW<name 
STRING, score INT>"))
-                        .withPartitionBy("leftTable", "name")
                         .withTableArgument(
-                                "rightTable", DataTypes.of("ROW<name STRING, 
city STRING>"))
-                        .withPartitionBy("rightTable", "name")
+                                TableArgument.forName("leftTable")
+                                        .type(DataTypes.of("ROW<name STRING, 
score INT>"))
+                                        .partitionBy("name")
+                                        .build())
+                        .withTableArgument(
+                                TableArgument.forName("rightTable")
+                                        .type(DataTypes.of("ROW<name STRING, 
city STRING>"))
+                                        .partitionBy("name")
+                                        .build())
                         .build()) {
 
             harness.processElementForTable("leftTable", Row.of("Alice", 100));
@@ -1107,11 +1179,13 @@ class ProcessTableFunctionTestHarnessTest {
         // and another is a Row, both partitioned by the same field type
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(MixedTypeMultiTablePTF.class)
-                        .withTableArgument("userTable")
-                        .withPartitionBy("userTable", "age")
                         .withTableArgument(
-                                "rowTable", DataTypes.of("ROW<name STRING, age 
INT NOT NULL>"))
-                        .withPartitionBy("rowTable", "age")
+                                
TableArgument.forName("userTable").partitionBy("age").build())
+                        .withTableArgument(
+                                TableArgument.forName("rowTable")
+                                        .type(DataTypes.of("ROW<name STRING, 
age INT NOT NULL>"))
+                                        .partitionBy("age")
+                                        .build())
                         .build()) {
 
             harness.processElementForTable("userTable", Row.of("Alice", 25));
@@ -1133,12 +1207,17 @@ class ProcessTableFunctionTestHarnessTest {
                         () -> {
                             
ProcessTableFunctionTestHarness.ofClass(MultiTableUnionPTF.class)
                                     .withTableArgument(
-                                            "leftTable", DataTypes.of("ROW<id 
INT, name STRING>"))
-                                    .withPartitionBy("leftTable", "id")
+                                            TableArgument.forName("leftTable")
+                                                    .type(DataTypes.of("ROW<id 
INT, name STRING>"))
+                                                    .partitionBy("id")
+                                                    .build())
                                     .withTableArgument(
-                                            "rightTable",
-                                            DataTypes.of("ROW<key STRING, city 
STRING>"))
-                                    .withPartitionBy("rightTable", "key")
+                                            TableArgument.forName("rightTable")
+                                                    .type(
+                                                            DataTypes.of(
+                                                                    "ROW<key 
STRING, city STRING>"))
+                                                    .partitionBy("key")
+                                                    .build())
                                     .build();
                         });
 
@@ -1154,12 +1233,17 @@ class ProcessTableFunctionTestHarnessTest {
                         () -> {
                             
ProcessTableFunctionTestHarness.ofClass(MultiTableUnionPTF.class)
                                     .withTableArgument(
-                                            "leftTable",
-                                            DataTypes.of("ROW<id INT, region 
STRING, name STRING>"))
-                                    .withPartitionBy("leftTable", "id", 
"region")
+                                            TableArgument.forName("leftTable")
+                                                    .type(
+                                                            DataTypes.of(
+                                                                    "ROW<id 
INT, region STRING, name STRING>"))
+                                                    .partitionBy("id", 
"region")
+                                                    .build())
                                     .withTableArgument(
-                                            "rightTable", DataTypes.of("ROW<id 
INT, city STRING>"))
-                                    .withPartitionBy("rightTable", "id")
+                                            TableArgument.forName("rightTable")
+                                                    .type(DataTypes.of("ROW<id 
INT, city STRING>"))
+                                                    .partitionBy("id")
+                                                    .build())
                                     .build();
                         });
 
@@ -1175,8 +1259,14 @@ class ProcessTableFunctionTestHarnessTest {
                         () -> {
                             ProcessTableFunctionTestHarness.ofClass(
                                             
InvalidPassColumnsThroughMultiTablePTF.class)
-                                    .withTableArgument("leftTable", 
DataTypes.of("ROW<a INT>"))
-                                    .withTableArgument("rightTable", 
DataTypes.of("ROW<b INT>"))
+                                    .withTableArgument(
+                                            TableArgument.forName("leftTable")
+                                                    .type(DataTypes.of("ROW<a 
INT>"))
+                                                    .build())
+                                    .withTableArgument(
+                                            TableArgument.forName("rightTable")
+                                                    .type(DataTypes.of("ROW<b 
INT>"))
+                                                    .build())
                                     .build();
                         });
 
@@ -1193,10 +1283,16 @@ class ProcessTableFunctionTestHarnessTest {
     void testProcessElementOnMultiTableThrows() throws Exception {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(MultiTableUnionPTF.class)
-                        .withTableArgument("leftTable", DataTypes.of("ROW<id 
INT, name STRING>"))
-                        .withTableArgument("rightTable", DataTypes.of("ROW<id 
INT, value STRING>"))
-                        .withPartitionBy("leftTable", "id")
-                        .withPartitionBy("rightTable", "id")
+                        .withTableArgument(
+                                TableArgument.forName("leftTable")
+                                        .type(DataTypes.of("ROW<id INT, name 
STRING>"))
+                                        .partitionBy("id")
+                                        .build())
+                        .withTableArgument(
+                                TableArgument.forName("rightTable")
+                                        .type(DataTypes.of("ROW<id INT, value 
STRING>"))
+                                        .partitionBy("id")
+                                        .build())
                         .build()) {
 
             Exception exception =
@@ -1217,7 +1313,10 @@ class ProcessTableFunctionTestHarnessTest {
     void testClearOutput() throws Exception {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(PassthroughPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<value 
INT>"))
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<value INT>"))
+                                        .build())
                         .build()) {
 
             harness.processElement(Row.of(10));
@@ -1243,7 +1342,10 @@ class ProcessTableFunctionTestHarnessTest {
     void testFunctionOutputReturnsUnwrappedAtomicValue() throws Exception {
         try (ProcessTableFunctionTestHarness<Integer> harness =
                 ProcessTableFunctionTestHarness.ofClass(AtomicOutputPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<value 
INT>"))
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<value INT>"))
+                                        .build())
                         .build()) {
 
             harness.processElement(Row.of(21));
@@ -1257,8 +1359,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testFunctionOutputExcludesPrependedPartitionKey() throws Exception {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(PartitionedPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<key 
STRING, value INT>"))
-                        .withPartitionBy("input", "key")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<key STRING, 
value INT>"))
+                                        .partitionBy("key")
+                                        .build())
                         .build()) {
 
             harness.processElement(Row.of("X", 10));
@@ -1277,7 +1382,10 @@ class ProcessTableFunctionTestHarnessTest {
     void testProcessElementForTableWithInvalidName() throws Exception {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(PassthroughPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<value 
INT>"))
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<value INT>"))
+                                        .build())
                         .build()) {
 
             Exception exception =
@@ -1296,12 +1404,16 @@ class ProcessTableFunctionTestHarnessTest {
                         () -> {
                             
ProcessTableFunctionTestHarness.ofClass(PartitionedPTF.class)
                                     .withTableArgument(
-                                            "input", DataTypes.of("ROW<key 
STRING, value INT>"))
+                                            TableArgument.forName("input")
+                                                    .type(
+                                                            DataTypes.of(
+                                                                    "ROW<key 
STRING, value INT>"))
+                                                    .build())
                                     .build();
                         });
 
         assertThat(exception.getMessage()).contains("No partition 
configuration found");
-        assertThat(exception.getMessage()).contains("withPartitionBy");
+        assertThat(exception.getMessage()).contains("TableArgument.forName");
     }
 
     @Test
@@ -1312,8 +1424,12 @@ class ProcessTableFunctionTestHarnessTest {
                         () -> {
                             
ProcessTableFunctionTestHarness.ofClass(PartitionedPTF.class)
                                     .withTableArgument(
-                                            "input", DataTypes.of("ROW<key 
STRING, value INT>"))
-                                    .withPartitionBy("input", "nonexistent")
+                                            TableArgument.forName("input")
+                                                    .type(
+                                                            DataTypes.of(
+                                                                    "ROW<key 
STRING, value INT>"))
+                                                    .partitionBy("nonexistent")
+                                                    .build())
                                     .build();
                         });
 
@@ -1322,19 +1438,31 @@ class ProcessTableFunctionTestHarnessTest {
     }
 
     @Test
-    void testPartitionByDuplicateConfigThrows() {
+    void testBuilderRejectsDuplicateTableArgumentWithPartitioning() {
+        // Configuring the same table argument twice is rejected, even when 
the second
+        // configuration only differs in its partitioning.
         Exception exception =
                 assertThrows(
                         IllegalArgumentException.class,
                         () -> {
                             
ProcessTableFunctionTestHarness.ofClass(PartitionedPTF.class)
-                                    .withTableArgument(
-                                            "input", DataTypes.of("ROW<key 
STRING, value INT>"))
-                                    .withPartitionBy("input", "key") // First 
config
-                                    .withPartitionBy("input", "key"); // 
Duplicate - should fail
+                                    .withTableArgument( // First config
+                                            TableArgument.forName("input")
+                                                    .type(
+                                                            DataTypes.of(
+                                                                    "ROW<key 
STRING, value INT>"))
+                                                    .partitionBy("key")
+                                                    .build())
+                                    .withTableArgument( // Duplicate - should 
fail
+                                            TableArgument.forName("input")
+                                                    .type(
+                                                            DataTypes.of(
+                                                                    "ROW<key 
STRING, value INT>"))
+                                                    .partitionBy("key")
+                                                    .build());
                         });
 
-        assertThat(exception.getMessage()).contains("Partition config already 
exists");
+        assertThat(exception.getMessage()).contains("Argument already 
configured");
     }
 
     // 
-------------------------------------------------------------------------
@@ -1345,8 +1473,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testValueState() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<name 
STRING, value INT>"))
-                        .withPartitionBy("input", "name")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<name STRING, 
value INT>"))
+                                        .partitionBy("name")
+                                        .build())
                         .build();
 
         harness.processElementForTable("input", Row.of("Alice", 10));
@@ -1368,8 +1499,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testValueStatePartitionIsolation() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<name 
STRING, value INT>"))
-                        .withPartitionBy("input", "name")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<name STRING, 
value INT>"))
+                                        .partitionBy("name")
+                                        .build())
                         .build();
 
         harness.processElementForTable("input", Row.of("Alice", 10));
@@ -1393,8 +1527,11 @@ class ProcessTableFunctionTestHarnessTest {
 
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<id 
INT>"))
-                        .withPartitionBy("input", "id")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<id INT>"))
+                                        .partitionBy("id")
+                                        .build())
                         .withInitialStateForKey("state", Row.of(1), 
initialState)
                         .build();
 
@@ -1414,8 +1551,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testGetStateKeys() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<name 
STRING, value INT>"))
-                        .withPartitionBy("input", "name")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<name STRING, 
value INT>"))
+                                        .partitionBy("name")
+                                        .build())
                         .build();
 
         harness.processElementForTable("input", Row.of("Alice", 10));
@@ -1433,8 +1573,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testGetAllState() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<name 
STRING, value INT>"))
-                        .withPartitionBy("input", "name")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<name STRING, 
value INT>"))
+                                        .partitionBy("name")
+                                        .build())
                         .build();
 
         harness.processElementForTable("input", Row.of("Alice", 10));
@@ -1454,8 +1597,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testListViewState() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithListViewState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<key 
STRING, value INT>"))
-                        .withPartitionBy("input", "key")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<key STRING, 
value INT>"))
+                                        .partitionBy("key")
+                                        .build())
                         .build();
 
         harness.processElementForTable("input", Row.of("A", 1));
@@ -1475,8 +1621,10 @@ class ProcessTableFunctionTestHarnessTest {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithMapViewState.class)
                         .withTableArgument(
-                                "input", DataTypes.of("ROW<partition STRING, 
key STRING>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<partition 
STRING, key STRING>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .build();
 
         harness.processElementForTable("input", Row.of("P1", "foo"));
@@ -1499,8 +1647,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testRowState() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(PTFWithRowState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<name 
STRING, value INT>"))
-                        .withPartitionBy("input", "name")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<name STRING, 
value INT>"))
+                                        .partitionBy("name")
+                                        .build())
                         .build();
 
         harness.processElementForTable("input", Row.of("Alice", 10));
@@ -1519,8 +1670,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testEmptyState() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<name 
STRING, value INT>"))
-                        .withPartitionBy("input", "name")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<name STRING, 
value INT>"))
+                                        .partitionBy("name")
+                                        .build())
                         .build();
 
         PTFWithValueState.CounterState state = harness.getStateForKey("state", 
Row.of("Alice"));
@@ -1534,8 +1688,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testClearAllStatesForKey() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<name 
STRING, value INT>"))
-                        .withPartitionBy("input", "name")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<name STRING, 
value INT>"))
+                                        .partitionBy("name")
+                                        .build())
                         .build();
 
         harness.processElementForTable("input", Row.of("Alice", 10));
@@ -1560,8 +1717,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testClearStateForKey() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<name 
STRING, value INT>"))
-                        .withPartitionBy("input", "name")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<name STRING, 
value INT>"))
+                                        .partitionBy("name")
+                                        .build())
                         .build();
 
         harness.processElementForTable("input", Row.of("Alice", 10));
@@ -1586,8 +1746,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testMultipleStateParameters() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithMultipleStates.class)
-                        .withTableArgument("input", DataTypes.of("ROW<key 
STRING, value INT>"))
-                        .withPartitionBy("input", "key")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<key STRING, 
value INT>"))
+                                        .partitionBy("key")
+                                        .build())
                         .build();
 
         harness.processElementForTable("input", Row.of("A", 10));
@@ -1615,8 +1778,11 @@ class ProcessTableFunctionTestHarnessTest {
 
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithListViewState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<key 
STRING, value INT>"))
-                        .withPartitionBy("input", "key")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<key STRING, 
value INT>"))
+                                        .partitionBy("key")
+                                        .build())
                         .withInitialStateForKey("listState", Row.of("A"), 
initialList)
                         .build();
 
@@ -1637,8 +1803,10 @@ class ProcessTableFunctionTestHarnessTest {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithMapViewState.class)
                         .withTableArgument(
-                                "input", DataTypes.of("ROW<partition STRING, 
key STRING>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<partition 
STRING, key STRING>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withInitialStateForKey("mapState", Row.of("P1"), 
initialMap)
                         .build();
 
@@ -1659,9 +1827,12 @@ class ProcessTableFunctionTestHarnessTest {
                         () ->
                                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
                                         .withTableArgument(
-                                                "input",
-                                                DataTypes.of("ROW<name STRING, 
value INT>"))
-                                        .withPartitionBy("input", "name")
+                                                TableArgument.forName("input")
+                                                        .type(
+                                                                DataTypes.of(
+                                                                        
"ROW<name STRING, value INT>"))
+                                                        .partitionBy("name")
+                                                        .build())
                                         .withInitialStateForKey(
                                                 "state",
                                                 Row.of("Alice", 42),
@@ -1681,9 +1852,12 @@ class ProcessTableFunctionTestHarnessTest {
                         () ->
                                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
                                         .withTableArgument(
-                                                "input",
-                                                DataTypes.of("ROW<name STRING, 
value INT>"))
-                                        .withPartitionBy("input", "name")
+                                                TableArgument.forName("input")
+                                                        .type(
+                                                                DataTypes.of(
+                                                                        
"ROW<name STRING, value INT>"))
+                                                        .partitionBy("name")
+                                                        .build())
                                         .withInitialStateForKey(
                                                 "state",
                                                 Row.of(42),
@@ -1700,8 +1874,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testSetStateForKey() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<name 
STRING, value INT>"))
-                        .withPartitionBy("input", "name")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<name STRING, 
value INT>"))
+                                        .partitionBy("name")
+                                        .build())
                         .build();
 
         harness.processElementForTable("input", Row.of("Alice", 10));
@@ -1730,8 +1907,11 @@ class ProcessTableFunctionTestHarnessTest {
                         IllegalArgumentException.class,
                         () ->
                                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
-                                        .withTableArgument("input", 
DataTypes.of("ROW<id INT>"))
-                                        .withPartitionBy("input", "id")
+                                        .withTableArgument(
+                                                TableArgument.forName("input")
+                                                        
.type(DataTypes.of("ROW<id INT>"))
+                                                        .partitionBy("id")
+                                                        .build())
                                         .withInitialStateForKey(
                                                 "nonExistentState", Row.of(1), 
"value")
                                         .build());
@@ -1750,8 +1930,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testPartitionKeyValidationWrongArity() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<name 
STRING, value INT>"))
-                        .withPartitionBy("input", "name")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<name STRING, 
value INT>"))
+                                        .partitionBy("name")
+                                        .build())
                         .build();
 
         Exception exception =
@@ -1768,8 +1951,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testPartitionKeyValidationWrongType() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<name 
STRING, value INT>"))
-                        .withPartitionBy("input", "name")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<name STRING, 
value INT>"))
+                                        .partitionBy("name")
+                                        .build())
                         .build();
 
         Exception exception =
@@ -1787,8 +1973,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testPartitionKeyValidationOnSetState() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<name 
STRING, value INT>"))
-                        .withPartitionBy("input", "name")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<name STRING, 
value INT>"))
+                                        .partitionBy("name")
+                                        .build())
                         .build();
 
         PTFWithValueState.CounterState state = new 
PTFWithValueState.CounterState();
@@ -1805,8 +1994,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testPartitionKeyValidationOnClearAllStates() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<name 
STRING, value INT>"))
-                        .withPartitionBy("input", "name")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<name STRING, 
value INT>"))
+                                        .partitionBy("name")
+                                        .build())
                         .build();
 
         assertThrows(
@@ -1820,8 +2012,11 @@ class ProcessTableFunctionTestHarnessTest {
     void testPartitionKeyValidationOnClearState() throws Exception {
         ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PTFWithValueState.class)
-                        .withTableArgument("input", DataTypes.of("ROW<name 
STRING, value INT>"))
-                        .withPartitionBy("input", "name")
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<name STRING, 
value INT>"))
+                                        .partitionBy("name")
+                                        .build())
                         .build();
 
         assertThrows(
@@ -2130,12 +2325,19 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(MultiTableTimerPTF.class)
                         .withTableArgument(
-                                "leftTable", DataTypes.of("ROW<partition 
STRING, ts TIMESTAMP(3)>"))
+                                TableArgument.forName("leftTable")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withTableArgument(
-                                "rightTable",
-                                DataTypes.of("ROW<partition STRING, ts 
TIMESTAMP(3)>"))
-                        .withPartitionBy("leftTable", "partition")
-                        .withPartitionBy("rightTable", "partition")
+                                TableArgument.forName("rightTable")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2172,10 +2374,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(ContextClearStatePTF.class)
                         .withTableArgument(
-                                "input",
-                                DataTypes.of(
-                                        "ROW<partition STRING, action STRING, 
ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
action STRING, ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2205,10 +2409,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(ContextClearStatePTF.class)
                         .withTableArgument(
-                                "input",
-                                DataTypes.of(
-                                        "ROW<partition STRING, action STRING, 
ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
action STRING, ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2232,10 +2438,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(ContextClearStatePTF.class)
                         .withTableArgument(
-                                "input",
-                                DataTypes.of(
-                                        "ROW<partition STRING, action STRING, 
ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
action STRING, ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2268,8 +2476,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(ContextSemanticsIntrospectionPTF.class)
                         .withTableArgument(
-                                "input", DataTypes.of("ROW<partition STRING, 
ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2300,8 +2512,8 @@ class ProcessTableFunctionTestHarnessTest {
     void testPojoInputWithOnTimeColumn() throws Exception {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(PojoTimerPTF.class)
-                        .withTableArgument("input")
-                        .withPartitionBy("input", "key")
+                        .withTableArgument(
+                                
TableArgument.forName("input").partitionBy("key").build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2329,9 +2541,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(OnTimePTF.class)
                         .withTableArgument(
-                                "input",
-                                DataTypes.of("ROW<partition STRING, name 
STRING, ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
name STRING, ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2347,9 +2562,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(OnTimePTF.class)
                         .withTableArgument(
-                                "input",
-                                DataTypes.of("ROW<partition STRING, name 
STRING, ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
name STRING, ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2365,7 +2583,10 @@ class ProcessTableFunctionTestHarnessTest {
     void testWatermarkAdvancesWithoutOnTimeColumn() throws Exception {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(PassthroughPTF.class)
-                        .withTableArgument("input", DataTypes.of("ROW<value 
INT>"))
+                        .withTableArgument(
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<value INT>"))
+                                        .build())
                         .build()) {
 
             harness.processElement(Row.of(42));
@@ -2383,9 +2604,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(TimerPTF.class)
                         .withTableArgument(
-                                "input",
-                                DataTypes.of("ROW<partition STRING, name 
STRING, ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
name STRING, ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2425,8 +2649,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(UnnamedTimerPTF.class)
                         .withTableArgument(
-                                "input", DataTypes.of("ROW<partition STRING, 
ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2448,9 +2676,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(TimerPTF.class)
                         .withTableArgument(
-                                "input",
-                                DataTypes.of("ROW<partition STRING, name 
STRING, ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
name STRING, ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2485,9 +2716,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(TimerPTF.class)
                         .withTableArgument(
-                                "input",
-                                DataTypes.of("ROW<partition STRING, name 
STRING, ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
name STRING, ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2519,8 +2753,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(TimerWithStatePTF.class)
                         .withTableArgument(
-                                "input", DataTypes.of("ROW<partition STRING, 
ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2549,9 +2787,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(TimerPTF.class)
                         .withTableArgument(
-                                "input",
-                                DataTypes.of("ROW<partition STRING, name 
STRING, ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
name STRING, ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2577,8 +2818,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(PassThroughTimerPTF.class)
                         .withTableArgument(
-                                "input", DataTypes.of("ROW<partition STRING, 
ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2597,8 +2842,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(NoOnTimerPTF.class)
                         .withTableArgument(
-                                "input", DataTypes.of("ROW<partition STRING, 
ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2620,10 +2869,12 @@ class ProcessTableFunctionTestHarnessTest {
                         () ->
                                 
ProcessTableFunctionTestHarness.ofClass(TimerPTF.class)
                                         .withTableArgument(
-                                                "input",
-                                                DataTypes.of(
-                                                        "ROW<partition STRING, 
ts TIMESTAMP(3)>"))
-                                        .withPartitionBy("input", "partition")
+                                                TableArgument.forName("input")
+                                                        .type(
+                                                                DataTypes.of(
+                                                                        
"ROW<partition STRING, ts TIMESTAMP(3)>"))
+                                                        
.partitionBy("partition")
+                                                        .build())
                                         .build());
         assertThat(e.getMessage()).contains("requires a time attribute", 
"on_time");
     }
@@ -2633,8 +2884,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(MultipleOnTimerPTF.class)
                         .withTableArgument(
-                                "input", DataTypes.of("ROW<partition STRING, 
ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2653,8 +2908,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(CascadingTimerPTF.class)
                         .withTableArgument(
-                                "input", DataTypes.of("ROW<partition STRING, 
ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2683,10 +2942,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(ClearTimerPTF.class)
                         .withTableArgument(
-                                "input",
-                                DataTypes.of(
-                                        "ROW<partition STRING, action STRING, 
ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
action STRING, ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2709,10 +2970,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(ClearTimerPTF.class)
                         .withTableArgument(
-                                "input",
-                                DataTypes.of(
-                                        "ROW<partition STRING, action STRING, 
ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
action STRING, ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2737,10 +3000,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(ClearTimerPTF.class)
                         .withTableArgument(
-                                "input",
-                                DataTypes.of(
-                                        "ROW<partition STRING, action STRING, 
ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
action STRING, ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2766,10 +3031,12 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 ProcessTableFunctionTestHarness.ofClass(ClearTimerPTF.class)
                         .withTableArgument(
-                                "input",
-                                DataTypes.of(
-                                        "ROW<partition STRING, action STRING, 
ts TIMESTAMP(3)>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(
+                                                DataTypes.of(
+                                                        "ROW<partition STRING, 
action STRING, ts TIMESTAMP(3)>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .withOnTimeColumn("ts")
                         .build()) {
 
@@ -2793,8 +3060,10 @@ class ProcessTableFunctionTestHarnessTest {
         try (ProcessTableFunctionTestHarness<Row> harness =
                 
ProcessTableFunctionTestHarness.ofClass(WatermarkOnlyTimerPTF.class)
                         .withTableArgument(
-                                "input", DataTypes.of("ROW<partition STRING, 
value INT>"))
-                        .withPartitionBy("input", "partition")
+                                TableArgument.forName("input")
+                                        .type(DataTypes.of("ROW<partition 
STRING, value INT>"))
+                                        .partitionBy("partition")
+                                        .build())
                         .build()) {
 
             harness.setWatermark(Instant.ofEpochMilli(1000));

Reply via email to