Tags are used to provide additional information for the request and contribute to a better control over deduplication. A request can only contain a unique tag with same name and value.
There are three types of tags.
Case
Label
Annotation
1. Case
Case is a tag that is used to create a mock at a particular branching which needs to be covered in a request and does not let it get deduplicated if there is a version of the same request already present.
Case is created with the following syntax in source code.
Case contributes to the deduplicating hash and essentially creates a new version of the request if the latter was already present. Typically this is used to create different versions of the same request to increase code coverage and cover all branching statements.
Case can also be added in the root context of an application. If a case is added in root context then the same case is inserted in every incoming request when the server span is created.
Case is created at root context with the following syntax in source code.
Imagine an api where the logic splits based on a requestParam action.
Suppose, we hit a request with requestParam itemType as credit, and then with requestParam itemType as debit then the 2nd request would get deduplicated (so there won't be generation of test case for it).
To generate a test case for both the branches we can use case tag like this:
@GetMapping("/updateBalance")
public ResponseEntity<?> updateBalance(@RequestParam("userId") String userId,
@RequestParam("amount") BigDecimal amount,
@RequestParam("action") String action) {
// Use the CASE tag to record the branch of execution based on the action parameter.
HypertestAgent.addTag("action", action, EnumManager.TagType.CASE);
// Fetch the current balance for the user
BigDecimal currentBalance = userService.getBalance(userId);
if ("credit".equalsIgnoreCase(action)) {
// Credit branch: add the specified amount to the current balance
BigDecimal updatedBalance = currentBalance.add(amount);
userService.updateBalance(userId, updatedBalance);
return ResponseEntity.ok("User " + userId + " credited with " + amount +
". Current balance: " + updatedBalance);
} else if ("debit".equalsIgnoreCase(action)) {
// Debit branch: subtract the specified amount from the current balance
BigDecimal updatedBalance = currentBalance.subtract(amount);
userService.updateBalance(userId, updatedBalance);
return ResponseEntity.ok("User " + userId + " debited with " + amount +
". Current balance: " + updatedBalance);
} else {
// Invalid action handling
return ResponseEntity.badRequest().body("Invalid action specified.");
}
}
2. Label
Label is a tag that is used to create a mock inside a particular route to avoid more versions of the same request due to difference in response schema. If there is a label inside a request, then only the cases and labels are considered for creating the deduplicating hash value thereby retaining the desired version of the request.
Label is created with the following syntax in source code.
Label can also be added in the root context of an application. If a label is added in root context then the same label is inserted in every incoming request when the server span is created.
Label is created at root context with the following syntax in source code.
Imagine an endpoint that returns user details in two different response schemas based on the detailLevel query parameter.
The underlying business logic remains similar, but the schema of outbound JPA call varies. Without intervention, these schema differences would result in multiple test cases.
By adding a Label tag, you ensure that the deduplication process considers only your defined label value (e.g., a fixed output schema version), thus retaining a single desired version of the request.
@GetMapping("/users")
public ResponseEntity<?> getUser(@RequestParam("detailLevel") String detailLevel) {
// By adding a label with a constant value (e.g., "v1"),
// we ensure that differences in the output details don't result in separate test cases.
HypertestAgent.addTag("outputSchema", "v1", EnumManager.TagType.LABEL);
if ("full".equals(detailLevel)) {
// Full branch: returns comprehensive user details.
User fullUser = userService.getFullUser();
return ResponseEntity.ok(fullUser);
} else {
// Basic branch: returns minimal user details.
User basicUser = userService.getBasicUser();
return ResponseEntity.ok(basicUser);
}
}
3. Annotation
Annotation is a tag that is used to create an unimportant mock inside a route to provide additional context to the request. This does not contribute to the deduplicating hash.
Annotation is created with the following syntax in source code.
Annotation can also be added in the root context of an application. If a annotation is added in root context then the same annotation is inserted in every incoming request when the server span is created.
Annotation is created at root context with the following syntax in source code.
In this scenario, there are 2 kind of APIs one for handling user operations (such as creating a user and logging in), while the other manages order-related operations.
The annotations add metadata that can later be used on Hypertest dashboard to filter or in .htTestConf.js to run only selected groups of APIs.
@RestController
public class Controller {
@PostMapping("/create")
public ResponseEntity<?> createUser(@RequestBody User user) {
// Annotate this endpoint as belonging to the "user" group.
HypertestAgent.addTag("apiGroup", "user", EnumManager.TagType.ANNOTATION);
// Business logic for creating a user
userService.createUser(user);
return ResponseEntity.ok("User created successfully");
}
@PostMapping("/login")
public ResponseEntity<?> loginUser(@RequestBody LoginRequest loginRequest) {
// Annotate this endpoint as belonging to the "user" group.
HypertestAgent.addTag("apiGroup", "user", EnumManager.TagType.ANNOTATION);
// Business logic for logging in a user
boolean success = userService.login(loginRequest);
if (success) {
return ResponseEntity.ok("User logged in successfully");
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid credentials");
}
}
@PostMapping("/place")
public ResponseEntity<?> placeOrder(@RequestBody Order order) {
// Annotate this endpoint as belonging to the "order" group.
HypertestAgent.addTag("apiGroup", "order", EnumManager.TagType.ANNOTATION);
// Business logic for placing an order
orderService.placeOrder(order);
return ResponseEntity.ok("Order placed successfully");
}
}