{"id":5373,"date":"2023-01-20T09:25:34","date_gmt":"2023-01-20T08:25:34","guid":{"rendered":"https:\/\/blog.besharp.it\/?p=5373"},"modified":"2023-01-20T14:12:58","modified_gmt":"2023-01-20T13:12:58","slug":"integration-testing-con-postman-e-newman","status":"publish","type":"post","link":"https:\/\/blog.besharp.it\/it\/integration-testing-con-postman-e-newman\/","title":{"rendered":"Integration testing con Postman e Newman"},"content":{"rendered":"\n
Bentornato sul nostro blog Proud2beCloud! <\/p>\n\n\n\n
Oggi andremo ad esplorare come implementare test d\u2019integrazione per le tue API direttamente all\u2019interno di pipeline utilizzando Postman e Newman.<\/p>\n\n\n\n
Parleremo di Newman, Pipeline, Codebuild, Testing, Scripting, condivisibilit\u00e0 della soluzione e molto altro.<\/p>\n\n\n\n
Cominciamo!<\/p>\n\n\n\n
Avere la possibilit\u00e0 di rilasciare API in sicurezza in produzione ed avere la certezza che il comportamento atteso sia rispettato \u00e8 cruciale. Solo con unit test non possiamo avere questo tipo di certezza.<\/strong><\/p>\n\n\n\n Ecco un esempio: immagina di avere un\u2019applicazione unit testata perfettamente. Dato un input noto, il codice funziona perfettamente. Davanti al codice applicativo abbiamo un utente che chiama un API e invia dati all\u2019applicazione.<\/p>\n\n\n\n Gli Unit test non sono abbastanza; vogliamo essere sicuri che anche la chiamata sia valida, testato header, body prima dell\u2019applicativo, timeout, status code e vari tipi di dati e metadati relativi alla chiamata in s\u00e8 e non solo alla logica.<\/p>\n\n\n\n In applicazioni reali, col passare del tempo i comportamenti utente e le applicazioni cambiano, moduli connessi tra di loro \u00e8 probabile che vengano modificati o che venga modificato come i dati sono passati tra di essi.<\/strong><\/p>\n\n\n\n Potremmo addirittura avere applicazioni terze parti integrate con la nostra soluzione e non avremmo la possibilit\u00e0 di effettuare unit test.<\/p>\n\n\n\n Altre volte (anche se questo non dovrebbe capitare!), gli sviluppatori rilasciano applicazioni in velocit\u00e0 senza test completi ed esaustivi. Ecco dove i test d\u2019integrazione vengono in nostro aiuto.<\/p>\n\n\n\n Queste appena citate sono alcune delle motivazioni principali per cui \u00e8 necessario utilizzare anche i test di integrazione.<\/p>\n\n\n\n Nel nostro caso, parlando di API Gateway e Lambda, vogliamo anche testare le rotte, i decoratori e tutto ci\u00f2 che si frappone tra il client e il codice applicativo.<\/p>\n\n\n\n Best practices:<\/p>\n\n\n\n <\/p>\n\n\n <\/p>\n\n\n\n In Postman abbiamo due tipi di variabili differenti:<\/p>\n\n\n\n Queste sono variabili utilizzate da tutta la collection, indipendentemente dall\u2019ambiente in cui siamo. Dovrebbero essere utilizzate per parametri che sono indipendenti dall\u2019ambiente come il nome dell\u2019applicazione, variabili custom del business, etc.<\/p>\n\n\n\n <\/p>\n\n\n <\/p>\n\n\n\n In Postman \u00e8 possibile creare ambienti diversi. Possiamo definire variabili all\u2019interno di questi ambienti come per la collection: <\/p>\n\n\n\n <\/p>\n\n\n <\/p>\n\n\n\n Se la stessa chiave di una variabile \u00e8 presente sia come variabile di Collection, che di ambiente, verr\u00e0 utilizzata quella di ambiente e quella di Collection sar\u00e0 ignorata.<\/p>\n\n\n\n Creare almeno un ambiente locale, uno per integration test e uno per l\u2019ambiente di sviluppo. Switchare tra ambienti semplificher\u00e0 di molto i test diretti verso API Gateway senza dover mai modificare le singole chiamate.<\/p>\n\n\n\n Nota: Postman<\/strong> di default mette a disposizione gi\u00e0 un set di variabili come {{randomEmail}}, {{randomInt}, {{$randomAlphaNumeric}} ed altre, molto utili per la randomizzazione del body in chiamate POST e PUT.<\/p>\n\n\n\n Sia per la Colelction, che per una singola chiamata API, c\u2019\u00e8 la possibilit\u00e0 di usare la pre-request script, <\/strong>che \u00e8 uno script js-like eseguito prima della chiamata API o dell\u2019inizio dell\u2019esecuzione della collection. Ecco alcuni esempi:<\/p>\n\n\n\n L\u2019esecuzione di questo script andr\u00e0 a settare nella variabile di collcection enum_val<\/em> un valore random tra \u2018value_one\u2019 e \u2018value_two\u2019<\/p>\n\n\n\n Molto utile per randomizzare variabili con valori custom, andr\u00e0 scritto nel pre-request di collection:<\/p>\n\n\n\n <\/p>\n\n\n <\/p>\n\n\n\n 2. Settare la prossima API eseguita. Postman di default eseguir\u00e0 la collection nell\u2019ordine in cui sono state inserite le chiamate API. Se vogliamo cambiare quest\u2019ordine (eseguendo ad esempio le DELETE alla fine), possiamo farlo usando la pre-request della singola chiamata come si seguito:<\/p>\n\n\n\n <\/p>\n\n\n\n Per fermare la collection possiamo usare la stessa funzione settando come parametro null: <\/em><\/p>\n\n\n\n \u00c9 una buona pratica avere una colleciton strutturata come abbiamo detto in precedenza. La maggior parte delle volte per\u00f2 abbiamo entit\u00e0 che dipendono da altre e non possiamo quindi eliminare l\u2019entit\u00e0 principale prima di aver eseguito test sull\u2019altra. <\/p>\n\n\n\n Vogliamo quindi scrivere le nostre nextRequest secondo un ordine di questo tipo:<\/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 Saremo cos\u00ec in grado di creare, modificare ed accedere ad oggetti finch\u00e9 ne abbiamo necessit\u00e0 e cancellarli in cascata solo alla fine.<\/p>\n\n\n\n Come suggerisce il titolo, per eseguire test d\u2019integrazione, abbiamo bisogno di test.<\/p>\n\n\n\n In questo caso, abbiamo un tab dedicato \u2018test\u2019<\/em> all\u2019interno di ogni singola chiamata API e verr\u00e0 eseguito dopo l’esecuzione della chiamata in modo da poter accedere anche alla risposta.<\/p>\n\n\n\n Useremo questa sezione per due motivi principali:<\/p>\n\n\n\n USE CASE esempio:<\/strong> esecuzione di una POST, mi aspetto che venga creato un nuovo ID e voglio poterlo utilizzare in una seguente chiamata in GET. Posso farlo recuperando la risposta, parsandola e inserendo il valore all\u2019interno di una variabile.<\/p>\n\n\n\n Nella altre API potr\u00f2 quindi utilizzare la variabile che \u00e8 stata valorizzata in maniera dinamica es {{id_entity}}<\/p>\n\n\n\n Avremo quindi valorizzato la nostra variabile id_entity<\/em> <\/em><\/strong> con l\u2019id appena creato in maniera dinamica.<\/p>\n\n\n\n 2. Testare la risposta<\/p>\n\n\n\n All\u2019interno dello stesso tab possiamo invocare la funzione .test <\/em>di postman e aggiungere un check sulla risposta, su qualsiasi parte di essa. <\/p>\n\n\n\n Il test sar\u00e0 una valutazione True | False, il test quindi sar\u00e0 OK o KO. <\/p>\n\n\n\n Questo script utilizza la response e controlla sia una parte del body che lo status code. <\/p>\n\n\n\n Se tutto ci\u00f2 che viene testato all\u2019interno della funzione .test() \u00e8 corretto, il test verr\u00e0 superato e risulter\u00e0 un test \u2018verde\u2019.<\/p>\n\n\n\n Una tab dedicata, come in screen, \u00e8 presente in Postman e, come andremo a vedere, Newman fornir\u00e0 inoltre un report su quante chiamate sono state eseguite, quanti test, quali sono passati, quali no e come mai.<\/p>\n\n\n\n <\/p>\n\n\n\n <\/p>\n\n\n\n Spiegati i vari step e feature che vengono offerte dall’utilizzo di Postman, riassumiamo gli step per impostare una collection pronta per gli integration test:<\/p>\n\n\n\n Integrare la propria collection all\u2019interno di Code Pipeline \u00e8 piuttosto semplice:<\/p>\n\n\n\n <\/p>\n\n\n <\/p>\n\n\n\n 2. Esportare, se presente, l\u2019ambiente. Un JSON con le variabili di ambiente verr\u00e0 scaricato<\/p>\n\n\n\n 3. Inserire entrambi i file nella repository<\/p>\n\n\n\n 4. Creare uno step di Code Build in CodePipeline. \u00c9 importante installare newman, il buildspec potrebbe essere una cosa simile a:<\/p>\n\n\n\n 5. Creare un file bash run_integration_test.sh<\/em> dove andremo ad eseguire la collection, in questo caso passando anche il file dell\u2019ambiente \u2018integration_test\u2019:<\/p>\n\n\n\n Semplicemente cos\u00ec, Newman eseguir\u00e0 la collection Postman con le variabili d\u2019ambiente e seguendo dalla prima API l\u2019ordine definito tramite le funzioni setNextRequest().<\/p>\n\n\n\n Ogni chiamata con un test definito sar\u00e0 eseguita e valutata. Se anche solo un test fallisse lo step di build andrebbe in errore e la pipeline si fermerebbe. Sar\u00e0 presente all\u2019interno dei log il report sulle chiamate in modo da fare troubleshooting sulla\/sulle chiamata\/e in errore.<\/p>\n\n\n\n Condivisibilit\u00e0<\/strong>: tramite i workspace, \u00e8 possibile creare workspace per cliente e condividerlo con il team (gratis fino a 3 membri) o condividere solo in view la collection.<\/p>\n\n\n\n Gli editor vedranno la collection aggiornata in tempo reale se modificata da altri membri del team e non dovranno importarsela ogni volta.<\/p>\n\n\n\n AWS Environment: <\/strong>per poter chiamare effettivamente le API \u00e8 nesessario che il codice sia rilasciato prima dello step di integration test, questo non sarebbe possibile farlo in ambienti come development o Produzione perch\u00e8 in caso di errore applicativo il rollback in pipeline non \u00e8 automatico.<\/p>\n\n\n\n La soluzione da noi adottata \u00e8 quella di creare un ambiente \u2018ombra\u2019. Ogni pipeline che esegue gli integration test, staging & production ad esempio, rilascer\u00e0 lo stesso pacchetto di codice applicativo su uno stack infrastrutturale dedicato per gli integration test: API Gateway, Lambda, etc. Questo ambiente avr\u00e0 cos\u00ec degli endpoint reali senza aver bisogno di una pipeline dedicata o di un setup dedicato lato codice.<\/p>\n\n\n\n Cos\u00ec possiamo sempre rilasciare il codice su questo ambiente, testarlo e, in caso di successo, rilasciarlo anche nell\u2019ambiente reale con la sicurezza che si comporter\u00e0 nello stesso modo (il pacchetto di codice \u00e8 lo stesso). <\/p>\n\n\n\n Su questo ambiente di integration test verranno eseguiti spesso rilasci dalle pipeline che si sovrascriveranno a vicenda, rilasciando ad esempio produzione e in seguito UAT con nuovo codice. <\/p>\n\n\n\n Non \u00e8 rilevante, l\u2019unica cosa importante \u00e8 che i test vengano eseguiti sul codice aggiornato.<\/p>\n\n\n\n L’Integration testing \u00e8 cruciale nello sviluppo di applicazioni web per garantire rilasci in produzione in sicurezza.<\/p>\n\n\n\n Per effetturali usiamo tool come Postman e Newman, configurabili e customizzabili per meglio adattarsi alle necessit\u00e0 di business. Questa soluzione \u00e8 agnostica rispetto al linguaggio di sviluppo, essendo semplicemente un pacchetto npm che va ad eseguire chiamate tramite un file .json. Pu\u00f2 essere integrato in progetti Python, Node, etc..<\/p>\n\n\n\n Integrare i test in un ambiente dedicato ed eseguirli direttamente all\u2019interno di pipeline rende la tua soluzione di CI\/CD pi\u00f9 sicura e affidabile; mentenere il controllo sul comportamento del codice scritto, non \u00e8 mai una brutta idea \ud83d\ude42 <\/p>\n\n\n\n Speriamo che questo articolo vi abbia lasciato buoni spunti per implementare una miglior strategia di testing. Lascia un commento per qualsiasi domanda o dubbio e raccontaci la tua esoperienza!<\/p>\n\n\n\n Rimani aggiornato sul mondo Cloud con i nostri prossimi articoli e, come sempre: #Proud2beCloud<\/strong>!<\/p>\n\n\n\nDiamo un\u2019occhiata a Postman<\/h2>\n\n\n\n
\n
<\/figure><\/div>\n\n\n
Variabili<\/h2>\n\n\n\n
\n
Collection:<\/h3>\n\n\n\n
<\/figure><\/div>\n\n\n
Ambiente:<\/h3>\n\n\n\n
<\/figure><\/div>\n\n\n
Best practice, secondo noi:<\/h3>\n\n\n\n
Pre-request script<\/h2>\n\n\n\n
\n
<\/figure><\/div>\n\n\n
<\/em> 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
Come farlo:<\/h3>\n\n\n\n
\n
var jsonData = JSON.parse(responseBody);\npostman.setEnvironmentVariable(\"id_entity\", jsonData.entityId);<\/code><\/pre>\n\n\n\n
pm.test(\"Create entity ok\", function () {\nvar jsonData = pm.response.json();\npm.response.to.have.status(201);\npm.expect(jsonData.message).to.contain('Entity created');\n});<\/code><\/pre>\n\n\n\n
<\/figure>\n\n\n\n
Riassunto: postman collection completa<\/h2>\n\n\n\n
\n
Collection in repository e Newman<\/h2>\n\n\n\n
\n
<\/figure><\/div>\n\n\n
version: 0.2\nphases:\n install:\n runtime-versions:\n nodejs: 14\nbuild:\n commands:\n - npm install -g newman\n - .\/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
Note addizionali<\/h3>\n\n\n\n
Conclusioni<\/h2>\n\n\n\n
\n\n\n\nAbout Proud2beCloud<\/h4>\n\n\n\n