CSV comparison to a responseBody

CSV comparison

  • The issue I am currently facing is that, I want to compare my responseBody to a CSV file, but it does not work as expected. I want to compare the csv row with the matching responseBody object.
  • The CSV file has multiple rows and columns, and the responseBody is an array of objects.
  • Platform Details - I am using windows 10 enterprise, the Postman desktop application and my postman version is : (v10.19)

This is currently my test :
expectedValueOP = pm.iterationData.get(‘Operation ID’);

responseBody.forEach(object => {
    pm.test(`Operation ID : ${object.code} matches`, () => {
        pm.expect(object.code).to.be.include(expectedValueOP);
        console.log(object.code);
        console.log(expectedValueOP);
    });
});

of course responseBody is defined as follows :

responseBody = pm.response.json();

Can you post an example response?

You also don’t really say what is not working. What is the code doing wrong?

Console log the object.code and expectedValueOP before the pm.expect assertion.

If the assertion fails, then it will stop executing any more code in that block.

However, shouldn’t the assertion be an equals comparison.

pm.expect(object.code).to.equal(expectedValueOP);

That would be the example responseBody :

[
    {
        "id": 121,
        "code": "111",
        "activity": "M",
        "furniture": {
            "id": 345,
            "code": "32-ES",
            "fieldCode": "32-ES",
            "familyCode": "M",
            "address": "AU",
            "addressComplement": "CLUB",
            "city": "LAS"
        },
        "areaCode": "E1",
        "address": {
            "address": "AU",
            "addressComplement": "CLUB",
            "district": null,
            "postalCode": "45",
            "city": "LAS",
            "latitude": "28",
            "longitude": "-15"
        },
        "workCenterCode": "DAY",
        "description": "Door",
        "reasonCode": "DET",
        "comment": "",
        "priority": "NORMAL",
        "creationDate": "2022-04-01T15:04:15.948",
        "creator": "U",
        "initialPlannedDate": "2022-04-01",
        "plannedDate": "2022-04-01",
        "plannedUntil": null,
        "plannedStartTime": null,
        "status": "PE",
        "plannedTo": "U0",
        "executedDate": "2022-04-01T15:29:42.197",
        "closingDate": null,
        "executedBy": "U",
        "providerId": null,
        "providerName": null,
        "order": null,
        "incidentCode": "I",
        "latestIntervention": null,
        "sequence": null,
        "isPunctual": true,
        "routeCode": null,
        "tourId": null,
        "activityType": "M",
        "plannedToName": "Carlos",
        "supervisorName": "Volo",
        "supervisorCode": "U0",
        "accountPayable": false,
        "vendorCode": null,
        "vendorName": null,
        "predefinedTemplate": null
    },
    {
        "id": 20,
        "code": "819",
        "activity": "MAT",
        "furniture": {
            "id": 21,
            "code": "E",
            "fieldCode": "206",
            "familyCode": "D",
            "address": "C.",
            "addressComplement": "LOCAL",
            "city": "SANTA"
        },
        "areaCode": "1",
        "address": {
            "address": "C.",
            "addressComplement": "LO",
            "district": null,
            "postalCode": "38",
            "city": "SANTA",
            "latitude": "28",
            "longitude": "-16"
        },
        "workCenterCode": "DAY",
        "description": "LCD",
        "reasonCode": "DT",
        "comment": "",
        "priority": "NORMAL",
        "creationDate": "2022-04-01T15:02:40.804",
        "creator": "U10",
        "initialPlannedDate": "2022-04-01",
        "plannedDate": "2022-04-01",
        "plannedUntil": null,
        "plannedStartTime": null,
        "status": "PF",
        "plannedTo": "U03",
        "executedDate": "2022-04-01T15:33:23.41",
        "closingDate": null,
        "executedBy": "U63",
        "providerId": null,
        "providerName": null,
        "order": null,
        "incidentCode": "I071",
        "latestIntervention": null,
        "sequence": null,
        "isPunctual": true,
        "routeCode": null,
        "tourId": null,
        "activityType": "MAT",
        "plannedToName": "Dan",
        "supervisorName": "Vasco",
        "supervisorCode": "U008",
        "accountPayable": false,
        "vendorCode": null,
        "vendorName": null,
        "predefinedTemplate": null
    }
],

console output :
O003569493

O003569493, which shows that they do match, and indeed the tests do pass for it. However the issue here is that after the the passes - so the values to match, it continues on with comparing the rest of the rows to that responseBody value, which of course fails. That is valid for all the comparisons, the value which matches - the test passes, but afterwards it goes through all the rest of the values, which fails.

Can you share what the CSV looks like?

It sounds like you have a CSV file with multiple lines in it, which you want to compare against a single request which returns an array of objects. With each line of the CSV matching against one of those objects.

You can’t do that as the Collection Runner will run your collection once for each line in the CSV file.

Is it just the “code” element you need to check?

I don’t think you need the array. I would use the JavaScript find or filter function against the array to find the object where the code equals the expected value, and the test then becomes as easy as checking that the results of the find is not undefined or null.

Your “expected result” data cannot be on separate lines in the CSV file.

Either add the codes you want to check as an array in a single column or consider using a JSON data file instead of a CSV and structure your JSON so everything sits under an array. This way, you should be able to iterate over your codes.

If you share your current CSV file, so I can confirm that I’m on the right path, I can show you how to present and iterate over the data file. (Tomorrow as I’m about to go to the pub) :slight_smile:

ID Id Type Status I Id AC Activity Type F field code F code Add Add complement D Postal code City Work center code Desc R C C P Pro E ID Creation date Initial planned date Planned date End date Executed Date F O Code S Name S Code F O Name Route Code Sequence V code V name Status
01 I072 NT NT MD-01032 MD-01032 IMA TICO 03 LAS PALMA Daily problem / ock ation NAL 2022-04-01T15:04:15.948 01/04/2022 01/04/2022 2022-04-01T15:29:42.197 U00 Voloan U45 Caobar Peormed
O19 I071 MAIT AINT ES-00206 ES06 C.C. LTTI 0 005 SANTA Daily maintenance LCD Di / Blank /No le oration NORL 2022-04-01T15:02:40.804 01/04/2022 01/04/2022 2022-04-01T15:33:23.41 U63 Vasel U8 Dl Pars rmed

This is how my CSV looks like (keep in mind that the data could not match, because I did in fact edit it, because it is confidential, but in reality it is exactly the same). There are 250+ more rows of the same kind.

When it comes to your question about only checking the code, I would need to check the fields - columns if they match, keep in mind that I am doing some mapping, because in the responseBody there are only the abbriviations of the actual CSV values.

Ok, this will be better structured as JSON.

The following is an example of an array with two objects. Each line of your CSV will be a separate object and you would include all of the relevant fields you want to check. I’ve only included three fields for testing purposes, but these would match your CSV headers.

[
    {
        "ID": 121,
        "address-city": "LAS",
        "workCenterCode": "DAY"
    },
    {
        "ID": 100,
        "address-city": "AU",
        "workCenterCode": "DAY"
    }
]

I would then recommend iterating over the JSON, and then searching the response based on the primary key which for this example, I’m using the ID.

This would return the object in your response for that primary key, which you can then target and assert the other fields.

// Step 1 - parse response
const response = pm.response.json();

// Step 2 - define data file. 
let testData = JSON.parse(pm.collectionVariables.get("testData"));
// You would change this to read from the data file.  
// You can access the iteration data from the special "data" variable
// let testData = data

// Step 3 - Iterate over the test data\input file
testData.forEach(element => {

    // Step 4 - Test each record in the input file
    // Using string literals to create a custom test case name
    // So its easier to know which record failed
    pm.test(`response keys match for ID ${element.ID}`, function () {

        // Step 5
        // Search the response using the ID from the testData
        let search = (response.find(obj => { return obj.id === element.ID }));

        // Step 6
        // You don't need to test the ID is correct
        // You can just check that the search is not undefined
        pm.expect(search).to.not.be.undefined;
        // console.log(search);

        // Step 7
        // You can now assert on the other fields
        // Example using bracket notation, just in case of special characters
        pm.expect(search.address.city).to.eql(element["address-city"]);
        // Example using dot notation
        pm.expect(search.workCenterCode).to.eql(element.workCenterCode);
    });
})

And the results are in…

image

Hello Mr.Jones,
Your solution did indeed work, but I had a bit of a stupid question. By the “iterating over the JSON” you mean the CSV converted to a JSON file or the responseBody,
However, I did try it with your example with my data, where I converted my CSV to a JSON file and everything worked flawlessly, please let me know if that is what you meant,
Thank you for your response in advance!

In my example, you are using a JSON data file and iterating over that. (Step 3).

The main iteration is against the data file, not the response (as you only have one response but with all of the elements\records in it).

There is an outer iteration, that the collection runner is performing, but as you have a single array, it should just run once. (Actually saying that, can you confirm that it is only running one request, not two, it might need to be modified slightly so that the array is under an initial object so it only runs once?)

You can also use an CSV file with a single header called JSON with the whole of the JSON body as the value or you could add this to a collection or environment variable in the same way. (Remember to JSON stringify when storing arrays and JSON parse when retrieving otherwise it will be treated as a string and fail).

You can use one of the online JSON minify applications to take your JSON body and remove all of the whitespace, etc and you would just paste that into the value.

But ideally, you would just convert your data file to JSON, as its much easier to work with (and amend when needed).

Everything works well, and thank you for the explanation I found it really helpful. I only have one remaining question regarding of how should I do the comparison, when a “white space” is involved for instance - Operation ID, how should it look like in my tests tab? With some form of brackets, for example - element[“Operation-ID”]?
I would guess the easiest way would be to create a variable and pass a string of the field that I want to access and have a white space in it?
P.S. Passing the field as a string works.

The issue afterwards with your example is that if my field is not defined in the CSV and it is null in the responseBody it should pass.

Thank you in advance!

If the field has a special character like a space, you would use the bracket notation with a string instead of dot notation (and you can mix the types as you see fit).

response.element["elementWithSpecialCharacter"].anotherElement
["response"]["element"]["elementWithSpecialCharacter"]["anotherElement"]

I always use dot notation unless it has special characters.

I tried it, works flawlessly, thanks Mr.Jones.

All in all, everything works perfectly now…
However, I am a bit dissapointed that it needs to be converted to a JSON type file, but it is the way to go for now.
Regardless, thanks you for your help, it is appriciated!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.