Link Cerca Menu Expand Document

Preparació i distribució

Resultats d’aprenentatge:

  1. Avalua el funcionament d’aplicacions dissenyant i executant proves.
  2. Documenta aplicacions seleccionant i utilitzant eines específiques.
  3. 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:

  1. Proves unitàries: validació dels blocs més atòmics del software, les funcions. Son poc
  2. Proves d’integració: validació que diferents peces del software funcionen juntes.
  3. 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:

  1. Les proves són tan importants com el codi.
  2. Prova només una funcionalitat per prova. Que sigui curta farà que sigui més clara.
  3. Escriure el nostre codi amb funcions petites ens ajudarà a fer proves més granulars.
  4. Estructura les proves amb “arrange, act, assert” o bé “given, when, then”.
  5. 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:

  1. Arrange: prepara les entrades i els objectius de la prova.
  2. Act: invoca el comportament, cridant una funció, interactuant amb un API, una pàgina web, etc.
  3. 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:

  1. Afegir un nou test
  2. Executar tots els tests. La nova prova ha de fallar.
  3. Escriure el codi més senzill que permeti passar el test.
  4. Totes les proves han de funcionar novament.
  5. 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ó

Veure JSDoc i TSDoc.

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.

Referències