@@ -140,6 +140,19 @@ public class TestTableUpdatePartitionSpec extends TableTestBase {
 
     Assert.assertEquals("should match evolved spec", evolvedSpec, table.spec());
     Assert.assertEquals(1002, table.spec().lastAssignedFieldId());
+
+    table.updateSpec()
+        .renameField("id_bucket_8", "id_partition")
+        .commit();
+
+    evolvedSpec = PartitionSpec.builderFor(table.schema())
+        .withSpecId(3)
+        .bucket("data", 16, "data_bucket")
+        .bucket("id", 8, "id_partition")
+        .truncate("id", 4, "id_trunc_4")
+        .build();
+    Assert.assertEquals("should match evolved spec", evolvedSpec, table.spec());
+    Assert.assertEquals(1002, table.spec().lastAssignedFieldId());
   }
 
   @Test
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.iceberg;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import static org.apache.iceberg.expressions.Expressions.bucket;
import static org.apache.iceberg.expressions.Expressions.truncate;

@RunWith(Parameterized.class)
public class TestTableUpdatePartitionSpec extends TableTestBase {

  @Parameterized.Parameters
  public static Object[][] parameters() {
    return new Object[][] {
        new Object[] { 1 },
        new Object[] { 2 },
    };
  }

  public TestTableUpdatePartitionSpec(int formatVersion) {
    super(formatVersion);
  }

  @Before
  public void verifyInitialSpec() {
    PartitionSpec initialSpec = PartitionSpec.builderFor(table.schema()).bucket("data", 16).build();
    Assert.assertEquals("Should use the expected initial spec", initialSpec, table.spec());
    Assert.assertEquals(1000, table.spec().lastAssignedFieldId());
    Assert.assertEquals(0, table.spec().specId());
  }

  @Test
  public void testCommitUpdatedSpec() {
    table.updateSpec()
        .addField(bucket("id", 8))
        .commit();

    PartitionSpec evolvedSpec = PartitionSpec.builderFor(table.schema())
        .withSpecId(1)
        .bucket("data", 16)
        .bucket("id", 8, "id_bucket_8")
        .build();
    Assert.assertEquals("Should append a partition field to the spec", evolvedSpec, table.spec());
    Assert.assertEquals(1001, table.spec().lastAssignedFieldId());

    table.updateSpec()
        .removeField("id_bucket_8")
        .removeField("data_bucket")
        .addField(truncate("data", 8))
        .commit();

    V1Assert.assertEquals("Should soft delete id and data buckets", PartitionSpec.builderFor(table.schema())
        .withSpecId(2)
        .alwaysNull("data", "data_bucket")
        .alwaysNull("id", "id_bucket_8")
        .truncate("data", 8, "data_trunc_8")
        .build(), table.spec());

    V2Assert.assertEquals("Should hard delete id and data buckets", PartitionSpec.builderFor(table.schema())
        .withSpecId(2)
        .add(2, 1002, "data_trunc_8", "truncate[8]")
        .build(), table.spec());

    Assert.assertEquals(1002, table.spec().lastAssignedFieldId());
  }

  @Test
  public void testNoopCommit() {
    TableMetadata current = table.ops().current();
    int currentVersion = TestTables.metadataVersion("test");

    // no-op commit due to no-op
    table.updateSpec().commit();
    TableMetadata updated = table.ops().current();
    Integer updatedVersion = TestTables.metadataVersion("test");
    Assert.assertEquals(current, updated);
    currentVersion += 1;
    Assert.assertEquals(currentVersion, updatedVersion.intValue());

    // no-op commit due to no-op rename
    table.updateSpec()
        .renameField("data_bucket", "data_bucket")
        .commit();
    updated = table.ops().current();
    updatedVersion = TestTables.metadataVersion("test");
    Assert.assertEquals(current, updated);
    currentVersion += 1;
    Assert.assertEquals(currentVersion, updatedVersion.intValue());
  }

  @Test
  public void testRenameField() {
    table.updateSpec()
        .renameField("data_bucket", "data_partition")
        .addField(bucket("id", 8))
        .commit();

    PartitionSpec evolvedSpec = PartitionSpec.builderFor(table.schema())
        .withSpecId(1)
        .bucket("data", 16, "data_partition")
        .bucket("id", 8, "id_bucket_8")
        .build();

    Assert.assertEquals("should match evolved spec", evolvedSpec, table.spec());
    Assert.assertEquals(1001, table.spec().lastAssignedFieldId());

    table.updateSpec()
        .addField(truncate("id", 4))
        .renameField("data_partition", "data_bucket")
        .commit();

    evolvedSpec = PartitionSpec.builderFor(table.schema())
        .withSpecId(2)
        .bucket("data", 16, "data_bucket")
        .bucket("id", 8, "id_bucket_8")
        .truncate("id", 4, "id_trunc_4")
        .build();

    Assert.assertEquals("should match evolved spec", evolvedSpec, table.spec());
    Assert.assertEquals(1002, table.spec().lastAssignedFieldId());
  }

  @Test
  public void testRemoveAndAddField() {
    table.updateSpec()
        .removeField("data_bucket")
        .addField(bucket("id", 8))
        .commit();

    V1Assert.assertEquals("Should soft delete data bucket", PartitionSpec.builderFor(table.schema())
        .withSpecId(1)
        .alwaysNull("data", "data_bucket")
        .bucket("id", 8, "id_bucket_8")
        .build(), table.spec());

    V2Assert.assertEquals("Should hard delete data bucket", PartitionSpec.builderFor(table.schema())
        .withSpecId(1)
        .add(1, 1001, "id_bucket_8", "bucket[8]")
        .build(), table.spec());

    Assert.assertEquals(1001, table.spec().lastAssignedFieldId());
  }

  @Test
  public void testAddAndRemoveField() {
    table.updateSpec()
        .addField(bucket("data", 6))
        .removeField("data_bucket")
        .commit();

    V1Assert.assertEquals("Should remove and then add a bucket field", PartitionSpec.builderFor(table.schema())
        .withSpecId(1)
        .alwaysNull("data", "data_bucket")
        .bucket("data", 6, "data_bucket_6")
        .build(), table.spec());
    V2Assert.assertEquals("Should remove and then add a bucket field", PartitionSpec.builderFor(table.schema())
        .withSpecId(1)
        .add(2, 1001, "data_bucket_6", "bucket[6]")
        .build(), table.spec());
    Assert.assertEquals(1001, table.spec().lastAssignedFieldId());
  }
}

This seems like it should be its own test case. Could you move it?