</>

Technology

API Automation

Difficulty

Advanced

Interview Question

How do you handle API versioning in test automation?

Answer

API Versioning in Test Automation

APIs evolve over time. Good test automation handles multiple versions cleanly.

Common API Versioning Patterns

PatternExample
URL path versioning/api/v1/users, /api/v2/users
Query parameter/api/users?version=2
Header versioningAccept-Version: 2
Subdomainv2.api.example.com/users

Strategy 1: Version-Based Test Configuration

Java
// config.properties
api.version=v2
base.url=https://api.example.com

// BaseApiTest.java
public class BaseApiTest {
    protected static final String VERSION = ConfigManager.get("api.version");
    protected static final String BASE_URL = ConfigManager.get("base.url");

    protected String endpoint(String path) {
        return BASE_URL + "/api/" + VERSION + path;
    }
}

// Usage in test
@Test
public void testGetUsers() {
    given()
        .when()
        .get(endpoint("/users"))  // resolves to /api/v2/users
        .then()
        .statusCode(200);
}

Strategy 2: Separate Test Suites Per Version

CODE
tests/
ā”œā”€ā”€ v1/
│   ā”œā”€ā”€ UserApiV1Test.java
│   └── OrderApiV1Test.java
└── v2/
    ā”œā”€ā”€ UserApiV2Test.java   ← New fields in v2
    └── OrderApiV2Test.java
Java
// V1 Test
public class UserApiV1Test {
    private static final String BASE = "/api/v1";

    @Test
    public void testGetUserV1() {
        given().when().get(BASE + "/users/1")
               .then().statusCode(200)
               .body("$", hasKey("name"))
               .body("$", not(hasKey("full_name"))); // v1 uses 'name', not 'full_name'
    }
}

// V2 Test
public class UserApiV2Test {
    private static final String BASE = "/api/v2";

    @Test
    public void testGetUserV2() {
        given().when().get(BASE + "/users/1")
               .then().statusCode(200)
               .body("$", hasKey("full_name"))  // v2 renamed to 'full_name'
               .body("$", hasKey("profile_picture"));  // v2 added new field
    }
}

Strategy 3: Parameterized Version Tests

Java
@DataProvider(name = "apiVersions")
public Object[][] apiVersions() {
    return new Object[][] {
        { "v1" },
        { "v2" }
    };
}

@Test(dataProvider = "apiVersions")
public void testUsersEndpointAcrossVersions(String version) {
    given()
        .when()
        .get("/api/" + version + "/users")
        .then()
        .statusCode(200); // Both versions should return 200
}

Strategy 4: Header-Based Versioning

Java
@Test
public void testApiWithVersionHeader() {
    // Request v1 response
    given()
        .header("Accept-Version", "1.0")
        .when()
        .get("/api/users")
        .then()
        .statusCode(200)
        .header("API-Version", "1.0");

    // Request v2 response — different fields
    given()
        .header("Accept-Version", "2.0")
        .when()
        .get("/api/users")
        .then()
        .statusCode(200)
        .header("API-Version", "2.0")
        .body("data[0]", hasKey("full_name")); // v2-specific field
}

CI/CD: Testing Multiple Versions in Pipeline

YAML
# GitHub Actions matrix strategy
strategy:
  matrix:
    api-version: [v1, v2]

steps:
  - name: Run API Tests for ${{ matrix.api-version }}
    run: mvn test -Dapi.version=${{ matrix.api-version }}

Best Practices

  • āœ“Keep v1 smoke tests running alongside v2 tests during deprecation period
  • āœ“Use semantic versioning contracts with Pact
  • āœ“Document version differences in test class Javadoc
  • āœ“Remove tests for officially deprecated versions after sunset date

Follow AutomateQA

Related Topics