Preparació i distribució
Resultats d’aprenentatge:
- Avalua el funcionament d’aplicacions dissenyant i executant proves.
- Documenta aplicacions seleccionant i utilitzant eines específiques.
- Prepara aplicacions per a la seva distribució avaluant i analitzant eines específiques.
Proves
Tenir codi llest per a producció requereix fer proves. Com que no podem tenir milers de testers, sorgeix la necessitat d’automatitzar-les. Un procés que va de la mà de les pràctiques de desenvolupament àgil i el CD (Continuous delivery).
La piràmide de les proves
La piràmide de les proves és una metàfora visual que descriu les capes de les proves:
- Proves unitàries: validació dels blocs més atòmics del software, les funcions. Son poc
- Proves d’integració: validació que diferents peces del software funcionen juntes.
- Proves end to end (E2E): validació des del punt de vista de l’usuari, tractant el software com una caixa negra.
En el món real, aquesta categorització no és estricta, hi ha proves que poden estar al mig d’aquestes capes.
. | Unitàries | Integració | End-to-end |
---|---|---|---|
Objectiu principal | funcions individuals | integració de funcions | funcionalitat d’usuari |
Quantitat | Nombroses | Una mica freqüent | Escassa |
Velocitat | Molt alta | Mitjana | Lenta |
Freqüència d’execució | Alta, quan es desenvolupen una funció | Regular, quan es desenvolupa una funcionalitat | Quan s’acaba una funcionalitat |
Feedback | Entrada i sortida per a la funció | Comportament problemàtic | Funcionalitat incorrecta |
Cost | Baix: petita, fàcil d’actualitzar, executar i entendre | Moderat | Costós |
Coneixement de l’aplicació | Acoblat al codi | Codi, bases de dades, xarxa, arxius | Inconscient |
Beneficis | Feedback ràpid durant el desenvolupament, evitar regressions, documentació | Ús de llibreries de tercers, comprova efectes secundaris | Funcionament correcte de l’usuari |
Tècniques
Qualitat de les proves
Aquestes són algunes pistes per a aconseguir proves que siguin mantenibles:
- Les proves són tan importants com el codi.
- Prova només una funcionalitat per prova. Que sigui curta farà que sigui més clara.
- Escriure el nostre codi amb funcions petites ens ajudarà a fer proves més granulars.
- Estructura les proves amb “arrange, act, assert” o bé “given, when, then”.
- La claredat és més important que no repetir-se.
Arrange, act i assert
L’estructura recomanada d’una prova és una seqüència de tres passos:
- Arrange: prepara les entrades i els objectius de la prova.
- Act: invoca el comportament, cridant una funció, interactuant amb un API, una pàgina web, etc.
- Assert: comprova que el resultat és l’esperat.
Test Doubles
Els test doubles són una tècnica que permet introduir una versió simplificada (o falsa) de les dades o funcions reals que permeten reduir la complexitat i facilitar les proves. Aquests objectes falsos poden classificar-se en:
- Dummy: objectes que es passen però no s’utilitzen.
- Fake: implementacions que funcionen, però no serveixen per a producció.
- Stubs: proporcionen respostes enllaunades a certes preguntes, no responent a res que no hi hagi a la prova.
- Spies: són stubs que guarden informació de com van ser cridats.
- Mocks: estan programats amb expectatives, i per tant poden comprovar si la crida no s’espera, o falta alguna crida, llençant excepcions. Per tant, abans d’utilitzar-los cal indicar quines són les expectatives. Molts desenvolupadors utilitzen “mocks” per parlar de forma general dels dobles.
Test-driven development
El TDD (desenvolupament guiat per proves) és una pràctica de desenvolupament que utilitza les proves unitàries per a escriure codi, i ho fa seguint el següent procediment:
- Afegir un nou test
- Executar tots els tests. La nova prova ha de fallar.
- Escriure el codi més senzill que permeti passar el test.
- Totes les proves han de funcionar novament.
- Fer refactoring quan calgui, utilitzant els tests per assegurar-se que la funcionalitat es preserva.
Eines
Jest i Vitest
El framework de proves JS més conegut és Jest. L’alternativa més interessant és Vitest, completament compatible amb Jest, més ràpid i que funciona amb mòduls.
Les proves JS s’emparellen amb el codi que es vol testar. Per exemple, feature.js
tindria les proves a feature.test.js
. Dins d’aquest arxiu s’han de poder trobar crides del tipus:
test('descripció de la prova', () => {
// codi de la prova (arrange, act, assert)
});
Alternativament, també s’utilitza la funció it
(sinònim) en lloc de test
. Aquestes altres funcions també ens serveixen per a fer el arrange de les proves:
beforeAll(() => {
// s'executa abans de totes les proves
});
beforeEach(() => {
// s'executa abans de cada prova
});
afterEach(() => {
// s'executa després de cada prova
});
afterAll(() => {
// s'executa després de totes les proves
});
Per al pas assert, tenim l’estructura expect(receivedValue).matcher(expectedValue)
. Els matchers més habituals són:
toBe
: per a comprovar valors primitius.toEqual
: per a comprovar objectes o arrays.not.matcher(expectedValue)
: per a negar qualsevol matcher.toBeNull, toBeUndefined, toBeDefined, toBeTruthy, toBeFalsy
: per a comprovar truthiness.toBeGreaterThan, toBeGreaterThanOrEqual, toBeLessThan, toBeLessThanOrEqual
: per a números.toMatch(/.../)
: per a expressions regulars.toContain
: per a comprovar si un array o iterable conté un ítem.toThrow
: per a comprovar si es llença una excepció. Permet comprovar el text també.
Per exemple, expect(2 + 2).toBe(4)
comprova que 2+2 són 4.
Testing Library
La Testing Library és un complement a jest o vitest que afegeix noves funcionalitats per a fer proves.
Aquesta llibreria conté:
- Queries, uns mètodes per trobar elements a una pàgina. getBy, queryBy i findBy.
- fireEvent i userEvent.
- waitFor
- Matchers addicionals per a jest/vitest
A més, és aplicable tan a aplicacions vanilla JS com a React o d’altres frameworks.
JSDOM
Es tracta de la implementació JavaScript d’un navegador sense interfície i molt més ràpid que els convencionals. Permet implementar proves automatitzades amb poca infraestructura i senzillesa.
Implementa l’objecte window.document i les seves API.
Configuració
Vanilla JS
La llibreria més fàcil d’utilitzar és Vitest, compatible amb la sintaxi de Jest i amb ES modules. Necessitarem npm
per a fer les proves, i això requereix crear un package.json
:
$ npm init -y
$ npm install --save-dev vitest@0.26.x jsdom
Caldria editar l’entrada script del nostre package.json
:
"test": "vitest --run --reporter verbose"
Si necessitem provar el DOM, caldria afegir l’environment jsdom a la capçalera de qualsevol arxiu de proves. La sintaxi de Vitest és la de Jest:
// @jest-environment jsdom
Podem fer npm test
per a executar els tests.
Per a fer proves DOM amb un script utilitzant Vitest, l’arrange podria ser:
const initialHtml = fs.readFileSync("./index.html", "utf-8");
document.body.innerHTML = initialHtml;
vi.resetModules(); // recarrega mòduls
await import('./script.js'); // aplica un script que estaria a l'HTML
React
No cal configurar res, el create-react-app ja ho fa per nosaltres: utilitza Jest amb Testing Library. Només caldria assegurar-se que tenim l’arxiu setupTests.js
a la carpeta src
del projecte React.
També, hem de tenir un script a package.json
per a l’entrada test
. El valor per defecte és:
"test": "react-scripts test",
Aquesta versió torna a executar els tests cada cop que desem un arxiu, i ens dona un menú per la consola. Si volem executar les proves quan volem, podem canviar el script a:
"test": "react-scripts test --watchAll=false --verbose",
Podem fer npm test
per a executar els tests.
Documentació
Distribució
Un cop tenim la versió de producció amb els arxius estàtics, és senzill fer la distribució.
Les aplicacions SPA poden ser distribuits utilitzant CDNs. En essència, tenim una aplicació que es connectarà al nostre backend i que pot estar a qualsevol servidor de continguts estàtics. Alternativament, podem distribuir-les al mateix servidor que el backend. Això ens estalvia la gestió dels headers CORS i poder gestionar de forma particular com se serveix l’app, però ens cal configurar el backend per a servir simultàniament l’app i el backend (API).
Una altra qüestió és què distribuim del frontend.
- No hi hauria d’haver cap dada confidencial, ja què el navegador permet veure tot el codi font de la nostra aplicació JS.
- Podem esborrar tots els comentaris del codi font amb una transformació
- Hauríem d’evitar mostrar el logging.
- Utilitzar variables al font per a donar valors que canvien en entorn de desenvolupament i de producció. Per exemple, a React, tenim els arxius .env i .env.production que permeten afegir variables. Per exemple, per a tenir una URL diferent de la nostra Rest API en cada entorn.