Testing if a date sorting is correct in Postman

Hello,
I send a request which has a random date.

In pre-request Script:

pm.globals.set(‘hours’, _.random(10,23));
pm.globals.set(‘minutes’, _.random(10,59));
pm.globals.set(‘seconds’, _.random(10,59));
pm.globals.set(‘day’, _.random(10,30));
pm.globals.set(‘month’, _.random(10,12));
pm.globals.set(‘year’, _.random(2010,2019));

in body:

{
“eventtype”: “{{eventtype}}”,
“severity” : “{{severity}}”,
“description” : “{{event_description}}”,
“settingtime”: “{{year}}-{{month}}-{{day}}T{{hours}}:{{minutes}}:{{seconds}}”
}

Example output:

{
“eventtype”: “manual”,
“severity”: “warning”,
“description”: “fwquovfwwu”,
“settingtime”: “2018-12-27T11:30:53”
}

That request generate an event for me. After generating plenty of that kind of events I send another request with a TimeBegin parameter which should get every event for me which has a parameter “settingtime” greater than my parameter TimeBegin.

For example:


TimeBegin = 2016-11-18T11:41:51 and request should return every event which has a “newer” setting_time parameter than this.

I want to write a test which automatically checks if every generated event which had parameter setting_time greater than TimeBegin was returned by the response of the server. Moreover, checks if response is sorted correctly (in rising mode).

I would be very grateful for any kind of help. I use native Postman and Newman.

We can make use of moment.js and loadsh which are built into postman (available in the scripts).
Docs: https://learning.getpostman.com/docs/postman/scripts/postman_sandbox_api_reference/

MomentJS docs: https://momentjs.com/docs/#/query/is-before/

Step 1:
So we need timeBegin, so in the request where you generate the time begin, you should store that in an environment variable.
Instead of breaking the time into multiple variables you can directly store it as one single variable and also use it in the request body or I am sure you know how to get around that problem.

Step 2:
I have hardcoded the responseBody but you have to replace it with what the comment says.
Here’s the test script that’s going to help you out:

Test Script:

_ = require("lodash");

let moment = require('moment');
// Hardcoding the response body, replace this with
// responseBody = pm.response.json();
let responseBody = {
    rows: [
        {
            "setting_time": "2018-12-27T11:30:53"
        },
        {
            "setting_time": "2018-12-27T11:30:53"
        },
        {
            "setting_time": "2018-12-27T11:32:51"
        },
        {
            "setting_time": "2018-12-27T11:32:53"
        },
    ] 
}

pm.test('Are all dates after time begin and in correct sorted order', function () {
    let previousDate = null,
        timeBegin = pm.environment.get('timeBegin') || "2018-12-27T11:30:52",
        isDateAfterTimeBegin, // Will be used to check if date if time begin is before the given setting_time
        isBreakingSortOrder; // Will be used to check if the time is breaking the sort order

    areDatesInvalid = _.some(responseBody.rows, (row) => {
        isDateAfterTimeBegin = moment(timeBegin).isBefore(row.setting_time);

        isBreakingSortOrder = previousDate ? moment(previousDate).isBefore(row.setting_time) : false;

        previousDate = row.setting_time; // Storing this which will be used in next iteration to check if the sort order is not being broken

        return !isDateAfterTimeBegin && !isBreakingSortOrder;
    });

    pm.expect(areDatesInvalid).to.be.false;
});

Explanation:
I am checking if any of the dates are invalid - each date is always after the timeBegin.
Also, I am checking if any of the dates is breaking the sort order i.e each setting_time should be more than the previousDate.
For the first iteration, previousDate is null so that’s why there’s a conditional check in there.

Finally, if any of the date is invalid then _.some will return true that yeah some date is actually invalid and your test will fail.
Otherwise, the test will pass.

2 Likes

I was having a bit of a geek moment and thought I might be able to do a solution in straight javascript… this is what I came up with (borrowing @sivcan’s general approach)

let response_Body = {
    rows: [
        {"setting_time": "2018-12-27T11:30:53"},
        {"setting_time": "2018-12-27T11:30:53"},
        {"setting_time": "2018-12-27T11:32:51"},
        {"setting_time": "2018-12-27T11:32:53"}
    ] 
};
// Check if there are any rows with time less than timeBegin
const timeBegin = new Date("2018-12-27T11:30:51");
const anyRowsBeforeTimeBegin = response_Body.rows.find(
   row => new Date(row.setting_time) < timeBegin
);
pm.test("no RowsBeforeTimeBegin", () => {
    pm.expect(anyRowsBeforeTimeBegin).to.be.undefined;
});

// Check the order is correct
const rowsAsReceived = response_Body.rows; 
// Create a copy of the array, and sort it by date
const sortedRows = Array.from(rowsAsReceived).sort(
    (a, b) => new Date(a.setting_time) - new Date(b.setting_time)
);
// check if the arrays are both still in the same order
const orderHasNotChanged = sortedRows.every(
   (a,i) => a.setting_time === rowsAsReceived[i].setting_time
);
pm.test("orderHasNotChanged", () => {
    pm.expect(orderHasNotChanged).to.be.true;
});

Running that gives
image

If I change the input slightly

let response_Body = {
    rows: [
        {"setting_time": "2018-12-27T11:30:53"},
        {"setting_time": "2018-12-27T11:30:50"},//before timeBegin & out of order
        {"setting_time": "2018-12-27T11:32:51"},
        {"setting_time": "2018-12-27T11:32:53"}
    ] 
};

It does this


(the error messages could be more helpful)

Links for more details

2 Likes