Answer
Scenario: Designing an API Test Automation Framework
Framework Architecture
CODE
api-test-framework/
├── src/
│ ├── main/java/
│ │ ├── config/
│ │ │ └── ConfigManager.java ← Read config.properties
│ │ ├── api/
│ │ │ ├── BaseApi.java ← Base RequestSpec setup
│ │ │ ├── UserApi.java ← User endpoint methods
│ │ │ ├── AuthApi.java ← Auth endpoint methods
│ │ │ └── OrderApi.java ← Order endpoint methods
│ │ ├── models/
│ │ │ ├── User.java ← POJO for User
│ │ │ └── Order.java ← POJO for Order
│ │ └── utils/
│ │ ├── TestDataFactory.java ← Generate test data
│ │ └── FileUtils.java ← File helpers
│ └── test/java/
│ ├── tests/
│ │ ├── UserApiTest.java
│ │ ├── AuthApiTest.java
│ │ └── OrderApiTest.java
│ └── schemas/
│ └── user-schema.json ← JSON schema files
├── src/test/resources/
│ ├── config.properties
│ └── testdata/
│ └── users.csv
├── pom.xml
└── testng.xml
Base API Class
Java
public class BaseApi {
private static String BASE_URL;
private static String AUTH_TOKEN;
@BeforeSuite
public void setUp() {
BASE_URL = ConfigManager.get("base.url");
AUTH_TOKEN = AuthApi.getToken();
RestAssured.baseURI = BASE_URL;
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
}
protected RequestSpecification getAuthSpec() {
return given()
.header("Content-Type", "application/json")
.header("Authorization", "Bearer " + AUTH_TOKEN);
}
protected RequestSpecification getPublicSpec() {
return given()
.header("Content-Type", "application/json");
}
}
API Layer — UserApi
Java
public class UserApi extends BaseApi {
public Response createUser(User user) {
return getAuthSpec()
.body(user)
.when()
.post("/api/users");
}
public Response getUserById(int userId) {
return getAuthSpec()
.pathParam("id", userId)
.when()
.get("/api/users/{id}");
}
public Response updateUser(int userId, User user) {
return getAuthSpec()
.pathParam("id", userId)
.body(user)
.when()
.put("/api/users/{id}");
}
public Response deleteUser(int userId) {
return getAuthSpec()
.pathParam("id", userId)
.when()
.delete("/api/users/{id}");
}
}
Test Class — Clean and Readable
Java
public class UserApiTest extends BaseApi {
private UserApi userApi = new UserApi();
private static int createdUserId;
@Test(priority = 1)
public void testCreateUser() {
User user = TestDataFactory.createRandomUser();
Response response = userApi.createUser(user);
assertEquals(response.getStatusCode(), 201);
assertNotNull(response.jsonPath().getInt("id"));
assertEquals(response.jsonPath().getString("name"), user.getName());
createdUserId = response.jsonPath().getInt("id");
}
@Test(priority = 2, dependsOnMethods = "testCreateUser")
public void testGetCreatedUser() {
Response response = userApi.getUserById(createdUserId);
assertEquals(response.getStatusCode(), 200);
assertEquals(response.jsonPath().getInt("id"), createdUserId);
}
@Test(priority = 3, dependsOnMethods = "testGetCreatedUser")
public void testDeleteUser() {
Response response = userApi.deleteUser(createdUserId);
assertEquals(response.getStatusCode(), 204);
}
}
Configuration Management
PROPERTIES
# config.properties
base.url=https://api.example.com
test.username=testuser
test.password=testpass
Java
public class ConfigManager {
private static Properties props = new Properties();
static {
props.load(new FileInputStream("src/test/resources/config.properties"));
}
public static String get(String key) {
return props.getProperty(key);
}
}
CI/CD Integration
YAML
# pom.xml profile for CI
<profiles>
<profile>
<id>staging</id>
<properties>
<base.url>https://api.staging.com</base.url>
</properties>
</profile>
</profiles>
Bash
# Run staging tests
mvn test -P staging -Dgroups="smoke"
