{"id":28882,"date":"2024-07-23T16:22:25","date_gmt":"2024-07-23T14:22:25","guid":{"rendered":"https:\/\/www.codemotion.com\/magazine\/?p=28882"},"modified":"2024-07-23T16:22:27","modified_gmt":"2024-07-23T14:22:27","slug":"le-api-di-bruno-assertion-e-test","status":"publish","type":"post","link":"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/","title":{"rendered":"Le API di Bruno \u2013 Assertion e Test"},"content":{"rendered":"\n<p>Tutti noi che lavoriamo pressoch\u00e9 quotidianamente con chiamate API, abbiamo trovato grandi compagni di viaggio nei Client dedicati, grazie ai quali possiamo:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Verificare il corretto funzionamento delle rotte che stiamo sviluppando.<\/li>\n\n\n\n<li>Provare il reale funzionamento degli entrypoint che ci vengono forniti da terze parti (ogni tanto la manualistica riserva interessanti sorprese).<\/li>\n\n\n\n<li>Capire cosa sta succedendo nel momento in cui ci viene aperto un bug.<\/li>\n<\/ul>\n\n\n\n<p>Per ottemperare queste attivit\u00e0 \u00e8 sufficiente impostare una request ed eseguirla, leggendo lo status della response e, se disponibile, valutare visivamente il payload restituito in risposta. Ma Bruno, per noi, pu\u00f2 fare molto di pi\u00f9, aiutandoci nel controllo delle response mediante le sue \u201cAssertion\u201d e, ove non sufficienti allo scopo, utilizzando i suoi \u201cScript\u201d.&nbsp;<\/p>\n\n\n\n<p>Anche Postman, ad esempio, \u00e8 in grado di fare tutto ci\u00f2 di cui parleremo in questo post, \u00e8 ovvio <a href=\"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-bruno-vs-postman\/\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\">che non siano prerogative esclusive di Bruno<\/a>. Quello su cui mi sento di porre l\u2019accento \u00e8 la semplicit\u00e0,nonch\u00e9 l\u2019elasticit\u00e0, con cui Bruno ci permette di farlo.<\/p>\n\n\n\n<p>A scopo puramente dimostrativo user\u00f2 alcune API di <strong><em>MusicBrainz.org<\/em><\/strong>, una vera e propria enciclopedia open source dedicata alla musica, un database di Artisti, Generi, Dischi e chi pi\u00f9 ne ha pi\u00f9 ne metta (eh no, le registrazioni non ci sono\u2026) tutto gestito dalla sua Community.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"h-assertion\">Assertion<\/h1>\n\n\n\n<p>Il primo strumento di cui vorrei parlarvi \u00e8 la Assertion che ci permette, in maniera semplice e diretta, di verificare se le risposte che otteniamo possiedono le caratteristiche che ci aspettiamo per considerarle valide.<\/p>\n\n\n\n<p>Lo strumento \u00e8 molto semplice ma, nonostante ci\u00f2, sono convinto che copra un\u2019ampia variet\u00e0 di esigenze, sufficiente per molti Dev.<\/p>\n\n\n\n<p>La forma della tipica asserzione \u00e8 la seguente:<\/p>\n\n\n\n<p>&lt;expression&gt; &lt;operator&gt; &lt;value&gt;<\/p>\n\n\n\n<p>Una \u201c<strong><em>expression<\/em><\/strong>\u201d rappresenta un campo della response che vogliamo testare, che indicheremo in \u201cdot notation\u201d partendo dall\u2019oggetto \u201c<strong>res<\/strong>\u201d, che mette a disposizione le seguenti propriet\u00e0:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong><em>status<\/em><\/strong><\/td><td>Il codice numerico dello status di risposta. Es: 200<\/td><\/tr><tr><td><strong><em>statusText<\/em><\/strong><\/td><td>Il codice testuale dello status di risposta. Es: OK<\/td><\/tr><tr><td><strong><em>headers<\/em><\/strong><\/td><td>Oggetto che rappresenta gli Headers in risposta.<\/td><\/tr><tr><td><strong><em>body<\/em><\/strong><\/td><td>L\u2019eventuale payload ottenuto in risposta.<\/td><\/tr><tr><td><strong><em>responseTime<\/em><\/strong><\/td><td>Il tempo di esecuzione della chiamata, espresso in millisecondi.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>[PITFALL] Bruno converte la risposta JSON in un oggetto JavaScript, in modo tale da poterlo interrogare con la ben nota \u201cdot notation\u201d. Nel caso in cui una propriet\u00e0 contenga un carattere invalido per JavaScript (ad esempio il trattino, \u201c-\u201c) \u00e8 necessario indirizzarla sfruttando una sintassi differente. Ad esempio:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">res.body.life-span.begin =&gt; Errore<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">res.body.&#91;\u2018life-span\u2019].begin =&gt; OK !<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Il \u201c<strong><em>value<\/em><\/strong>\u201d \u00e8 il valore con cui confrontare la sopraccitata expression. Questo pu\u00f2 essere una costante oppure una variabile (definita a monte della richesta e specificata tra doppie parentesi graffe).<\/p>\n\n\n\n<p>Per quanto riguarda l\u2019\u201c<strong><em>operator<\/em><\/strong>\u201d, questo indica come vogliamo porre in relazione expression e value, per verificarne la validit\u00e0 (secondo i nostri criteri). Gli operatori attualmente previsti sono i seguenti:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong><em>Assert\u2026<\/em><\/strong><\/td><td><strong><em>\u00e8 verificata se\u2026<\/em><\/strong><\/td><\/tr><tr><td><strong><em>equals<\/em><\/strong><\/td><td>il valore di expression \u00e8 uguale a quanto specificato in Value.<\/td><\/tr><tr><td><strong><em>notEquals<\/em><\/strong><\/td><td>il valore di expression \u00e8 diverso rispetto a quanto specificato in Value.<\/td><\/tr><tr><td><strong><em>gt<\/em><\/strong><\/td><td>il valore di expression \u00e8 maggiore (&gt;) di quanto specificato in Value.<\/td><\/tr><tr><td><strong><em>gte<\/em><\/strong><\/td><td>il valore di expression \u00e8 maggiore o uguale (&gt;=) di quanto specificato in Value.<\/td><\/tr><tr><td><strong><em>lt<\/em><\/strong><\/td><td>il valore di expression \u00e8 minore (&lt;) di quanto specificato in Value.<\/td><\/tr><tr><td><strong><em>lte<\/em><\/strong><\/td><td>il valore di expression \u00e8 minore o uguale (&lt;=) di quanto specificato in Value.<\/td><\/tr><tr><td><strong><em>in<\/em><\/strong><\/td><td>il valore di expression \u00e8 tra quelli specificati in Value. I valori di confronto devono essere specificati tra [] e separati da virgola, ad esempio:[ \u201cA\u201d, \u201cB\u201d, \u201cC\u201d ]<\/td><\/tr><tr><td><strong><em>notIn<\/em><\/strong><\/td><td>il valore di expression NON \u00e8 tra quelli specificati in Value. Il formato di Value \u00e8 lo stesso utilizzato con l\u2019operatore \u201cin\u201d.<\/td><\/tr><tr><td><strong><em>contains<\/em><\/strong><\/td><td>il valore di expression contiene quanto specificato in Value (il confronto ha senso sia nel caso in cui si parli di stringhe che di array).<\/td><\/tr><tr><td><strong><em>notContains<\/em><\/strong><\/td><td>il valore di expression NON contiene quanto specificato in Value.<\/td><\/tr><tr><td><strong><em>length<\/em><\/strong><\/td><td>il valore di expression \u00e8:Una stringa la cui lunghezza equivale al valore specificato in Value.Un array il cui numero di elementi equivale al valore specificato in Value.<\/td><\/tr><tr><td><strong><em>matches<\/em><\/strong><\/td><td>il valore di expression rispetta la Regular Expression indicata in Value.<\/td><\/tr><tr><td><strong><em>startsWith<\/em><\/strong><\/td><td>il valore di expression inizia con quanto specificato in Value.<\/td><\/tr><tr><td><strong><em>endsWith<\/em><\/strong><\/td><td>il valore di expression termina con quanto specificato in Value.<\/td><\/tr><tr><td><strong><em>between<\/em><\/strong><\/td><td>il valore di expression \u00e8 compreso tra i due valori numerici specificati (separati da virgola).<\/td><\/tr><tr><td><strong><em>isEmpty<\/em><\/strong><\/td><td>il valore di expression \u00e8 una stringa vuota oppure un array vuoto.<\/td><\/tr><tr><td><strong><em>isNull<\/em><\/strong><\/td><td>il valore di expression \u00e8 null.<\/td><\/tr><tr><td><strong><em>isUndefined<\/em><\/strong><\/td><td>il campo indicato da expression NON esiste.<\/td><\/tr><tr><td><strong><em>isDefined<\/em><\/strong><\/td><td>il campo indicato da expression esiste (con qualunque valore, anche null).<\/td><\/tr><tr><td><strong><em>isTruthy<\/em><\/strong><\/td><td>il valore di expression \u00e8 \u201ctrue\u201d.&nbsp;<\/td><\/tr><tr><td><strong><em>isFalsy<\/em><\/strong><\/td><td>il valore di expression \u00e8 \u201cfalse\u201d.<\/td><\/tr><tr><td><strong><em>isJson<\/em><\/strong><\/td><td>il valore di expression \u00e8 un oggetto JSON.<\/td><\/tr><tr><td><strong><em>isNumber<\/em><\/strong><\/td><td>il valore di expression \u00e8 un numero.<\/td><\/tr><tr><td><strong><em>isString<\/em><\/strong><\/td><td>il valore di expression \u00e8 una stringa.<\/td><\/tr><tr><td><strong><em>isBoolean<\/em><\/strong><\/td><td>il valore di expression \u00e8 un boolean.<\/td><\/tr><tr><td><strong><em>isArray<\/em><\/strong><\/td><td>il valore di expression \u00e8 un array.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Bene, a questo punto abbiamo tutti i mattoncini necessari a costruire le nostre Assertion, cos\u00ec da verificare che le chiamate rispondano come ci aspettiamo.<\/p>\n\n\n\n<p>Chiediamo quindi a <a href=\"https:\/\/musicbrainz.org\/ws\/2\/artist\/084308bd-1654-436f-ba03-df6697104e19?fmt=json\" class=\"ek-link\"><strong><em>MusicBrainz<\/em><\/strong> <\/a>i dati di dettaglio di un Gruppo scelto assolutamente a caso, ovvero i \u201cGreen Day\u201d e lavoriamo sulla risposta che ci viene fornita chiamando l\u2019API:<\/p>\n\n\n\n<p>La risposta, in formato JSON, \u00e8 la seguente:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JSON \/ JSON with Comments\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json\">{\n  <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-string\">\"Group\"<\/span>,\n  <span class=\"hljs-attr\">\"type-id\"<\/span>: <span class=\"hljs-string\">\"e431f5f6-b5d2-343d-8b36-72607fffb74b\"<\/span>,\n  <span class=\"hljs-attr\">\"country\"<\/span>: <span class=\"hljs-string\">\"US\"<\/span>,\n  <span class=\"hljs-attr\">\"end-area\"<\/span>: <span class=\"hljs-literal\">null<\/span>,\n  <span class=\"hljs-attr\">\"id\"<\/span>: <span class=\"hljs-string\">\"084308bd-1654-436f-ba03-df6697104e19\"<\/span>,\n  <span class=\"hljs-attr\">\"gender-id\"<\/span>: <span class=\"hljs-literal\">null<\/span>,\n  <span class=\"hljs-attr\">\"gender\"<\/span>: <span class=\"hljs-literal\">null<\/span>,\n  <span class=\"hljs-attr\">\"begin-area\"<\/span>: { <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Berkeley\"<\/span>,\n                  <span class=\"hljs-attr\">\"disambiguation\"<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n                  <span class=\"hljs-attr\">\"sort-name\"<\/span>: <span class=\"hljs-string\">\"Berkeley\"<\/span>,\n                  <span class=\"hljs-attr\">\"type-id\"<\/span>: <span class=\"hljs-literal\">null<\/span>,\n                  <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-literal\">null<\/span>,\n                  <span class=\"hljs-attr\">\"id\"<\/span>: <span class=\"hljs-string\">\"f9719692-c39a-4d9c-bf8c-dd4035b09534\"<\/span> },\n  <span class=\"hljs-attr\">\"disambiguation\"<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n  <span class=\"hljs-attr\">\"sort-name\"<\/span>: <span class=\"hljs-string\">\"Green Day\"<\/span>,\n  <span class=\"hljs-attr\">\"life-span\"<\/span>: { <span class=\"hljs-attr\">\"end\"<\/span>: <span class=\"hljs-literal\">null<\/span>,\n                 <span class=\"hljs-attr\">\"begin\"<\/span>: <span class=\"hljs-string\">\"1989\"<\/span>,\n                 <span class=\"hljs-attr\">\"ended\"<\/span>: <span class=\"hljs-literal\">false<\/span> },\n  <span class=\"hljs-attr\">\"ipis\"<\/span>: &#91;],\n  <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"Green Day\"<\/span>,\n  <span class=\"hljs-attr\">\"area\"<\/span>: { <span class=\"hljs-attr\">\"iso-3166-1-codes\"<\/span>: &#91; <span class=\"hljs-string\">\"US\"<\/span> ],\n            <span class=\"hljs-attr\">\"id\"<\/span>: <span class=\"hljs-string\">\"489ce91b-6658-3307-9877-795b68554c98\"<\/span>,\n            <span class=\"hljs-attr\">\"sort-name\"<\/span>: <span class=\"hljs-string\">\"United States\"<\/span>,\n            <span class=\"hljs-attr\">\"type-id\"<\/span>: <span class=\"hljs-literal\">null<\/span>,\n            <span class=\"hljs-attr\">\"disambiguation\"<\/span>: <span class=\"hljs-string\">\"\"<\/span>,\n            <span class=\"hljs-attr\">\"type\"<\/span>: <span class=\"hljs-literal\">null<\/span>,\n            <span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"United States\"<\/span> },\n  <span class=\"hljs-attr\">\"isnis\"<\/span>: &#91; <span class=\"hljs-string\">\"0000000122711282\"<\/span> ]\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON with Comments<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">json<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Proviamo ora ad implementare qualche assertion usando gli operatori di cui abbiamo appena parlato.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong><em>Expression<\/em><\/strong><\/td><td><strong><em>Operator<\/em><\/strong><\/td><td><strong><em>Value<\/em><\/strong><\/td><td><strong><em>Description<\/em><\/strong><\/td><\/tr><tr><td>res.status<\/td><td>equals<\/td><td>200<\/td><td>Lo status di risposta \u00e8 200.<\/td><\/tr><tr><td>res.status<\/td><td>notEquals<\/td><td>400<\/td><td>Lo status di risposta NON \u00e8 400.<\/td><\/tr><tr><td>res.responseTime<\/td><td>lte<\/td><td>500<\/td><td>Il tempo di risposta \u00e8 inferiore (o uguale) a 500ms.<\/td><\/tr><tr><td>res.body.name<\/td><td>equals<\/td><td>Green Day<\/td><td>Il campo <strong>name<\/strong> del body corrisponde a \u201cGreen Day\u201d<\/td><\/tr><tr><td>res.body.name<\/td><td>startsWith<\/td><td>Green<\/td><td>Il campo <strong>name<\/strong> del body inizia per \u201cGreen\u201d<\/td><\/tr><tr><td>res.body.name<\/td><td>endsWith<\/td><td>Day<\/td><td>Il campo <strong>name<\/strong> del body termina per \u201cDay\u201d<\/td><\/tr><tr><td>res.body.country<\/td><td>equals<\/td><td>US<\/td><td>Il campo <strong>country<\/strong> del body corrisponde a US.<\/td><\/tr><tr><td>res.body.country<\/td><td>matches<\/td><td>\/^U[S|K]$\/<\/td><td>Il campo country del body rispetta la Regular Exspression indicata, nella fattispecie la prima lettera \u00e8 una \u201cU\u201d, la seconda una \u201cS\u201d o una \u201cK\u201d.<\/td><\/tr><tr><td>res.body.country<\/td><td>in<\/td><td>[\u201cUS\u201d,\u201dUK\u201d]<\/td><td>Il campo <strong>country<\/strong> del body corrisponde ad uno degli item dell\u2019array specificato.<\/td><\/tr><tr><td>res.body.country<\/td><td>notIn<\/td><td>[\u201cIT\u201d,\u201dFR\u201d,\u201dES\u201d]<\/td><td>Il campo <strong>country<\/strong> del body NON corrisponde ad uno degli item dell\u2019array specificato.<\/td><\/tr><tr><td>res.body.ismis<\/td><td>length<\/td><td>1<\/td><td>L\u2019array corrispondente al campo <strong>ismis<\/strong> del body ha un solo elemento.<\/td><\/tr><tr><td>res.body.country<\/td><td>length<\/td><td>2<\/td><td>La lunghezza della stringa corrispondente al campo <strong>country<\/strong> \u00e8 di due caratteri.<\/td><\/tr><tr><td>res.body.life-span.begin<\/td><td>equals<\/td><td>\u201c1989\u201d<\/td><td>ERRORE \u2013 il carattere \u201c-\u201c non \u00e8 consentito !<\/td><\/tr><tr><td>res.body.[\u2018life-span\u2019].begin<\/td><td>equals<\/td><td>\u201c1989\u201d<\/td><td>La stringa corrispondente al campo <strong>begin<\/strong> dell\u2019oggetto <strong>life-span<\/strong> equivale a \u201c1989\u201d.Trattandosi di stringa, \u00e8 necessario racchiuderlo tra doppi apici.<\/td><\/tr><tr><td>res.body.name<\/td><td>contains<\/td><td>Day<\/td><td>Il campo <strong>name<\/strong> del body contiene la parola \u201cDay\u201d.<\/td><\/tr><tr><td>res.body.name<\/td><td>notContains<\/td><td>Sfera<\/td><td>Il campo <strong>name<\/strong> del body NON contiene la parola \u201cSfera\u201d.<\/td><\/tr><tr><td>res.body.area[\u2018iso-3166-1-codes\u2019]<\/td><td>contains<\/td><td>US<\/td><td>Il campo <strong>iso-3166-1-codes<\/strong> contiene, in quanto array, l\u2019item \u201cUS\u201d.<\/td><\/tr><tr><td>res.body.area[\u2018iso-3166-1-codes\u2019]<\/td><td>notContains<\/td><td>IT<\/td><td>Il campo <strong>iso-3166-1-codes<\/strong> NON contiene, in quanto array, l\u2019item \u201cIT\u201d.<\/td><\/tr><tr><td>res.responseTime<\/td><td>between<\/td><td>30,500<\/td><td>Il tempo di risposta \u00e8 compreso tra 30 e 500 millisecondi.<\/td><\/tr><tr><td>res.body.isnis.length<\/td><td>between<\/td><td>1,3<\/td><td>La lunghezza dell\u2019array <strong>isnis<\/strong> \u00e8 compresa tra 1 e 3.<\/td><\/tr><tr><td>res.body.name.length<\/td><td>between<\/td><td>5,10<\/td><td>La lunghezza del campo <strong>name<\/strong> \u00e8 compresa tra 5 e 10 caratteri.<\/td><\/tr><tr><td>res.body.ipis<\/td><td>isEmpty<\/td><td><\/td><td>Il campo <strong>ipis<\/strong> del body \u00e8 un array vuoto.<\/td><\/tr><tr><td>res.body.disambiguation<\/td><td>isEmpty<\/td><td><\/td><td>Il campo <strong>disambiguation<\/strong> \u00e8 una stringa vuota.<\/td><\/tr><tr><td>res.body.gender<\/td><td>isNull<\/td><td><\/td><td>Il campo <strong>gender<\/strong> \u00e8 null.<\/td><\/tr><tr><td>res.body.notexists<\/td><td>isUndefined<\/td><td><\/td><td>Il campo <strong>notexists<\/strong> NON \u00e8 definito nel body (non esiste)<\/td><\/tr><tr><td>res.body.gender<\/td><td>isDefined<\/td><td><\/td><td>Il campo <strong>gender<\/strong> del body \u00e8 definito (nonostante sia null).<\/td><\/tr><tr><td>res.body[&#8216;life-span&#8217;].ended<\/td><td>isFalsy<\/td><td><\/td><td>Il campo <strong>ended<\/strong> \u00e8 false.<\/td><\/tr><tr><td>res.body<\/td><td>isJson<\/td><td><\/td><td>Il body \u00e8 un oggetto JSON.<\/td><\/tr><tr><td>res.body.area<\/td><td>isJson<\/td><td><\/td><td>il campo area del body \u00e8 un oggetto JSON.<\/td><\/tr><tr><td>res.body[&#8216;life-span&#8217;].ended<\/td><td>isBoolean<\/td><td><\/td><td>il campo <strong>ended<\/strong> dell\u2019oggetto <strong>life-span<\/strong> \u00e8 di tipo boolean.<\/td><\/tr><tr><td>res.responseTime<\/td><td>isNumber<\/td><td><\/td><td>il tempo di risposta \u00e8 un numero.<\/td><\/tr><tr><td>res.body.type<\/td><td>isString<\/td><td><\/td><td>il campo <strong>type<\/strong> \u00e8 una stringa.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Dopo aver impostato tutte queste assertion, possiamo provare ad eseguire la nostra Request. Nella parte destra della finestra di Bruno, in corrispondenza del Tab \u201cTests\u201d troveremo il risultato delle nostre assertion:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/docsz\/AD_4nXeO8LHejZemuBJxwO5t69Om9Ylztp4ocCXcw29IytNwA4jA1yeuNK-FCkE5NPdGU5QGFuYRfUsCPKeDEcnr4WbZwMyRz_uzgEzr4ljEJHH0RDzEW1YNL7ck74pTAmnfDGs8wc70vC0JlZZsMnMBUTVYCIyatYBXsKmMxdjHZKCxsLu4AzoBZ2A?key=NU_RK1vTu-Z1s2UTdF7MsQ\" alt=\"A screenshot of a computer\n\nDescription automatically generated\"\/><\/figure>\n\n\n\n<p>Notare il numero \u201c1\u201d in apice sul nome del Tab, che indica la quantit\u00e0 di test falliti (nel nostro caso ne abbiamo uno, che fallisce a causa dell\u2019ormai noto trattino nel nome del campo \u201clife-span\u201d), che vengono evidenziati in rosso nell\u2019area sottostante.&nbsp;<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"h-test\">Test<\/h1>\n\n\n\n<p><em>\u201cQuando il gioco si fa duro, i duri cominciano a giocare\u201d (cit.)<\/em><\/p>\n\n\n\n<p>Sebbene le assertion siano in grado di coprire la maggior parte delle esigenze di testing di noi Dev, Bruno ci offre una ghiotta alternativa, ovvero quella dei Test, che si basano sulle interfacce <strong><em>expect<\/em><\/strong> e <strong><em>assert<\/em><\/strong> di <strong>Chai<\/strong>, permettendoci il controllo totale di quanto restituito dalle requests.<\/p>\n\n\n\n<p>Possiamo inserire i Test, a livello di request, selezionando l\u2019omonimo tab, come illustrato dall\u2019immagine seguente:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/docsz\/AD_4nXdNcuce953DnlygLEOCivOn9NNDgXpj7jDaKq0HdVwqBXXZUShHpJIwh06ruLiTbxgkI6j1SwR0SDWwUZqExduv22Rz6qG4aV2YGvT62ZluWMUM8QF_YgkAWgaPrB8SomKgCu71bt4qR85NlbAqUmjCxqZ7na9GvOJw2i04pnZY6OIQnNLvCQs?key=NU_RK1vTu-Z1s2UTdF7MsQ\" alt=\"A black screen with white text\n\nDescription automatically generated\"\/><\/figure>\n\n\n\n<p>All\u2019inizio del file di test andiamo a definire le variabili che useremo:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ Extract body from response<\/span>\n\n<span class=\"hljs-keyword\">const<\/span> _payload = res.getBody();\n\n<span class=\"hljs-comment\">\/\/ Extract Response Status<\/span>\n\n<span class=\"hljs-keyword\">const<\/span> _status = res.getStatus();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Non \u00e8 assolutamente obbligatorio, ma usare variabili \u201csemplici\u201d al posto dei metodi, render\u00e0 il codice pi\u00f9 leggibile.<\/p>\n\n\n\n<p>Ora, se dovessimo riscrivere via test l\u2019assert di verifica dello status di risposta (controllando che corrisponda a \u201cOK\u201d, ovvero 200) potremmo utilizzare indifferentemente <strong><em>expect<\/em><\/strong>:\u00a0<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">test(<span class=\"hljs-string\">\"&#91;Using Expect] Response Status should be 200\"<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\n\u00a0\u00a0expect(_status).to.equal(<span class=\"hljs-number\">200<\/span>);\n\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>oppure <strong><em>assert<\/em><\/strong>:<\/p>\n\n\n\n<p>Se invece volessimo valutare il tempo di risposta per verificare che rientri in un intervallo di tempo specifico, dovremmo rivolgerci a <strong><em>expect<\/em><\/strong>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">test(<span class=\"hljs-string\">\"&#91;Using Expect] ResponseTime is between 30 and 500\"<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  expect(_status).to.be.gte(<span class=\"hljs-number\">30<\/span>).and.lte(<span class=\"hljs-number\">500<\/span>);\n});\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Ancora, verifichiamo che la carriera dei Green Day sia iniziata nel 1989 (il dato viene restituito come stringa):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">test(<span class=\"hljs-string\">\"&#91;Using Expect] Career should start in 1989\"<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\n\u00a0\u00a0expect(_payload&#91;<span class=\"hljs-string\">'life-span'<\/span>].begin).to.equal(<span class=\"hljs-string\">\"1989\"<\/span>);\n\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>e se volessimo usare <strong><em>assert<\/em><\/strong>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">test(<span class=\"hljs-string\">\"&#91;Using Assert] Career should start in 1989\"<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\n\u00a0\u00a0assert.equal(_payload&#91;<span class=\"hljs-string\">'life-span'<\/span>].begin, <span class=\"hljs-string\">\"1989\"<\/span>);\n\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Proviamo adesso ad implementare qualcosa che le assert non ci permettono: andiamo a verificare che ogni item dell\u2019array <strong><em>isnis<\/em><\/strong> sia effettivamente una stringa che inizia con il carattere \u201c0\u201d e termina con il carattere \u201c2\u201d. Per fare ci\u00f2 usiamo <strong><em>expect<\/em><\/strong>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">test(<span class=\"hljs-string\">\"&#91;Using Expect] Check Items in isnis array\"<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\n\u00a0\u00a0expect(_payload.isnis).to.satisfy(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-params\">items<\/span>)<\/span>{\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-keyword\">return<\/span> items.every(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\">item<\/span>)<\/span>{\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-keyword\">return<\/span> item.startsWith(<span class=\"hljs-string\">\"0\"<\/span>) &amp;&amp; item.endsWith(<span class=\"hljs-string\">\"2\"<\/span>);\n\n\u00a0\u00a0\u00a0\u00a0})\n\n\u00a0\u00a0})\n\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Bene, a questo punto il meccanismo di base dei Test non ha pi\u00f9 segreti\u2026 o forse no? C\u2019\u00e8 ancora un\u2019interessante particolarit\u00e0 di cui vorrei parlarvi.<\/p>\n\n\n\n<p>Lo stesso tab \u201cTests\u201d esiste anche ai livelli di Collection e delle eventuali Directory che raggruppano le nostre chiamate. Come facilmente intuibile, ci viene consentito di inserire dei test anche a questi livelli in modo tale che vengano eseguiti su tutte le request figlie.<\/p>\n\n\n\n<p>La struttura del progetto a cui mi riferisco (troverete i riferimenti in calce al post) \u00e8 la seguente:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>BrunoSample (collection)\n<ul class=\"wp-block-list\">\n<li>MusicBrainz (dir)\n<ul class=\"wp-block-list\">\n<li>Artist Finder (request)<\/li>\n\n\n\n<li>XML (request)<\/li>\n\n\n\n<li>JSON Asserts (request)<\/li>\n\n\n\n<li>JSON Tests (request)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>Il Tab \u201cTests\u201d si trova nelle impostazioni di ogni collection\/directory, alle quali si accede attraverso l\u2019icona identificata dai 3 punti (si accende appoggiando il mouse al nodo dell\u2019albero):<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><img loading=\"lazy\" decoding=\"async\" alt=\"A screenshot of a computer\n\nDescription automatically generated\" src=\"https:\/\/lh7-us.googleusercontent.com\/docsz\/AD_4nXfnggV96P7ov4vu57oMmHaLkKV6LnOQAn9LbfqHCu2LDr75RZiSsbPaYJZEJD-RprjZgUJNU7XkUJpV3UmZTlBLrYFl2t5mOfcrJKBeT90KAn2k5sdGf_IjcYEa-PRVFxzoYxuQhFs4YpyCxkB-q5yWGLHdUnC4ZR1xQJhDhAE2Qo97dXUtI4g?key=NU_RK1vTu-Z1s2UTdF7MsQ\" width=\"134\" height=\"112\"><\/td><td><img loading=\"lazy\" decoding=\"async\" alt=\"A screen shot of a black background\n\nDescription automatically generated\" src=\"https:\/\/lh7-us.googleusercontent.com\/docsz\/AD_4nXdEv06leuCBLiQZpMMRgnyAr3ExTuJCieANTD975_mvEaVCGB1G65riKYFjm6GV0haTtHZlcJTMw01l_DmxD3OxpOR4uwTdka5TEw6PM_JnVWqfAmZClORn7CZAo3Qu4PVIRv9oSjwuc3Y4l4JDTli2fWub8DqdxwiXecFIxNXSojx3SG5pTok?key=NU_RK1vTu-Z1s2UTdF7MsQ\" width=\"160\" height=\"106\"><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Questa possibilit\u00e0 che ci viene offerta \u00e8 semplicemente fantastica (non trovate?), in quanto ci permette di riutilizzare il codice di quei Test comuni a pi\u00f9 Request.<\/p>\n\n\n\n<p>Ad esempio, possiamo definire che, per essere valide, tutte le request della nostra collection debbano rispondere entro i 500 millisecondi. Per implementare questo check, dobbiamo inserire le seguenti righe di codice nell\u2019area \u201cTests\u201d dei setting di collection:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">test(<span class=\"hljs-string\">\"&#91;Collection] ResponseTime max is 500 ms\"<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\n\u00a0\u00a0expect(res.getStatus()).to.be.lte(<span class=\"hljs-number\">500<\/span>);\n\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Potremmo anche voler verificare che le request di una specifica directory, essendo tutte GET, abbiano successo, restituendo lo status 200 (OK). Quindi, nell\u2019area \u201cTest\u201d dei setting di directory andiamo ad inserire quanto segue:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">test(<span class=\"hljs-string\">\"&#91;MusicBrainz] Response Status is OK (200)\"<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\n\u00a0\u00a0expect(res.getStatus()).to.equal(<span class=\"hljs-number\">200<\/span>);\n\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Eseguendo una qualsiasi delle nostre request potremo verificare che, tra i risultati dei test ci sono anche quelli comuni per collection e directory (che abbiamo volutamente identificato):<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/docsz\/AD_4nXcHRwkkeZ37oLr64Nq-0za1QvxdFjefX_nQxXkN0x5G5aAazYShGpasWDAv3Y9h54-eRjcuBTpznRIzCFhLf6VP8XS5kNVB6RdmhuSuQuNoxNeXLsF9v0YjTnFo6Wcs6I0ulrfEcRKw9CBsfO3cVpDTPy36ae6AP1xVN6Y38LwCtFsaaWFAKzA?key=NU_RK1vTu-Z1s2UTdF7MsQ\" alt=\"A screenshot of a test\n\nDescription automatically generated\"\/><\/figure>\n\n\n\n<p>Non \u00e8 \u201cmeraviglioso\u201d? (semicit.)<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"h-test-level-up\">Test \u2013 Level Up<\/h1>\n\n\n\n<p>Fino ad ora abbiamo verificato la bont\u00e0 delle risposte in formato JSON. Cosa potremmo fare nel sempre piu raro caso in cui il formato della risposta sia differente?&nbsp;<\/p>\n\n\n\n<p>MusicBrainz ci offre la <a href=\"https:\/\/musicbrainz.org\/ws\/2\/artist\/084308bd-1654-436f-ba03-df6697104e19?fmt=xml\" class=\"ek-link\">possibilit\u00e0 di ottenere gli stessi dati anche in formato XML cambiando un <\/a>solo parametro della request:<\/p>\n\n\n\n<p>Questa volta, in virt\u00f9 del nuovo valore del parametro <strong><em>fmt<\/em><\/strong> otteniamo il seguente output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-meta\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">metadata<\/span> <span class=\"hljs-attr\">xmlns<\/span>=<span class=\"hljs-string\">\"http:\/\/musicbrainz.org\/ns\/mmd-2.0#\"<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artist<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"084308bd-1654-436f-ba03-df6697104e19\"<\/span>\u00a0\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"Group\"<\/span> <span class=\"hljs-attr\">type-id<\/span>=<span class=\"hljs-string\">\"e431f5f6-b5d2-343d-8b36-72607fffb74b\"<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">name<\/span>&gt;<\/span>Green Day<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">name<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">sort-name<\/span>&gt;<\/span>Green Day<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">sort-name<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">isni-list<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">isni<\/span>&gt;<\/span>0000000122711282<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">isni<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">isni-list<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">country<\/span>&gt;<\/span>US<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">country<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">area<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"489ce91b-6658-3307-9877-795b68554c98\"<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">name<\/span>&gt;<\/span>United States<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">name<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">sort-name<\/span>&gt;<\/span>United States<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">sort-name<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">iso-3166-1-code-list<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">iso-3166-1-code<\/span>&gt;<\/span>US<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">iso-3166-1-code<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">iso-3166-1-code-list<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">area<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">begin-area<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"f9719692-c39a-4d9c-bf8c-dd4035b09534\"<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">name<\/span>&gt;<\/span>Berkeley<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">name<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">sort-name<\/span>&gt;<\/span>Berkeley<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">sort-name<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">begin-area<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">life-span<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">begin<\/span>&gt;<\/span>1989<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">begin<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">life-span<\/span>&gt;<\/span>\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artist<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">metadata<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Per Bruno, questo output \u00e8 una banalissima stringa che possiamo verificare con qualche assertion:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong><em>Expression<\/em><\/strong><\/td><td><strong><em>Operator<\/em><\/strong><\/td><td><strong><em>Value<\/em><\/strong><\/td><td><strong><em>Description<\/em><\/strong><\/td><\/tr><tr><td>res.body<\/td><td>startsWith<\/td><td>&lt;?xml<\/td><td>La risposta inizia con \u201c&lt;?xml\u201d<\/td><\/tr><tr><td>res.body<\/td><td>contains<\/td><td>&lt;metadata<\/td><td>La risposta contiene la stringa:&nbsp;\u201c&lt;metadata\u201d<\/td><\/tr><tr><td>res.body<\/td><td>contains<\/td><td>&lt;\/metadata&gt;<\/td><td>La risposta contiene la stringa:&nbsp;\u201c&lt;\/metadata&gt;\u201d<\/td><\/tr><tr><td>res.body<\/td><td>contains<\/td><td>&lt;name&gt;Green Day&lt;\/name&gt;<\/td><td>La risposta contiene la stringa:\u201c&lt;name&gt;Green Day&lt;\/name&gt;\u201d<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Eseguendo la request otteniamo, nel tab \u201cTest\u201d, i seguenti risultati, ivi compresi, non dimentichiamoli, quelli dei test che abbiamo inserito a livello di directory e collection:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/docsz\/AD_4nXcSe8SrCT6-UYnLy73CZ346TzJoby6V8JqPD6lD4Huaqkre7Nhh-UmHlmxD0j6kQBSbuMpULE4tnKaDmKd9E221DHiBSaHeiuVSMGtR8_I-b4JyFpAClbBgFAuGaQ3t8HVwu-VAmsVv0DzhnpWfGlfEtYky-EIOmlGr284FajFPh0z_7Bfpx4I?key=NU_RK1vTu-Z1s2UTdF7MsQ\" alt=\"A screenshot of a computer program\n\nDescription automatically generated\"\/><\/figure>\n\n\n\n<p>Ovviamente, questi sono controlli molto blandi che lasciano il tempo che trovano: abbiamo semplicemente chiesto a Bruno di verificare che una stringa contenga effettivamente delle sottostringhe.<\/p>\n\n\n\n<p>Proviamo a fare il salto di qualit\u00e0 e trattiamo l\u2019XML tale (e non come una stringa).&nbsp;<\/p>\n\n\n\n<p>Iniziamo con l\u2019aggiungere alla nostra directory principale il file <strong><em>package.json<\/em><\/strong> che ci permetter\u00e0 di gestire il caricamento dei moduli npm aggiuntivi (necessari quando non bastano quelli \u201cinbuilt\u201d di Bruno). Il contenuto del file dovrebbe essere simile al seguente:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"JSON \/ JSON with Comments\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json\">{\n\n\u00a0\u00a0<span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"brunosample\"<\/span>,\n\n\u00a0\u00a0<span class=\"hljs-attr\">\"version\"<\/span>: <span class=\"hljs-string\">\"1.0.0\"<\/span>,\n\n\u00a0\u00a0<span class=\"hljs-attr\">\"main\"<\/span>: <span class=\"hljs-string\">\"index.js\"<\/span>\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON with Comments<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">json<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>A questo punto, da terminale, possiamo installare \u2013 nel contesto della nostra collection \u2013 i package che useremo per la gestione dell\u2019XML:<\/p>\n\n\n\n<p>npm install xmldom xpath<\/p>\n\n\n\n<p>Il file package.json avr\u00e0 guadagnato nuove dipendenze:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"JSON \/ JSON with Comments\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json\">{\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-attr\">\"name\"<\/span>: <span class=\"hljs-string\">\"brunosample\"<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-attr\">\"version\"<\/span>: <span class=\"hljs-string\">\"1.0.0\"<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-attr\">\"main\"<\/span>: <span class=\"hljs-string\">\"index.js\"<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-attr\">\"dependencies\"<\/span>: {\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-attr\">\"xmldom\"<\/span>: <span class=\"hljs-string\">\"^0.6.0\"<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-attr\">\"xpath\"<\/span>: <span class=\"hljs-string\">\"^0.0.34\"<\/span>\n\n\u00a0\u00a0\u00a0\u00a0}\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON with Comments<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">json<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Perfetto, a questo punto possiamo iniziare ad implementare i test per verificare l\u2019xml in risposta.<\/p>\n\n\n\n<p>Spostiamoci nell\u2019area Test della request ed iniziamo ad inserire le prime righe di codice comuni a tutti i test che andremo ad implementare:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> xpath = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'xpath'<\/span>);\n\n<span class=\"hljs-keyword\">const<\/span> dom = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">'xmldom'<\/span>).DOMParser;\n\n<span class=\"hljs-keyword\">const<\/span> doc = <span class=\"hljs-keyword\">new<\/span> dom().parseFromString(res.body, <span class=\"hljs-string\">'text\/xml'<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Ora che nella variabile <strong><em>doc<\/em><\/strong> abbiamo l\u2019oggetto XML che rappresenta la nostra response, possiamo navigarla con xPath, per verificarne i dai sfruttando Chai.<\/p>\n\n\n\n<p>Ad esempio, se volessimo verificare che il tag <strong><em>name<\/em><\/strong> contenga effettivamente la stringa \u201c<em>Green Day<\/em>\u201d, potremmo utilizzare quanto segue:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">test(<span class=\"hljs-string\">\"Expect Name is Green Day\"<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n\n\u00a0\u00a0<span class=\"hljs-keyword\">const<\/span> _query = <span class=\"hljs-string\">\"\/\/*&#91;local-name()='artist']\/*&#91;local-name()='name']\/text()\"<\/span>;\n\n\u00a0\u00a0<span class=\"hljs-keyword\">const<\/span> _name = xpath.select(_query, doc);\n\n\u00a0\u00a0expect(_name.toString()).to.equal(<span class=\"hljs-string\">\"Green Day\"<\/span>);\n\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Allo stesso modo possiamo verificare che la loro carriera sia effettivamente iniziata nel 1989:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">test(<span class=\"hljs-string\">\"Expect Begin is 1989\"<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n\n\u00a0\u00a0<span class=\"hljs-keyword\">const<\/span> _query = <span class=\"hljs-string\">\"\/\/*&#91;local-name()='artist']\/*&#91;local-name()='life-span']\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/*&#91;local-name()='begin']\/text()\"<\/span>;\n\n\u00a0\u00a0<span class=\"hljs-keyword\">const<\/span> _begin = xpath.select(_query, doc);\n\n\u00a0\u00a0expect(_begin.toString()).to.equal(<span class=\"hljs-string\">\"1989\"<\/span>);\n\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Ancora, verifichiamo che tutti gli elementi della lista isni (International Standard Name Identifier) inizino per \u201c0\u201d e finiscano con \u201c2\u201d:<\/p>\n\n\n\n<p>E, per finire, verifichiamo che vi sia un solo elemento nella lista isin:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">test(<span class=\"hljs-string\">\"Expect isni has 1 element\"<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> _query = <span class=\"hljs-string\">\"count(\/\/*&#91;local-name()='artist']\/*&#91;local-name()='isni-list']\n                                                           \/*&#91;local-name()='isni'])\"<\/span>;\n  <span class=\"hljs-keyword\">const<\/span> _isniCounter = xpath.select(_query, doc);\n  expect(_isniCounter).to.equal(<span class=\"hljs-number\">1<\/span>);\n});\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>test(&#8220;Expect isni has 1 element&#8221;, function() {<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-bruno-cli\">Bruno CLI<\/h2>\n\n\n\n<p>Ora che abbiamo impostato le nostre request, farcite di assert e test per verificarne la bont\u00e0 delle risposte, <strong>possiamo sfruttare la CLI offerta da Bruno<\/strong> per eseguirle massivamente, del resto eseguirle singolarmente dalla App di Bruno sarebbe quantomeno noioso !<\/p>\n\n\n\n<p>Per installare la CLI dobbiamo rifarci a <strong><em>npm<\/em><\/strong> con il seguente comando:<\/p>\n\n\n\n<p>npm install -g @usebruno\/cli<\/p>\n\n\n\n<p>Da questo momento abbiamo il commando <strong><em>bru<\/em><\/strong> a nostra disposizione. Per eseguire tutte le request della directory MusicBrainz dobbiamo, nel terminale, spostarci nella directory principale della Collection ed eseguire:<\/p>\n\n\n\n<p>bru run MusicBrainz -r<\/p>\n\n\n\n<p>L\u2019output che otteniamo \u00e8 il seguente:<\/p>\n\n\n\n<p>Running Folder Recursively&nbsp;<\/p>\n\n\n\n<p>MusicBrainz\/Artist Finder (200 OK) &#8211; 185 ms<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.artists: length 5<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 [Collection] ResponseTime max is 500 ms<\/p>\n\n\n\n<p>MusicBrainz\/XML Tests (200 OK) &#8211; 203 ms<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body: startsWith &lt;?xml<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body: contains &lt;metadata<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body: contains &lt;\/metadata&gt;<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body: contains &lt;name&gt;Green Day&lt;\/name&gt;<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 [Collection] ResponseTime max is 500 ms<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 Expect Name is Green Day<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 Expect Begin is 1989<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 Expect every isni starts with 0 and ends with 2<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 Expect isni has 1 element<\/p>\n\n\n\n<p>MusicBrainz\/JSON Asserts (200 OK) &#8211; 93 ms<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.status: eq 200<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.status: neq 400<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.responseTime: lte 500<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.name: eq Green Day<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.name: startsWith Green<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.name: endsWith Day<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.country: eq US<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.country: in [&#8220;US&#8221;,&#8221;UK&#8221;]<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.country: notIn [&#8220;IT&#8221;,&#8221;FR&#8221;,&#8221;ES&#8221;]<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.isnis: length 1<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.country: length 2<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2715 assert: res.body.life-span.begin: eq &#8220;1989&#8221;<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cannot read properties of undefined (reading &#8216;begin&#8217;)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body[&#8216;life-span&#8217;].begin: eq &#8220;1989&#8221;<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body[&#8216;begin-area&#8217;][&#8216;sort-name&#8217;]: eq Berkeley<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.name: contains Day<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.name: notContains Sfera<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.area[&#8216;iso-3166-1-codes&#8217;]: contains US<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.area[&#8216;iso-3166-1-codes&#8217;]: notContains IT<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.responseTime: between 30,500<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.isnis.length: between 1,3<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.name.length: between 5,10<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.ipis: isEmpty<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.disambiguation: isEmpty<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.gender: isNull<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.notexists: isUndefined<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.gender: isDefined<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body[&#8216;life-span&#8217;].ended: isFalsy<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body: isJson<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.area: isJson<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body[&#8216;life-span&#8217;].ended: isBoolean<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.responseTime: isNumber<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.type: isString<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 assert: res.body.country: matches \/^U[S|K]$\/<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 [Collection] ResponseTime max is 500 ms<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 Response Status should be 200<\/p>\n\n\n\n<p>MusicBrainz\/JSON Tests (200 OK) &#8211; 124 ms<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 [Collection] ResponseTime max is 500 ms<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 [Using Expect] Response Status should be 200<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 [Using Assert] Response Status should be 200<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 [Using Expect] Response Time should be between 30 and 500<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 [Using Expect] Career should start in 1989<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 [Using Assert] Career should start in 1989<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;\u2713 [Using Expect]&nbsp;All Items in isnis should start with 0 and end with 2<\/p>\n\n\n\n<p><strong>Requests:&nbsp; &nbsp; <\/strong><strong>4 passed<\/strong><strong>, 4 total<\/strong><\/p>\n\n\n\n<p><strong>Tests: &nbsp; &nbsp; &nbsp; <\/strong><strong>15 passed<\/strong><strong>, 15 total<\/strong><\/p>\n\n\n\n<p><strong>Assertions:&nbsp; <\/strong><strong>37 passed<\/strong><strong>, <\/strong><strong>1 failed<\/strong><strong>, 38 total<\/strong><\/p>\n\n\n\n<p>Ran all requests &#8211; 605 ms<\/p>\n\n\n\n<p>Alla versione attuale di <strong><em>bru<\/em><\/strong> (la 1.20), esistono due bug:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>I parametri a livello di URL non vengono presi in considerazione (l\u2019output qui sopra \u00e8 stato ottenuto da una mia versione locale fixata, per cui ho gi\u00e0 aperto una PR).<\/li>\n\n\n\n<li>Gli script a livello di directory non vengono presi in considerazione da <strong><em>bru<\/em><\/strong>.<\/li>\n<\/ol>\n\n\n\n<p>La CLI, nonostante questi problemi di giovent\u00f9, \u00e8 comunque un importante strumento per il testing delle nostre API, integrabile anche nelle pipeline di CI\/CD.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"h-conclusioni\">Conclusioni<\/h1>\n\n\n\n<p>Grazie per essere arrivati fino a qui!!! Spero di avervi fornito le basi per implementare test e assertion in Bruno e, soprattutto, di avervi trasmesso la voglia di sperimentare.<\/p>\n\n\n\n<p>Bruno \u00e8 relativamente giovane, \u00e8 facile incappare in qualche bug (ne abbiamo visti giusto un paio nell\u2019ultima sezione dedicata alla CLI): sappiate che sia le Pull Request che le segnalazioni di Bug o Features sul repository di Bruno (<a href=\"https:\/\/github.com\/usebruno\/bruno\" class=\"ek-link\">https:\/\/github.com\/usebruno\/bruno<\/a>) sono sempre gradite. A tal proposito, la stesura di questo articolo mi ha dato l\u2019opportunit\u00e0 di inviarne un paio\u2026 Partecipare ad un progetto in cui si crede \u00e8 sempre fonte di soddisfazione.<\/p>\n\n\n\n<p>Se volete scaricare le sopraccitate request e tutti i test\/assert con cui le abbiamo \u201cfarcite\u201d, trovate il repository qui:<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/fgrande\/brunosample\">https:\/\/github.com\/fgrande\/brunosample<\/a><\/p>\n\n\n\n<p>\u00c8 un repository dedicato alle sperimentazioni relative a Bruno, che cerco di tenere sempre aggiornato con le ultime novit\u00e0. Fatelo vostro!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Tutti noi che lavoriamo pressoch\u00e9 quotidianamente con chiamate API, abbiamo trovato grandi compagni di viaggio nei Client dedicati, grazie ai quali possiamo: Per ottemperare queste attivit\u00e0 \u00e8 sufficiente impostare una request ed eseguirla, leggendo lo status della response e, se disponibile, valutare visivamente il payload restituito in risposta. Ma Bruno, per noi, pu\u00f2 fare molto&#8230; <a class=\"more-link\" href=\"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/\">Read more<\/a><\/p>\n","protected":false},"author":261,"featured_media":28889,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","_uag_custom_page_level_css":"","_genesis_hide_title":false,"_genesis_hide_breadcrumbs":false,"_genesis_hide_singular_image":false,"_genesis_hide_footer_widgets":false,"_genesis_custom_body_class":"","_genesis_custom_post_class":"","_genesis_layout":"","footnotes":""},"categories":[10263],"tags":[12454,12222,12173,12456],"collections":[11708],"class_list":{"0":"post-28882","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-backend-it","8":"tag-assertion","9":"tag-bruno","10":"tag-database-it","11":"tag-test","12":"collections-dalla-community","13":"entry"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.9 (Yoast SEO v27.5) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Assertion e test con Bruno - Codemotion Magazine<\/title>\n<meta name=\"description\" content=\"Scopri come utilizzare assertion e test con Bruno in questa guida approfondita scritta da Fabio Grande.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Le API di Bruno \u2013 Assertion e Test\" \/>\n<meta property=\"og:description\" content=\"Scopri come utilizzare assertion e test con Bruno in questa guida approfondita scritta da Fabio Grande.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/\" \/>\n<meta property=\"og:site_name\" content=\"Codemotion Magazine\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Codemotion.Italy\/\" \/>\n<meta property=\"article:published_time\" content=\"2024-07-23T14:22:25+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-07-23T14:22:27+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1368\" \/>\n\t<meta property=\"og:image:height\" content=\"768\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Fabio Grande\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@CodemotionIT\" \/>\n<meta name=\"twitter:site\" content=\"@CodemotionIT\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fabio Grande\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/it\\\/backend-it\\\/le-api-di-bruno-assertion-e-test\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/it\\\/backend-it\\\/le-api-di-bruno-assertion-e-test\\\/\"},\"author\":{\"name\":\"Fabio Grande\",\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/#\\\/schema\\\/person\\\/d47d145dba7746776b7d736aecffdd44\"},\"headline\":\"Le API di Bruno \u2013 Assertion e Test\",\"datePublished\":\"2024-07-23T14:22:25+00:00\",\"dateModified\":\"2024-07-23T14:22:27+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/it\\\/backend-it\\\/le-api-di-bruno-assertion-e-test\\\/\"},\"wordCount\":3140,\"publisher\":{\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/it\\\/backend-it\\\/le-api-di-bruno-assertion-e-test\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/wp-content\\\/uploads\\\/2024\\\/07\\\/Bruno.Dog_.Reading.jpg\",\"keywords\":[\"assertion\",\"bruno\",\"Database\",\"test\"],\"articleSection\":[\"Backend\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/it\\\/backend-it\\\/le-api-di-bruno-assertion-e-test\\\/\",\"url\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/it\\\/backend-it\\\/le-api-di-bruno-assertion-e-test\\\/\",\"name\":\"Assertion e test con Bruno - Codemotion Magazine\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/it\\\/backend-it\\\/le-api-di-bruno-assertion-e-test\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/it\\\/backend-it\\\/le-api-di-bruno-assertion-e-test\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/wp-content\\\/uploads\\\/2024\\\/07\\\/Bruno.Dog_.Reading.jpg\",\"datePublished\":\"2024-07-23T14:22:25+00:00\",\"dateModified\":\"2024-07-23T14:22:27+00:00\",\"description\":\"Scopri come utilizzare assertion e test con Bruno in questa guida approfondita scritta da Fabio Grande.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/it\\\/backend-it\\\/le-api-di-bruno-assertion-e-test\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/it\\\/backend-it\\\/le-api-di-bruno-assertion-e-test\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/it\\\/backend-it\\\/le-api-di-bruno-assertion-e-test\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/wp-content\\\/uploads\\\/2024\\\/07\\\/Bruno.Dog_.Reading.jpg\",\"contentUrl\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/wp-content\\\/uploads\\\/2024\\\/07\\\/Bruno.Dog_.Reading.jpg\",\"width\":1368,\"height\":768,\"caption\":\"bruno assertion e test\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/it\\\/backend-it\\\/le-api-di-bruno-assertion-e-test\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Backend\",\"item\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/it\\\/backend-it\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Le API di Bruno \u2013 Assertion e Test\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/#website\",\"url\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/\",\"name\":\"Codemotion Magazine\",\"description\":\"We code the future. Together\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/#organization\",\"name\":\"Codemotion\",\"url\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/wp-content\\\/uploads\\\/2019\\\/11\\\/codemotionlogo.png\",\"contentUrl\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/wp-content\\\/uploads\\\/2019\\\/11\\\/codemotionlogo.png\",\"width\":225,\"height\":225,\"caption\":\"Codemotion\"},\"image\":{\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/Codemotion.Italy\\\/\",\"https:\\\/\\\/x.com\\\/CodemotionIT\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/#\\\/schema\\\/person\\\/d47d145dba7746776b7d736aecffdd44\",\"name\":\"Fabio Grande\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/fabio-grande-profile-100x100.jpg\",\"url\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/fabio-grande-profile-100x100.jpg\",\"contentUrl\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/fabio-grande-profile-100x100.jpg\",\"caption\":\"Fabio Grande\"},\"url\":\"https:\\\/\\\/www.codemotion.com\\\/magazine\\\/author\\\/fabio-grande\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Assertion e test con Bruno - Codemotion Magazine","description":"Scopri come utilizzare assertion e test con Bruno in questa guida approfondita scritta da Fabio Grande.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/","og_locale":"en_US","og_type":"article","og_title":"Le API di Bruno \u2013 Assertion e Test","og_description":"Scopri come utilizzare assertion e test con Bruno in questa guida approfondita scritta da Fabio Grande.","og_url":"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/","og_site_name":"Codemotion Magazine","article_publisher":"https:\/\/www.facebook.com\/Codemotion.Italy\/","article_published_time":"2024-07-23T14:22:25+00:00","article_modified_time":"2024-07-23T14:22:27+00:00","og_image":[{"width":1368,"height":768,"url":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading.jpg","type":"image\/jpeg"}],"author":"Fabio Grande","twitter_card":"summary_large_image","twitter_creator":"@CodemotionIT","twitter_site":"@CodemotionIT","twitter_misc":{"Written by":"Fabio Grande","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/#article","isPartOf":{"@id":"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/"},"author":{"name":"Fabio Grande","@id":"https:\/\/www.codemotion.com\/magazine\/#\/schema\/person\/d47d145dba7746776b7d736aecffdd44"},"headline":"Le API di Bruno \u2013 Assertion e Test","datePublished":"2024-07-23T14:22:25+00:00","dateModified":"2024-07-23T14:22:27+00:00","mainEntityOfPage":{"@id":"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/"},"wordCount":3140,"publisher":{"@id":"https:\/\/www.codemotion.com\/magazine\/#organization"},"image":{"@id":"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/#primaryimage"},"thumbnailUrl":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading.jpg","keywords":["assertion","bruno","Database","test"],"articleSection":["Backend"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/","url":"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/","name":"Assertion e test con Bruno - Codemotion Magazine","isPartOf":{"@id":"https:\/\/www.codemotion.com\/magazine\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/#primaryimage"},"image":{"@id":"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/#primaryimage"},"thumbnailUrl":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading.jpg","datePublished":"2024-07-23T14:22:25+00:00","dateModified":"2024-07-23T14:22:27+00:00","description":"Scopri come utilizzare assertion e test con Bruno in questa guida approfondita scritta da Fabio Grande.","breadcrumb":{"@id":"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/#primaryimage","url":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading.jpg","contentUrl":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading.jpg","width":1368,"height":768,"caption":"bruno assertion e test"},{"@type":"BreadcrumbList","@id":"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/le-api-di-bruno-assertion-e-test\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.codemotion.com\/magazine\/"},{"@type":"ListItem","position":2,"name":"Backend","item":"https:\/\/www.codemotion.com\/magazine\/it\/backend-it\/"},{"@type":"ListItem","position":3,"name":"Le API di Bruno \u2013 Assertion e Test"}]},{"@type":"WebSite","@id":"https:\/\/www.codemotion.com\/magazine\/#website","url":"https:\/\/www.codemotion.com\/magazine\/","name":"Codemotion Magazine","description":"We code the future. Together","publisher":{"@id":"https:\/\/www.codemotion.com\/magazine\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.codemotion.com\/magazine\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.codemotion.com\/magazine\/#organization","name":"Codemotion","url":"https:\/\/www.codemotion.com\/magazine\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.codemotion.com\/magazine\/#\/schema\/logo\/image\/","url":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2019\/11\/codemotionlogo.png","contentUrl":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2019\/11\/codemotionlogo.png","width":225,"height":225,"caption":"Codemotion"},"image":{"@id":"https:\/\/www.codemotion.com\/magazine\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/Codemotion.Italy\/","https:\/\/x.com\/CodemotionIT"]},{"@type":"Person","@id":"https:\/\/www.codemotion.com\/magazine\/#\/schema\/person\/d47d145dba7746776b7d736aecffdd44","name":"Fabio Grande","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/06\/fabio-grande-profile-100x100.jpg","url":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/06\/fabio-grande-profile-100x100.jpg","contentUrl":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/06\/fabio-grande-profile-100x100.jpg","caption":"Fabio Grande"},"url":"https:\/\/www.codemotion.com\/magazine\/author\/fabio-grande\/"}]}},"featured_image_src":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading-600x400.jpg","featured_image_src_square":"https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading-600x600.jpg","author_info":{"display_name":"Fabio Grande","author_link":"https:\/\/www.codemotion.com\/magazine\/author\/fabio-grande\/"},"uagb_featured_image_src":{"full":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading.jpg",1368,768,false],"thumbnail":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading-150x150.jpg",150,150,true],"medium":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading-300x168.jpg",300,168,true],"medium_large":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading-768x431.jpg",768,431,true],"large":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading-1024x575.jpg",1024,575,true],"1536x1536":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading.jpg",1368,768,false],"2048x2048":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading.jpg",1368,768,false],"small-home-featured":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading-100x100.jpg",100,100,true],"sidebar-featured":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading-180x128.jpg",180,128,true],"genesis-singular-images":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading-896x504.jpg",896,504,true],"archive-featured":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading-400x225.jpg",400,225,true],"gb-block-post-grid-landscape":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading-600x400.jpg",600,400,true],"gb-block-post-grid-square":["https:\/\/www.codemotion.com\/magazine\/wp-content\/uploads\/2024\/07\/Bruno.Dog_.Reading-600x600.jpg",600,600,true]},"uagb_author_info":{"display_name":"Fabio Grande","author_link":"https:\/\/www.codemotion.com\/magazine\/author\/fabio-grande\/"},"uagb_comment_info":0,"uagb_excerpt":"Tutti noi che lavoriamo pressoch\u00e9 quotidianamente con chiamate API, abbiamo trovato grandi compagni di viaggio nei Client dedicati, grazie ai quali possiamo: Per ottemperare queste attivit\u00e0 \u00e8 sufficiente impostare una request ed eseguirla, leggendo lo status della response e, se disponibile, valutare visivamente il payload restituito in risposta. Ma Bruno, per noi, pu\u00f2 fare molto&#8230;&hellip;","lang":"it","_links":{"self":[{"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/posts\/28882","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/users\/261"}],"replies":[{"embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/comments?post=28882"}],"version-history":[{"count":2,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/posts\/28882\/revisions"}],"predecessor-version":[{"id":28888,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/posts\/28882\/revisions\/28888"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/media\/28889"}],"wp:attachment":[{"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/media?parent=28882"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/categories?post=28882"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/tags?post=28882"},{"taxonomy":"collections","embeddable":true,"href":"https:\/\/www.codemotion.com\/magazine\/wp-json\/wp\/v2\/collections?post=28882"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}