Accessing Local Variables within a Global Function

I am able to implement this:

Collection Pre-requisite Script:

utils = {
    hello: function() {
        return 'hello';
    }
}

Request-level Test Script results to hello in my console when executing:

console.log(utils.hello());

Following this pattern, I have tests which are doing the same thing across my requests thus I’d like to reference them as a global function.

With the following, I am getting ReferenceError: scenario is not defined when I run my collection.

Collection Pre-requisite Script:

utils = {
    verifyStatusCode: function(pm) {
        pm.test("Verify status code", function() {
            pm.expect(pm.response.code).to.be.equal(scenario.expectedResponseCode);
            }
        );
    }
}

Request-level Test Script:

let scenario = {"expectedResponseCode": 200}; 
// I have other assertions thus I am referencing from a JSON
// Retaining expectedResponseCode only for the sake of example.

console.log("scenario: " + JSON.stringify(scenario)); 
// This results to the JSON above

console.log(utils.verifyStatusCode(pm)); 
// This results to undefined

Am I missing something in terms of initializing/referencing the variable scenario which is then used by the global function?

Note that I’m avoiding using eval() as advised here.

The following appears to work.

Pre-request script

utils = {
    verifyStatusCode: function(pm, expectedResponseCode) {
        pm.test("Verify status code", function() {
            pm.response.to.have.status(expectedResponseCode);
        });
    }
}

Tests tab

let scenario = {"expectedResponseCode": 200}; 

utils.verifyStatusCode(pm, scenario.expectedResponseCode);

Test Results

image

Negative Test

Changing the status code to 300.

image

You can’t console log the function like you are doing, as that will just produce “undefined”. But the function will trigger and the test results are produced as expected.

Thanks @michaelderekjones , that works!

Not really related to my question, but what is the difference between the two and why is the other preferred over the other?

pm.expect(pm.response.code).to.be.equal(scenario.expectedResponseCode);
pm.response.to.have.status(expectedResponseCode);

Let’s see if I can explain this correctly.

pm.test is the test library. It just takes the name of the test and a function that returns either true or false. (Passing or failing the test).

Within the pm.test function, you write assertions.

If any of the assertions fail, then the test fails immediately. (It’s a hard fail and doesn’t have the concept of soft assertions).

Therefore if you have a test function with 3-4 assertions. As soon as the first assertion fails, then the test will fail and the other assertions will not execute. Which may be an issue if you want the feedback of those tests (which would usually indicate it should be a separate test).

The following explains the different types of assertions.

Writing tests | Postman Learning Center

pm.expect is basically using Chai for its assertion library.

Expect / Should - Chai (chaijs.com)

pm.response is Postman’s implementation and gives you quick access to certain elements.

You can mix match the two types. It’s just that some of the elements are easier to surface using pm.response (like the status codes).

There is also an older “tests” library that predates pm.expect that still works (that I only found out about earlier this week) which allows you to write directly to the tests results.

tests['test 1'] = true
tests['test 2'] = false

let age = "18";
let name = "mark";

tests["Age is number"] = typeof(age) === "number";
tests["Name is string"] = typeof(name) === "string";
1 Like

Thanks for patiently explaining, @michaelderekjones!

Appreciate the links for my guidance, bookmarking!