Introduction

In our REST Assured series, we’ve explored topics like REST Assured with JUnit, REST Assured with TestNG, and Request and Response Logging, equipping you with tools to create robust API tests. Now, we’ll dive into Parameterized Tests, a technique to run the same test with multiple input data sets, enhancing test coverage and efficiency. This guide demonstrates how to implement parameterized tests with REST Assured using JUnit 5 and TestNG, with practical examples and best practices. It’s designed for beginners and experienced developers, ensuring you can master data-driven API testing.

Key Point: Parameterized Tests in REST Assured allow you to execute the same test logic with different inputs, reducing code duplication and improving test scalability.

What are Parameterized Tests?

Parameterized Tests enable a single test method to run multiple times with different input parameters, ideal for testing APIs with varying inputs (e.g., different IDs, payloads, or query parameters). Both JUnit 5 and TestNG support parameterized testing:

  • JUnit 5: Uses @ParameterizedTest with data sources like @ValueSource, @CsvSource, or @MethodSource.
  • TestNG: Uses @DataProvider to supply data to @Test methods.

REST Assured’s fluent API integrates seamlessly with these frameworks, allowing assertions on responses for each parameter set. We’ll use https://jsonplaceholder.typicode.com for examples, testing endpoints like /posts and /comments to demonstrate parameterized tests with various data sources.

Setting Up for Parameterized Tests

We’ll set up a Maven project with REST Assured, JUnit 5, TestNG, and Allure for reporting, supporting both frameworks for parameterized tests. The junit-jupiter and testng dependencies enable JUnit 5 and TestNG, respectively.

Here’s the pom.xml, styled with your preferred Blogger format for XML syntax highlighting:



    4.0.0
    com.example
    rest-assured-parameterized
    1.0-SNAPSHOT

    
        11
        2.27.0
        1.9.22
    

    
        
            io.rest-assured
            rest-assured
            5.4.0
            test
        
        
            org.junit.jupiter
            junit-jupiter
            5.10.2
            test
        
        
            org.testng
            testng
            7.10.2
            test
        
        
            org.hamcrest
            hamcrest
            2.2
            test
        
        
            com.fasterxml.jackson.core
            jackson-databind
            2.15.2
            test
        
        
            io.qameta.allure
            allure-junit5
            ${allure.version}
            test
        
        
            io.qameta.allure
            allure-testng
            ${allure.version}
            test
        
    

    
        
            
                org.apache.maven.plugins
                maven-surefire-plugin
                3.2.5
                
                    
                        -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
                    
                
                
                    
                        org.aspectj
                        aspectjweaver
                        ${aspectj.version}
                    
                
            
            
                io.qameta.allure
                allure-maven
                2.12.0
                
                    ${allure.version}
                
            
        
    

No additional setup is required for https://jsonplaceholder.typicode.com. For TestNG, we’ll create a testng.xml file later in Example 4.

Implementing Parameterized Tests

Let’s explore how to implement parameterized tests with REST Assured using JUnit 5 and TestNG.

Example 1: JUnit 5 with @ValueSource

Use @ParameterizedTest with @ValueSource to test multiple post IDs.


import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

@Feature("Parameterized Tests with REST Assured")
public class JUnitValueSourceTest {

    @BeforeEach
    public void setup() {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";
    }

    @ParameterizedTest(name = "Test fetching post with ID {0}")
    @ValueSource(ints = {1, 2, 3})
    @Description("Test fetching posts with different IDs using ValueSource")
    public void testGetPosts(int postId) {
        given()
            .log().all()
        .when()
            .get("/posts/{id}", postId)
        .then()
            .log().all()
            .statusCode(200)
            .body("id", equalTo(postId))
            .body("userId", greaterThan(0));
    }
}

Explanation:

  • @ParameterizedTest: Marks the test as parameterized.
  • @ValueSource(ints = {...}): Provides a list of integers (post IDs).
  • name = "...": Customizes the test name in reports for clarity.
  • Each iteration tests a different post ID, logging requests and responses.
Important: Use @ValueSource for simple data types like integers, strings, or booleans.

Example 2: JUnit 5 with @CsvSource

Use @CsvSource to test posts with multiple parameters (ID and expected user ID).


import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

@Feature("Parameterized Tests with REST Assured")
public class JUnitCsvSourceTest {

    @BeforeEach
    public void setup() {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";
    }

    @ParameterizedTest(name = "Test post ID {0} with user ID {1}")
    @CsvSource({
        "1, 1",
        "11, 2",
        "21, 3"
    })
    @Description("Test fetching posts with ID and expected user ID using CsvSource")
    public void testGetPostsWithUserId(int postId, int expectedUserId) {
        given()
            .log().all()
        .when()
            .get("/posts/{id}", postId)
        .then()
            .log().all()
            .statusCode(200)
            .body("id", equalTo(postId))
            .body("userId", equalTo(expectedUserId));
    }
}

Explanation:

  • @CsvSource: Provides comma-separated values for multiple parameters.
  • Each row represents a test case with post ID and expected user ID.
  • Validates both the post ID and user ID in the response.

Example 3: JUnit 5 with @MethodSource

Use @MethodSource to provide complex data for testing POST requests.


import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.stream.Stream;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

@Feature("Parameterized Tests with REST Assured")
public class JUnitMethodSourceTest {

    @BeforeEach
    public void setup() {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";
    }

    static Stream postData() {
        return Stream.of(
            Arguments.of("Test Post 1", "Body 1", 1),
            Arguments.of("Test Post 2", "Body 2", 2),
            Arguments.of("Test Post 3", "Body 3", 3)
        );
    }

    @ParameterizedTest(name = "Test creating post with title {0}")
    @MethodSource("postData")
    @Description("Test creating posts with different data using MethodSource")
    public void testCreatePosts(String title, String body, int userId) {
        String requestBody = String.format("{\"title\": \"%s\", \"body\": \"%s\", \"userId\": %d}", title, body, userId);

        given()
            .header("Content-Type", "application/json")
            .body(requestBody)
            .log().all()
        .when()
            .post("/posts")
        .then()
            .log().all()
            .statusCode(201)
            .body("title", equalTo(title))
            .body("userId", equalTo(userId));
    }
}

Explanation:

  • @MethodSource: References a static method (postData) that returns a Stream.
  • Each argument set includes title, body, and user ID for a POST request.
  • Tests simulate creating posts with different payloads.
Pro Tip: Use @MethodSource for complex objects or dynamic data generation in parameterized tests.

Example 4: TestNG with @DataProvider

Use @DataProvider to test comments with different IDs.

Create testng.xml in the project root to run TestNG tests:




    
        
            
        
    

Test code:


import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.restassured.RestAssured;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

@Feature("Parameterized Tests with REST Assured")
public class TestNGDataProviderTest {

    @BeforeClass
    public void setup() {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";
    }

    @DataProvider(name = "commentIds")
    public Object[][] provideCommentIds() {
        return new Object[][] {
            {1},
            {2},
            {3}
        };
    }

    @Test(dataProvider = "commentIds", description = "Test fetching comments with different IDs")
    @Description("Test fetching comments with different IDs using DataProvider")
    public void testGetComments(int commentId) {
        given()
            .log().all()
        .when()
            .get("/comments/{id}", commentId)
        .then()
            .log().all()
            .statusCode(200)
            .body("id", equalTo(commentId))
            .body("email", notNullValue());
    }
}

Explanation:

  • @DataProvider: Supplies comment IDs to the test method.
  • @Test(dataProvider = "commentIds"): Runs the test for each ID.
  • testng.xml: Configures the test suite for execution.

Example 5: Parameterized Tests with Allure

Integrate parameterized tests with Allure reporting for JUnit 5.


import io.qameta.allure.Allure;
import io.qameta.allure.Description;
import io.qameta.allure.Feature;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

@Feature("Parameterized Tests with REST Assured")
public class JUnitAllureTest {

    @BeforeEach
    public void setup() {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";
    }

    @ParameterizedTest(name = "Test fetching post with ID {0}")
    @ValueSource(ints = {1, 2, 3})
    @Description("Test fetching posts with Allure reporting")
    public void testGetPostsWithAllure(int postId) {
        Response response = given()
            .log().all()
        .when()
            .get("/posts/{id}", postId)
        .then()
            .log().all()
            .statusCode(200)
            .body("id", equalTo(postId))
            .extract().response();

        Allure.addAttachment("Response Body for Post ID " + postId, "application/json", response.asString(), ".json");
    }
}

Explanation:

  • Allure.addAttachment: Attaches the response body for each parameterized test to the Allure report.
  • Dynamic attachment names include the post ID for clarity.
  • Run mvn clean test and mvn allure:serve to view the report.

Integrating with CI/CD

Add parameterized tests to a GitHub Actions pipeline for automation, supporting both JUnit and TestNG.

Create or update .github/workflows/ci.yml:


name: REST Assured Parameterized CI Pipeline

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  build-and-test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up JDK 11
        uses: actions/setup-java@v4
        with:
          java-version: '11'
          distribution: 'temurin'

      - name: Cache Maven dependencies
        uses: actions/cache@v4
        with:
          path: ~/.m2/repository
          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
          restore-keys: ${{ runner.os }}-maven-

      - name: Run JUnit and TestNG tests
        run: mvn clean test -Dsurefire.suiteXmlFiles=testng.xml

      - name: Generate Allure report
        run: mvn allure:report

      - name: Upload Allure results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: allure-results
          path: target/allure-results

      - name: Publish Allure report
        if: always()
        uses: simple-elf/allure-report-action@v1.7
        with:
          allure_results: target/allure-results
          gh_pages: gh-pages
          allure_report: allure-report

      - name: Deploy report to GitHub Pages
        if: always()
        uses: peaceiris/actions-gh-pages@v4
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: allure-report

Explanation:

  • -Dsurefire.suiteXmlFiles=testng.xml: Runs TestNG tests alongside JUnit tests.
  • Publishes Allure reports to GitHub Pages for visibility.

Tips for Beginners

  • Start Simple: Use @ValueSource or @DataProvider for basic data sets before moving to complex sources.
  • Keep Data Focused: Test only necessary parameter combinations to avoid excessive test runs.
  • Enable Logging: Use log().all() to debug failed parameterized tests.
  • Use Descriptive Names: Customize test names with parameters for clear reports.
Troubleshooting Tip: If a parameterized test fails, check the logs for the specific parameter set and verify the response matches the expected assertions.

What’s Next?

This post enhances our REST Assured series by introducing Parameterized Tests, a powerful tool for data-driven API testing. To continue your learning, consider exploring:

  • GraphQL Testing: Testing GraphQL APIs with REST Assured.
  • Advanced Allure Reporting: Customizing reports with environments and categories.
  • End-to-End Testing: Combining REST Assured with Selenium for UI and API testing.
Stay tuned for more testing tutorials!