Skip to content

Instantly share code, notes, and snippets.

@arifsuhan
Last active June 14, 2024 07:40
Show Gist options
  • Select an option

  • Save arifsuhan/beebfd886d84ede553429fec6d86cb58 to your computer and use it in GitHub Desktop.

Select an option

Save arifsuhan/beebfd886d84ede553429fec6d86cb58 to your computer and use it in GitHub Desktop.
Json compare, Assertion
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
import org.apache.jmeter.assertions.AssertionResult
import org.apache.jmeter.samplers.SampleResult
def expectedJsonFilePath = vars.get('filePath')
log.info(expectedJsonFilePath)
// Load the expected JSON from the file
def expectedJson = new JsonSlurper().parse(new File(expectedJsonFilePath))
// Get the response body from the HTTP Request sampler
def responseBody = prev.getResponseDataAsString()
// Parse the response JSON
def responseJson = new JsonSlurper().parseText(responseBody)
responseJson = responseJson.transactions[0]
// Compare the expected and actual JSON
def comparisonResult = compareJson(expectedJson, responseJson)
// Log the comparison result and JSON data
if (comparisonResult) {
log.info("The JSON response matches the expected JSON.")
log.info("Expected JSON: " + JsonOutput.prettyPrint(JsonOutput.toJson(expectedJson)))
log.info("Actual JSON: " + JsonOutput.prettyPrint(JsonOutput.toJson(responseJson)))
} else {
log.error("The JSON response does not match the expected JSON.")
log.info("Expected JSON: " + JsonOutput.prettyPrint(JsonOutput.toJson(expectedJson)))
log.info("Actual JSON: " + JsonOutput.prettyPrint(JsonOutput.toJson(responseJson)))
AssertionResult assertionResult = new AssertionResult("JSON Comparison Assertion")
assertionResult.setFailure(true)
assertionResult.setFailureMessage("The JSON response does not match the expected JSON.")
// SampleResult sampleResult = prev.getSampleResult()
// sampleResult.addAssertionResult(assertionResult)
// sampleResult.setSuccessful(false)
}
// Enhanced function to compare two JSON objects
boolean compareJson(def expected, def actual) {
if (expected == actual) {
return true
}
if (expected instanceof Map && actual instanceof Map) {
return compareMaps(expected, actual)
}
if (expected instanceof List && actual instanceof List) {
return compareLists(expected, actual)
}
return false
}
// Function to compare two maps with support for regex and boolean
boolean compareMaps(Map expected, Map actual) {
if (expected.size() != actual.size()) {
return false
}
for (entry in expected.entrySet()) {
def key = entry.key
def expectedValue = entry.value
def actualValue = actual.get(key)
if (expectedValue instanceof String && expectedValue.startsWith("regex:")) {
def pattern = expectedValue.substring(6)
if (!actualValue.toString().matches(pattern)) {
log.error("Mismatch at key '${key}': expected regex '${pattern}', got '${actualValue}'")
return false
}
} else if (expectedValue instanceof Boolean) {
if (expectedValue != actualValue) {
log.error("Mismatch at key '${key}': expected boolean '${expectedValue}', got '${actualValue}'")
return false
}
} else if (expectedValue instanceof Map) {
if (!compareMaps(expectedValue, actualValue)) {
log.error("Mismatch at key '${key}'")
return false
}
} else if (expectedValue instanceof List) {
if (!compareLists(expectedValue, actualValue)) {
log.error("Mismatch at key '${key}'")
return false
}
} else {
if (expectedValue != actualValue) {
log.error("Mismatch at key '${key}': expected '${expectedValue}', got '${actualValue}'")
return false
}
}
}
return true
}
// Function to compare two lists
boolean compareLists(List expected, List actual) {
if (expected.size() != actual.size()) {
log.error("List size mismatch: expected ${expected.size()}, got ${actual.size()}")
return false
}
for (int i = 0; i < expected.size(); i++) {
def expectedValue = expected[i]
def actualValue = actual[i]
if (expectedValue instanceof Map) {
if (!compareMaps(expectedValue, actualValue)) {
return false
}
} else if (expectedValue instanceof List) {
if (!compareLists(expectedValue, actualValue)) {
return false
}
} else {
if (expectedValue instanceof String && expectedValue.startsWith("regex:")) {
def pattern = expectedValue.substring(6)
if (!actualValue.toString().matches(pattern)) {
log.error("List mismatch at index ${i}: expected regex '${pattern}', got '${actualValue}'")
return false
}
} else if (expectedValue instanceof Boolean) {
if (expectedValue != actualValue) {
log.error("List mismatch at index ${i}: expected boolean '${expectedValue}', got '${actualValue}'")
return false
}
} else {
if (expectedValue != actualValue) {
log.error("List mismatch at index ${i}: expected '${expectedValue}', got '${actualValue}'")
return false
}
}
}
}
return true
}
// https://stackoverflow.com/questions/26049303/how-to-compare-two-json-have-the-same-properties-without-order
// https://stackoverflow.com/questions/201183/how-to-determine-equality-for-two-javascript-objects/16788517#16788517
// https://stackoverflow.com/questions/1068834/object-comparison-in-javascript
function compareJson(objA, objB) {
if(typeof(objA) === typeof(objA)){
keysA = Object.keys(objA).sort();
keysB = Object.keys(objB).sort();
return keysA.length === keysB.length && keysA.every(key => objA[key] === objB[key]);
}
return false;
}
// java - https://www.baeldung.com/jackson-compare-two-json-objects, https://github.com/fslev/json-compare
// python3 - https://pypi.org/project/json-diff
// js - https://www.npmjs.com/package/json-diff
// https://stackoverflow.com/questions/6526911/best-way-to-compare-two-json-files-in-java
jsonDiff = (obj1, obj2) => {
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) {
return false;
}
for (const key of keys1) {
if (!obj2.hasOwnProperty(key)) {
return false;
}
if (!valueDiff(obj1[key], obj2[key])) {
return false;
}
}
return true;
}
valueDiff = (value1, value2) => {
if (value2 instanceof RegExp) {
let re = new RegExp(value2);
return re.test(value1);
} else if (typeof value1 === 'object' && typeof value2 === 'object') {
const keys1 = Object.keys(value1);
const keys2 = Object.keys(value2);
if (keys1.length !== keys2.length) {
return false;
}
for (const key of keys1) {
if (!valueDiff(value1[key], value2[key])) {
return false;
}
}
return true;
} else if(typeof value1 == typeof value2 ){
return value1 === value2;
} else {
return false;
}
}
getFn = (name) => {
return eval(pm.variables.get(name));
}
baseFn = (flag,passMsg,failMsg) => {
if (flag){
pm.test(passMsg);
}else{
pm.test("Failed", ()=>{throw new Error(failMsg)});
}
}
pm.collectionVariables.set("getFn", getFn.toString());
pm.collectionVariables.set("baseFn", baseFn.toString());
pm.collectionVariables.set("jsonDiff", jsonDiff.toString());
pm.collectionVariables.set("valueDiff", valueDiff.toString());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment