On a test for response body keys, how do I output in the test result what keys are either missing or extra?

My question:
I have a series of checks for keys:

pm.expect(jsonData).to.have.keys(definedArrayOfKeys);

When the test fails, I would like Runner to output which keys are either observed and missing from my list, or more importantly, not observed and missing from the response.

In runner/test view/monitors, I get this ugly blob back:

Test 'object returns expected keys | AssertionError: expected { Object (apple, mandarin, …) } to have keys ‘apple’, ‘mandarin’, ‘peach’, ‘potato’, ‘corn’, ‘sprouts’, ‘banana’, ‘oranges’, ‘peanuts’, ‘candy’, ‘id’, ‘oil’, ‘yogurt’

And I have to compare the response and keys list manually. Not efficient.

I’m currently console.logging all this, but I have to manually compare as a person still to see which values are different. I sort of want… a .diff function, maybe?

I would like to see something like:

Test object returns expected keys | AssertionError: expected { Key: apple, but it’s missing }

It would not be ideal to have to check for each key individually. Some of these responses have more than 50 key:value pairs per object.

Hi @award-bounteous,

I’m not sure exactly how your expected/actual objects are structured, so I’ve made some assumptions, but here are a couple of ways (with examples) that I might choose to do it, both involving iterating over the lists.

Firstly, this will check every item in definedArrayOfKeys individually, and will fail when it hits the first error. It’s quick and easy to read, but will only tell you of the first failure:

definedArrayOfKeys = {a: 1, b: 2, c: 3}
jsonData = {b: 2}

for (var key of Object.keys(definedArrayOfKeys)) {
     pm.expect(jsonData).to.include.key(key)
}

// outputs: AssertionError: expected { b: 2 } to contain key 'a'

You could get all of the missing keys by writing each missing key to a list, and then expecting that list to be empty:

definedArrayOfKeys = {a: 1, b: 2, c: 3}
jsonData = {b: 2}

var missingKeys = [];
for (var key of Object.keys(definedArrayOfKeys)) {
    if(!jsonData.hasOwnProperty(key)) {
        missingKeys.push(key);
    }
}
pm.expect(missingKeys).to.be.empty;

// outputs: AssertionError: expected [ 'a', 'c' ] to be empty

Edit: Just spotted the other half of your question (identifying items that are found in jsonData, but weren’t in your expected data); you could just repeat this loop but switching the lists (iterate over jsonData, check whether any of the keys are missing from definedArrayOfKeys)

But maybe there’s a built-in method which can do this more effectively. My main reason for replying is so that I get notified if someone has a better answer :smiley: