top of page

Welcome
to NumpyNinja Blogs

NumpyNinja: Blogs. Demystifying Tech,

One Blog at a Time.
Millions of views. 

My Step‑by‑Step Approach to Overcoming LMS API Automation Challenges

Jan 13
4 min read

🔧 1. Challenge: Strict Field Validations Across Modules

The LMS APIs enforced extremely strict validation rules across Program, Batch, User, and Skill modules. Every field had a purpose, and the backend validated each one aggressively. Even a small mistake — such as a missing mandatory field, a description shorter than 4 characters, or a duplicate program name — immediately resulted in a 400 Bad Request. During my initial test runs, I spent more time debugging validation errors than actually writing automation. It became clear that manually crafting JSON bodies was not scalable.


How I resolved it (expanded explanation)

To eliminate human error, I created dedicated POJO classes for each module. This allowed me to define field types, enforce length constraints, and ensure mandatory fields were always included. I also integrated the Faker library to generate realistic and unique values for fields like programName, batchName, phoneNumber, and userLoginEmail. This prevented duplicate constraint failures, especially for fields like phone numbers and skill names that had to be unique.

To streamline everything, I built payload builder methods such as buildProgramPayload(), buildBatchPayload(), and buildUserPayload(). These methods returned fully validated JSON objects, ensuring that every request I sent was syntactically correct and aligned with backend rules. This approach dramatically reduced validation-related failures and made my test suite far more reliable.


🔐 2. Challenge: Auto‑Generated IDs Needed for Chaining Tests

The LMS system automatically generated IDs like programId, batchId, userId, and skillId. These IDs were essential for chaining operations — for example, updating a program required the programId, and creating a batch required a valid programId. Initially, I didn’t store these IDs properly, which caused my chained tests to break frequently.


How I resolved it (expanded explanation)

I began extracting IDs directly from API responses using JsonPath, storing them in variables, maps, or even thread-local storage when needed. For example:

java

int programId = response.jsonPath().getInt("programId");

I then passed these IDs dynamically into subsequent API calls. This allowed me to build fully automated workflows like:

  • Create Program → Update Program → Delete Program

  • Create Program → Create Batch → Get Batch by ProgramId

  • Create User → Assign Role → Update Login Status

This shift to dynamic ID extraction transformed my test suite into a fully data-driven framework, eliminating hardcoded values and dependency failures.


🔄 3. Challenge: Complex Workflow Dependencies (Program → Batch → User)

The LMS system followed a strict hierarchy. A Batch could not exist without a Program, and a User could not be assigned to a Batch without both programId and batchId. Initially, I attempted to test endpoints independently, which led to repeated failures because the required data simply didn’t exist.


How I resolved it (expanded explanation)

I created workflow helper methods that automated the entire sequence of operations. For example:

  • createProgram() returned a valid programId

  • createBatch(programId) used that ID to create a batch

  • createUser() returned userId

  • assignUserToProgramBatch(userId, programId, batchId) completed the chain

This approach ensured that every test had the correct prerequisites. It also allowed me to run end‑to‑end scenarios such as:

  • Creating a program

  • Creating batches under that program

  • Creating users

  • Assigning users to batches

  • Fetching users by program or batch

This not only improved test stability but also validated real business workflows.


🧩 4. Challenge: Handling 404 Errors and Boolean Success Flags

The LMS API returned structured error responses with fields like "message" and "success": false. However, different modules had slightly different formats, and error messages varied across environments (QA, UAT, Prod). This inconsistency made negative testing tricky.

How I resolved it (expanded explanation)

I standardized my validation strategy by always checking:

  • Status code

  • Partial error message

  • Boolean success flag

Instead of validating the entire message, I validated only the meaningful part. For example, instead of checking "Batch not found with Id : 10", I validated only "Batch not found".

This approach made my negative tests environment‑independent and far more stable.


🧵 5. Challenge: Extracting Deeply Nested JSON

Endpoints like “Programs with Users” and “Users with Roles” returned deeply nested JSON structures. Extracting fields like userLoginEmail or roleName using simple JsonPath became messy and error‑prone.

How I resolved it (expanded explanation)

I used advanced JsonPath expressions to navigate nested arrays. When the structure became too complex, I deserialized the entire response into custom POJO classes. This allowed me to access nested fields using getters instead of long JsonPath strings.

For example:

java

List<User> users = response.jsonPath().getList("users", User.class);

This made my validations cleaner, more readable, and easier to maintain.


🗂️ 6. Challenge: Unique Constraints Causing Test Failures

The LMS system enforced uniqueness for:

  • Program Name

  • Batch Name

  • Phone Number

  • Skill Name

My tests initially failed because I reused the same values across multiple runs.


How I resolved it (expanded explanation)

I implemented dynamic data generation using:

  • System.currentTimeMillis()

  • UUID.randomUUID()

  • Faker-generated names and emails

This ensured that every test run used fresh, unique data. It also prevented conflicts when multiple testers ran the suite simultaneously.


🔐 7. Challenge: Login & Token Handling for Protected Endpoints

The Login API returned a token required for most protected endpoints. Initially, I forgot to include the token in some requests, and sometimes the token expired mid‑suite.

How I resolved it (expanded explanation)

I built a TokenManager utility that:

  • Generated a token only when needed

  • Cached it in memory

  • Automatically refreshed it when expired

  • Added it to every request through a RequestSpecification filter

This eliminated all authentication-related failures and made my suite more resilient.


🧪 8. Challenge: Handling Different Response Formats Across Endpoints

Some endpoints returned arrays, some returned objects, some returned messages, and the V2 Users API returned a faceted structure. This inconsistency made parsing responses difficult.

How I resolved it (expanded explanation)

I created response handler utilities that abstracted the parsing logic. These utilities handled:

  • Arrays

  • Single objects

  • Message-only responses

  • Nested structures

This allowed me to write clean, reusable validation code and adapt to any response format.


⭐ Final Summary (Expanded)

By solving these challenges, I didn’t just automate the LMS APIs — I built a scalable, intelligent, and maintainable Rest Assured automation framework. This project strengthened my skills in:

  • Designing reusable payload builders

  • Managing dynamic data

  • Automating hierarchical workflows

  • Handling nested JSON

  • Implementing token-based authentication

  • Standardizing error validations

  • Building utility-driven frameworks

These solutions reflect real-world engineering practices and demonstrate my ability to handle complex API ecosystems with confidence.

 
 

+1 (302) 200-8320

NumPy_Ninja_Logo (1).png

Numpy Ninja Inc. 8 The Grn Ste A Dover, DE 19901

© Copyright 2025 by Numpy Ninja Inc.

  • Twitter
  • LinkedIn
bottom of page