{"id":5351,"date":"2023-01-20T09:25:34","date_gmt":"2023-01-20T08:25:34","guid":{"rendered":"https:\/\/blog.besharp.it\/?p=5351"},"modified":"2023-01-20T14:12:19","modified_gmt":"2023-01-20T13:12:19","slug":"easy-integration-testing-using-postman-and-newman","status":"publish","type":"post","link":"https:\/\/blog.besharp.it\/easy-integration-testing-using-postman-and-newman\/","title":{"rendered":"Easy Integration testing using Postman and Newman"},"content":{"rendered":"\n
Welcome back to the Proud2beCloud<\/strong> blog. Today we\u2019ll be exploring how to implement integration testing for your API directly into your pipelines by leveraging Postman and Newman.<\/p>\n\n\n\n We\u2019ll talk about Newman, Pipelines and CodeBuild, Testing, scripting, sharability, and much more.<\/p>\n\n\n\n Let’s dive into how to test APIs automatically and… start testing today!<\/p>\n\n\n\n To be able to safely deploy APIs in production we want to be sure that the expected behavior is going to be followed. With unit testing alone, we cannot be sure of that.<\/strong> <\/p>\n\n\n\n Let’s put a simple example: imagine having an application unit tested perfectly, hence the code is working as expected given a known input. In front of the application, we\u2019ll then have a user calling an API and passing some data to the app. Unit tests are simply not enough; we want to be able to test the effective format of variables passed to the application logic, test headers, and body prior to utilization, timeouts, different status code, and other test cases: write tests for integration.<\/p>\n\n\n\n In real-world applications, behaviors change over time, and modules connected to each other may face changes in how the data is passed onto the other and in API requests.<\/p>\n\n\n\n We may have some third-party applications integrated into our solution where we need to call external API and test using their responses.<\/p>\n\n\n\n Sometimes (but it should not happen!<\/em>) developers deploy applications quickly, maybe without unit testing and that\u2019s where integration testing comes in clutch.<\/p>\n\n\n\n Those are some reasons why we need this integration testing: to test how various modules (route, validation, application, data layer) interact with each other, after changes and overtime.<\/strong><\/p>\n\n\n\n In our case, talking about API Gateway and Lambda, we also want to test the route, decorators, and whatever is in between the user and the application code. <\/p>\n\n\n\n Best practices:<\/p>\n\n\n\n <\/p>\n\n\n\n <\/p>\n\n\n\n In Postman two different types of variables are available:<\/p>\n\n\n\n Those are variables for the whole collection, not depending on what environment we are in.<\/p>\n\n\n\n They should be utilized for the value of parameters that are environment-independent like custom application names, business names, etc.<\/p>\n\n\n\n <\/p>\n\n\n <\/p>\n\n\n\n In a collection it is also possible to create multiple environments; we can define variables in these environments too.<\/p>\n\n\n\n <\/p>\n\n\n <\/p>\n\n\n\n If the same variable key is present in an environment and<\/em> in the collection, the environment wins and the collection variable will be overridden.<\/p>\n\n\n\n Best practices, in my opinion:<\/p>\n\n\n\n Create at least a local env, an integration test one, and\/or a development one. Switching between environments is really useful and quick and setting up a variable like {{base_url}} with various values is gonna become handy.<\/p>\n\n\n\n Note: Postman<\/strong> already has some variables by default, like {{randomEmail}}, {{randomInt}, {{$randomAlphaNumeric}} which are really useful to randomize body in POST and PUT API calls.<\/p>\n\n\n\n Both for the whole collection and for a single API call, we have the possibility to use a pre-Request script, <\/strong>which is a js-like script to do various stuff. Here\u2019s some example: <\/p>\n\n\n\n Thanks to this script, it will be possible to have access to the enum_val<\/em> variable that will have a random value between \u2018value_one\u2019 and \u2018value_two\u2019.<\/p>\n\n\n\n This is useful and should be added to the Collection pre-request script.<\/p>\n\n\n\n <\/p>\n\n\n <\/p>\n\n\n\n 2. Set up the next request. Postman by default will run the collection in the order in which APIs are written, if we want to change that order (to leave DELETE last for example), we can do that by using the pre-request script of the single API call:<\/p>\n\n\n\n <\/p>\n\n\n\n To stop the collection, we can use the same function and set the parameter to null:<\/p>\n\n\n\n Is good practice to have a folder structure in our collection as stated before, but lots of times we have dependencies in between entities, so we want to set the setNextRequest<\/em> like this:<\/p>\n\n\n\n Entity1.POST \u2192 Entity1.GET \u2192 Entity1.PUT \u2192 Entity2.POST \u2192 Entity2.GET \u2192 Entity2.PUT \u2192 \u2026 \u2192 \u2026 \u2192 \u2026 \u2192 EntityN.Delete \u2192 EntityN-1.DELETE \u2192 \u2026 \u2192 Entity2.DELETE \u2192 Entity1.DELETE<\/p>\n\n\n\n To be able to create, update and access objects until we need them and, at last, delete everything back to the main entity.<\/p>\n\n\n\n As the title hints, to do some integration tests, we need tests. <\/p>\n\n\n\n In this case, there\u2019s a dedicated tab where we can execute the script AFTER the API call has been done, work with the response, and test that all reflects what we expect.<\/p>\n\n\n\n We\u2019ll use this section for 2 main reasons:<\/p>\n\n\n\n In Other API I can then use that ID by calling the variable {{id_entity}} With that, the variable will definitely have a value and we\u2019ll test the calls sequentially with dynamic data.<\/p>\n\n\n\n 2. Test the response<\/strong> <\/p>\n\n\n\n We can invoke a postman function .test <\/em>to actually impose a check on something, based on a boolean evaluation, the test will either fail or succeed.<\/p>\n\n\n\n This script gets the response and checks both the body and the status code of the response. If everything inside .test() is correct the test will pass. <\/p>\n\n\n\n A dedicated tab is presented on Postman and, as we\u2019re gonna see, Newman will also give a \u2018report\u2019 on how many requests were launched and how many of them failed, and why.<\/p>\n\n\n\n <\/p>\n\n\n\n <\/p>\n\n\n\n Explained the various steps and features that Postman allows us to use, the process to create a complete collection, ready to be used for integration testing can resemble something like that:<\/p>\n\n\n\n Integrating your collection in a pipeline is actually pretty straightforward.<\/p>\n\n\n\n <\/p>\n\n\n <\/p>\n\n\n\n 2. Export, if present, the environment. A JSON with the environment variables will be downloaded<\/p>\n\n\n\n 3. Put both files in the repository<\/p>\n\n\n\n 4. Create a Code Build step in CodePipeline. It is important to install Newman from npm. The buildspec should look something like this:<\/p>\n\n\n\n <\/p>\n\n\n\n 5. Create the run_integration_test.sh<\/em> file where we\u2019ll actually run the collection like this:<\/p>\n\n\n\n By doing so, Newman will run the postman collection using the environment variable present in the integration_test_env <\/em>file. <\/p>\n\n\n\n The collection will run in order from the first API and then following the trace created by the .setNextRequest.<\/p>\n\n\n\n Every request with a test written will be evaluated; if even one throws an error or doesn\u2019t return what\u2019s expected, the collection will have a KO status and the code build step will fail.<\/p>\n\n\n\n Sharability<\/strong>: via workspaces, it is possible to create a workspace for every client\/project and share it with the team (free up to 3 users) or share it by a link to viewers. The editors will see the collection updated in real time from other colleagues and won\u2019t need to import it every time.<\/p>\n\n\n\n AWS Environment: <\/strong>to be able to actually call APIs we need the code to be deployed prior to testing, this is not feasible for the production environment and often for staging it can be an issue, too.<\/p>\n\n\n\n We found a solution by deploying every time, with every pipeline that needs integration testing (staging & production), on a shadow env<\/em> which is actually present on AWS with API GW, Lambdas, etc.. but is not connected to a CloudFormation dedicated stack and does not have a pipeline either.<\/p>\n\n\n\n With that we can safely deploy on \u2018integration test env\u2019 , test the API and even if the deployment fails we won\u2019t have affected real environments.<\/p>\n\n\n\n Integration testing is crucial in application development and will make sure that production will behave as we expect.<\/p>\n\n\n\n To do that, tools like Postman and Newman are super useful and almost completely configurable to best fit business needs; they are even codebase-agnostic as it\u2019s just an npm package running a .json so they can be integrated into python projects, node ones, etc..<\/p>\n\n\n\n Integrating them in a dedicated shadow environment on AWS and executing them in the pipeline will make your CI\/CD more reliable and will make it easy to control your code which is always a good idea.<\/p>\n\n\n\n Hope this article helped you out! Feel free to leave a comment with questions, or doubts, or tell us your experience with integration testing.<\/p>\n\n\n\n Stay tuned for our next article and, as always, be #Proud2beCloud<\/strong>!<\/p>\n\n\n\nWhy should I need to do integration testing?<\/h2>\n\n\n\n
Let\u2019s have a quick look at Postman<\/h2>\n\n\n\n
\n
<\/figure>\n\n\n\n
Variables<\/h2>\n\n\n\n
\n
Collection:<\/h3>\n\n\n\n
<\/figure><\/div>\n\n\n
Environment:<\/h3>\n\n\n\n
<\/figure><\/div>\n\n\n
Pre-request script<\/h2>\n\n\n\n
\n
<\/figure><\/div>\n\n\n
postman.setNextRequest('update entity\u2019);<\/em><\/code><\/pre>\n\n\n
<\/figure><\/div>\n\n\n
postman.setNextRequest(null).<\/em><\/code><\/pre>\n\n\n\n
Tests<\/h2>\n\n\n\n
\n
USE CASE eg:<\/strong> I\u2019ll execute a POST, expecting a new ID to be created. I want to be able to use the ID in a subsequent GET call. I can do that by getting the response, parsing it to get the ID, and put it in an env variable previously created. <\/li>\n<\/ol>\n\n\n\n
HOW TO:<\/strong><\/p>\n\n\n\n\n
<\/li>\n<\/ul>\n\n\n\nvar jsonData = JSON.parse(responseBody);\npostman.setEnvironmentVariable(\"productId\", jsonData.entityId);<\/code><\/pre>\n\n\n\n
pm.test(\"Create entity ok\", function () {
var jsonData = pm.response.json();
pm.response.to.have.status(201);
pm.expect(jsonData.message).to.contain('Entity created');
});<\/code><\/pre>\n\n\n\n<\/figure>\n\n\n\n
Recap: complete Postman collection<\/h2>\n\n\n\n
\n
Suggested POST, GET, PUT, and after everything, all the DELETEs starting from the smallest entity going up the hierarchy.<\/li>\n\n\n\nCollection in repository and Newman<\/h2>\n\n\n\n
\n
<\/figure><\/div>\n\n\n
version: 0.2
phases:
install:
runtime-versions:
nodejs: 14
build:
commands:
- npm install -g newman
- .\/run_integration_test.sh<\/code><\/pre>\n\n\n\n#!\/bin\/bash\n\nnewman run postman_collection.json -e integration_test_env.json<\/code><\/pre>\n\n\n\n
Additional notes<\/h3>\n\n\n\n
Conclusion<\/h2>\n\n\n\n
\n\n\n\nAbout Proud2beCloud<\/h4>\n\n\n\n