Saltare al contenuto principale

Unit Testing React: Una Guida Pratica da Setup a CI/CD

Impara a testare unitariamente React, dal setup al CI/CD. Questa guida copre Jest, RTL, hook, async code, mocking e le migliori pratiche per applicazioni robuste cross-platform.

Martin Donadieu

Martin Donadieu

Content Marketer

Unit Testing React: Una Guida Pratica da Setup a CI/CD

Si apporta una piccola modifica al codice UI prima di pranzo. Sembrava innocua. Il testo di un pulsante cambia, una condizione di rendering si semplifica e un hook di aiuto prende in carico un nuovo ramo. La richiesta di pull è pulita, la revisione è veloce e il deploy esce.

Un'ora dopo, il supporto segnala che il login non funziona su una piattaforma. Web sembra tutto a posto. La shell desktop ha un percorso di rendering obsoleto. La build mobile si comporta in modo diverso dopo un cambiamento di stato asincrono. Nessuno l'ha notato perché i code avevano test, ma non i test giusti, e sicuramente non un sistema affidabile intorno a quei test.

That’s il problema principale con l’esecuzione di test di unità per React in team di produzione. Scrivere alcuni test che passano non è difficile. Costruire un insieme di test che ti protegga durante i refactoring, i treni di rilascio, le correzioni di emergenza e la confezione cross-platform è la parte difficile. Le app React non falliscono perché un team dimentica come chiamare render(). Falliscono perché i test si allontanano dai dettagli di implementazione, il comportamento asincrono viene coperto e il CI tratta i test come un casella di controllo invece di una porta di rilascio.

Il testing di unità moderno per React funziona quando si comporta come un sistema di sicurezza. Feedback veloci localmente. Controlli deterministici nel CI. Confine chiari intorno a cosa appartiene a un test di unità e cosa non appartiene. Ciò conta ancora di più quando lo stesso codice React viene distribuito attraverso i browser, Capacitor contenitori o shell di Electron.

Elenco dei contenuti

Perché gli unit test di React sono la tua rete di sicurezza migliore

Gli unit test guadagnano la loro parte quando catturano l'errore che eri convinto non potesse accadere. In React, questo significa spesso che un componente continua a renderizzare, ma il comportamento su cui un utente dipende è cambiato. Un pulsante disabilitato diventa cliccabile. Uno stato di caricamento non si cancella mai. Un messaggio di fallback scompare dopo un refactor. Questi errori sono piccoli in code e costosi in produzione.

Il testing di React è cambiato in un modo importante quando React Testing Library è diventata il modello mainstream per il testing del comportamento invece degli interni, spingendo le squadre verso test che riflettono il comportamento dell'utente piuttosto che le proprietà o lo stato dei componenti, come riflessi nella guida di testing di React Native in Panoramica del testing di React Native. Questo spostamento conta perché il code di React viene riarrangiato costantemente. Le hook si spostano. I componenti si dividono. Il contesto viene introdotto. Un test legato alla struttura interna si rompe durante refactor sani. Un test legato al comportamento visibile sopravvive di solito.

Cosa dovrebbe proteggere un test di unità

Un buon test di unità React protegge un piccolo contratto:

  • Output visualizzato: Il utente vede il testo, il label, lo stato o il fallback corretto?
  • Comportamento di interazione: Cliccando, digitando o toggliando cambia la UI correttamente?
  • Gestione dei confini: Il componente si comporta correttamente quando riceve gli input previsti, dati mancanti o un percorso di errore?

Un test debole protegge la cosa sbagliata:

  • Componenti interni: Forma dello stato, metodi privati, proprietà di implementazione solo
  • Meccanismi del framework: Se React ha aggiornato una funzione di hook in modo esatto come ti aspettavi internamente
  • Dettagli del figlio: La markup di cui è proprietario un componente nidificato che non intendi verificare qui

Regola pratica: Se puoi rifare il componente senza cambiare cosa il utente vede o fa, il test non dovrebbe cambiare nemmeno.

Il test di unità si trova in un sistema di testing più ampio. Non cercano di dimostrare che l'app funziona da capo a fondo. Sono la prima linea di difesa in qualsiasi stack di testing automatizzato per app di produzione. Per le squadre di React che inviano spesso, la fiducia deriva da questa divisione del lavoro. I test di unità catturano le regressioni locali velocemente. I test di integrazione verificano le giunzioni. I test end-to-end confermano le vie critiche. Omettere la layer di unità e tutto ciò che è più lento a valle deve sostenere troppo peso..

Configurazione della tua ambiente di testing moderno per React

Un ambiente di testing fragile crea test flaccidi prima di aver scritto un singolo assert. Molti sviluppatori incolpano Jest, jsdom o React quando il problema sottostante è una configurazione incoerente across macchine locali e CI. La soluzione è rendere l'ambiente noioso. Noioso è buono qui.

Un ambiente di lavoro pulito con un monitor del computer che mostra il testing di unità di React __CAPGO_KEEP_0__ in un __CAPGO_KEEP_1__ editor.

A clean workspace featuring a computer monitor displaying React unit testing code in a code editor.

Il tuo ambiente di testing è pronto per essere utilizzato

For un'app React moderna, soprattutto quella creata con Vite, lo setup di base dovrebbe includere:

  • Un eseguibile di test: Jest rimane comune, soprattutto in vecchi codici React e stack di CI aziendali.
  • Un ambiente simile a un browser: jsdom perché i test dei componenti possano renderizzare l'output DOM.
  • Utilità di Testing Library: @testing-library/react e @testing-library/jest-dom
  • Un unico punto di ingresso di setup: Un file per registrare gli matcher e le mock globali.

La guida di testing di React enfatizza un workflow semplice: rendere il componente in un ambiente jsdom, interrogare l'interfaccia utente con selezionatori come getByText o getByRole, attivare l'interazione e affermare il cambiamento DOM, come descritto in Documentazione di testing ReactQuel workflow rimane affidabile solo se ogni macchina esegue lo stesso ambiente di test.

Un setup Jest pratico solitamente assomiglia a questo:

// jest.config.js
module.exports = {
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['<rootDir>/src/setupTests.js'],
  moduleNameMapper: {
    '\\.(css|less|scss)$': 'identity-obj-proxy',
    '^@/(.*)$': '<rootDir>/src/$1',
  },
  transform: {
    '^.+\\.(js|jsx|ts|tsx)$': 'babel-jest',
  },
};

If your team uses SWC instead of Babel, that’s fine. The point isn’t the transformer. The point is consistency. Choose one path and standardize it in the repo. If you want a good companion reference for broader JavaScript testing conventions, Capgo’s guida ai test unitari in JavaScript è un utile documento di passaggio di squadra.

Aggiungi il file di configurazione che la tua suite dipenderà

Un setupTests.js salva molto rumore ripetuto:

import '@testing-library/jest-dom';

Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: jest.fn().mockImplementation(query => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: jest.fn(),
    removeListener: jest.fn(),
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    dispatchEvent: jest.fn(),
  })),
});

Questo file è dove risolvi le lacune di ambiente una volta sola al posto di dentro venti file di test. Aggiungi mock per le API che la tua UI dipende, come matchMedia, ResizeObserver, o IntersectionObserver, se la tua libreria di componenti le aspetta.

Senza questo, gli sviluppatori patcheranno globali ad hoc. Ciò crea test inconsistenti e fallimenti difficili da tracciare. La passata di un run locale passa perché gli utenti hanno aggiunto un mock manuale in un file. CI fallisce perché lo setup non è stato condiviso.

Tenere comportamento locale e CI allineato

La riga di comando locale dovrebbe corrispondere alla riga di comando CI il più possibile. Se gli sviluppatori eseguono il watch mode con impostazioni permissive ma CI esegue una configurazione più rigorosa, otterrai fallimenti sorprendenti dopo il merge. Tenere i script espliciti:

{
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watch",
    "test:ci": "jest --runInBand --coverage"
  }
}

Un breve walkthrough aiuta i nuovi membri del team a ottenere la stessa baseline velocemente:

La scelta di impostazione più impattante è la disciplina intorno alle impostazioni predefinite. Mettere gli alias nella configurazione. Mettere i mock di ambiente in un file di setup. Utilizzare jsdom per i test di UI e un ambiente più leggero per le utility pura quando possibile. Quanto meno il comportamento personalizzato che ogni singolo test richiede, tanto più affidabile il tuo sistema diventa.

Scrivere Test di Componenti Significativi

Gli organizzazioni non hanno un problema a scrivere test. Hanno un problema a scrivere test che ancora hanno senso sei mesi dopo.

Lo standard per il testing di unità dei componenti React è ancora il giusto: rendere il componente, interrogare l'interfaccia utente con selezionatori centrati sull'utente, attivare un'interazione e affermare il cambiamento DOM risultante, che tiene i test lontani dai dettagli di implementazione come stato o proprietà, come descritto nel guide di testing React. Il trucco è applicare quel pattern con moderazione.

Testa l'accordion come un utente lo utilizza

Prendi un componente base. Rende un pulsante con un titolo. Il contenuto del pannello inizia nascosto. Cliccando sul pulsante si rivela il contenuto e si aggiorna lo stato di accessibilità. Accordion Quel comportamento è sufficiente per diversi test utili:

La prima renderizzazione mostra il titolo ma non il contenuto.

  1. Cliccando sul trigger si rivela il contenuto.
  2. Cliccando di nuovo lo si comprime.
  3. Gli attributi di accessibilità riflettono lo stato visibile.
  4. Quel punto ultimo viene spesso trascurato. Se il tuo componente utilizza aria- o struttura basata su ruoli, verificali. Non sono dettagli di implementazione. Sono parte del contratto faccia-a-faccia con l'utente.

I migliori test dei componenti si leggono come un rapporto di bug che non vorresti mai ricevere. aria-expanded, aria-controlsInitial render shows the title but not the content.

Clicking the trigger reveals the content.

Scegli le query in base all'intento

La libreria di testing di React ti offre diversi stili di query, ma non sono intercambiabili. Scegliere quello sbagliato rende i test rumorosi o ingannevoli.

Tipo di Query Quando l'elemento viene trovato Quando l'elemento non viene trovato Esempio di utilizzo
getBy Restituisce l'elemento immediatamente Lancia un errore immediatamente Afferma che un pulsante o un titolo dovrebbe già essere sullo schermo
queryBy Restituisce l'elemento immediatamente Restituisce null Afferma che il contenuto nascosto non dovrebbe esistere prima dell'interazione
findBy Si risolve quando l'elemento appare Rifiuta dopo aver atteso Assert il contenuto caricato in modo asincrono appare dopo una richiesta o un aggiornamento differito

Un semplice modello mentale aiuta:

  • Usa getBy per le cose che devono già esistere.
  • Usa queryBy per le cose che non devono ancora esistere.
  • Usa findBy quando le modifiche all'interfaccia utente avvengono in seguito.

Se un test inizia con findBy per tutto, di solito significa che l'autore non è sicuro quando il componente si aggiorna. Quella incertezza diventa instabilità in seguito.

Un esempio pratico di accordione

Ecco un componente rappresentativo:

function Accordion({ title, children }) {
  const [open, setOpen] = React.useState(false);

  return (
    <section>
      <button
        aria-expanded={open}
        aria-controls="accordion-panel"
        onClick={() => setOpen(prev => !prev)}
      >
        {title}
      </button>
      {open ? (
        <div id="accordion-panel">
          {children}
        </div>
      ) : null}
    </section>
  );
}

Ecco la forma di testi degni di essere conservati:

import { render, screen, fireEvent } from '@testing-library/react';

test('renders the accordion title and hides content initially', () => {
  render(<Accordion title="Shipping details">Delivery takes 3 days</Accordion>);

  expect(screen.getByRole('button', { name: /shipping details/i })).toBeInTheDocument();
  expect(screen.queryByText(/delivery takes 3 days/i)).not.toBeInTheDocument();
});

test('reveals content when the trigger is clicked', () => {
  render(<Accordion title="Shipping details">Delivery takes 3 days</Accordion>);

  fireEvent.click(screen.getByRole('button', { name: /shipping details/i }));

  expect(screen.getByText(/delivery takes 3 days/i)).toBeInTheDocument();
});

test('updates aria-expanded when opened', () => {
  render(<Accordion title="Shipping details">Delivery takes 3 days</Accordion>);

  const button = screen.getByRole('button', { name: /shipping details/i });
  expect(button).toHaveAttribute('aria-expanded', 'false');

  fireEvent.click(button);

  expect(button).toHaveAttribute('aria-expanded', 'true');
});

Ciò che manca è altrettanto importante. Non ci sono affermazioni contro lo stato interno. Nessuna verifica che sia stata chiamata. Nessuna snapshot dell'intera albero di rendering. Quei test aggiungerebbero manutenzione, non fiducia. setOpen Alcuni abitudini rendono i test dei componenti più forti:

Preferisci le query basate sul ruolo:

  • I pulsanti, i titoli, i dialoghi, le avvisaglie e gli input dovrebbero essere trovati di solito per ruolo. Mantieni ogni test stretto:
  • Un comportamento visibile dell'utente per test mantiene le fallite leggibili. Nomi i test dopo gli esiti:
  • “Aggiorna aria-expanded quando aperto” è molto più utile di “funziona correttamente.” __CAPGO_KEEP_0__

If un componente è difficile da testare attraverso il DOM, ciò spesso rivela un problema di design. Forse nasconde lo stato in un posto sbagliato. Forse manca la marcatura semantica. Le buone prove spesso spingono le squadre verso componenti migliori.

Testare Hook personalizzati e logica di applicazione

Gli app React nascondono un sacco di comportamento importante al di fuori dei componenti. Le transizioni di stato vivono nei hook. La validazione e la formattazione vivono nelle funzioni ausiliarie. La modifica dei dati spesso avviene prima che qualsiasi cosa venga visualizzato. Se si testano solo i componenti visibili, si perderà una parte molto grande del code che può ancora rompere il comportamento di produzione.

Gli hook hanno bisogno di un harness React-aware

Un hook personalizzato ha ancora bisogno di React per eseguirsi correttamente, quindi testalo con renderHook e avvolgi le chiamate che cambiano lo stato in act().

Un piccolo useToggle hook è un buon esempio:

import { useState, useCallback } from 'react';

export function useToggle(initialValue = false) {
  const [value, setValue] = useState(initialValue);
  const toggle = useCallback(() => setValue(current => !current), []);
  return { value, toggle };
}

La sua prova dovrebbe restare focalizzata sul contratto pubblico:

import { renderHook, act } from '@testing-library/react';
import { useToggle } from './useToggle';

test('returns the initial value', () => {
  const { result } = renderHook(() => useToggle(true));
  expect(result.current.value).toBe(true);
});

test('toggles the value', () => {
  const { result } = renderHook(() => useToggle(false));

  act(() => {
    result.current.toggle();
  });

  expect(result.current.value).toBe(true);
});

Questa prova è utile perché lo hook stesso è l'unità. Non si sta testando gli interni di React. Si sta verificando il comportamento esterno dello hook.

Per le squadre di prodotto che stanno costruendo UI o primitive di funzionalità riutilizzabili, questo pattern conta molto. Gli hook spesso diventano l'interfaccia condivisa tra app, sistemi di design o strumenti interni. Se si sta progettando un comportamento riutilizzabile con intento commerciale, le risorse su hook per prodotti dei maker può aiutare a presentare gli hook come blocchi costruttivi standardizzati piuttosto che solo dettagli di implementazione.

La logica pura dovrebbe rimanere pura nei test

Non tutto ha bisogno di jsdom, React, o Testing Library. Se una funzione è pura, testiamola con Jest puro in un ambiente Node.

Esempio:

export function formatDisplayName(firstName: string, lastName: string) {
  return `${firstName.trim()} ${lastName.trim()}`.trim();
}

Quel test dovrebbe essere estremamente semplice:

import { formatDisplayName } from './formatDisplayName';

test('joins and trims both names', () => {
  expect(formatDisplayName(' Ada ', ' Lovelace ')).toBe('Ada Lovelace');
});

test('handles a missing last name', () => {
  expect(formatDisplayName('Ada', '')).toBe('Ada');
});

Il vantaggio qui è velocità e chiarezza. Quando una funzione non ha bisogno di un albero di rendering, non darle uno. Le librerie React aggiungono un sovraccarico. Mantieni i test della logica aziendale piccoli, veloci e vicini alla funzione che verificano.

Una suddivisione pratica funziona bene:

  • Hook: Usa renderHook, act(), e provider wrapper quando necessario.
  • Utility: Usa Jest puro e nessun DOM.
  • Logica incrociata di stato: Trasferiscilo in aiuti testabili quando il test del componente inizia a fare troppo.

I team spesso sovraccaricano i test dei componenti con affermazioni di logica che appartengono più in basso nella pila. Estrarre quella logica dà due benefici. Il test del componente si pulisce, e il test della logica si velocizza.

Maestri di Tecniche Avanzate Mocking e Async

La maggior parte delle suite React meno affidabili si rompono in due punti. Si rompono ai confini delle dipendenze, e si rompono intorno al tempo.

È per questo che il testing asincrono e il mocking sono la linea di demarcazione tra un insieme di test giocattolo e uno che puoi fidarti prima della release. Un'analisi attribuisce 46,5% di instabilità dei test a problemi ambientali o legati alle risorse, come il timing asincrono in questa analisi di testing React. In app React, questo si traduce direttamente in transizioni di stato, rendering ritardato, interfaccia utente guidata da rete, e test che ipotizzano invece di aspettare deterministicamente.

Un diagramma di confronto delle Tecniche di Testing React Avanzate, specificamente focalizzato sul Mocking delle Dipendenze contro il Testing Asincrono.

Mimetizza i confini, non ogni layer

La via più veloce per scrivere un test ingannevole è quella di mimetizzare metà della tua albero di componenti e poi affermare che i tuoi propri mock hanno funzionato.

Per un componente che recupera dati di account, mimetizza il client di rete o il modulo API. Non mimetizzare l'hook, il componente di riga figlio, lo spinner di caricamento e tre funzioni di utilità a meno che il test non abbia veramente bisogno di isolamento in quei punti di connessione.

Usa questo set di regole:

  • Mimetizza i servizi esterni: Client HTTP, analisi, API del browser esclusivo, ponti nativi
  • Mimetizza le API di piattaforma instabile: matchMediatimer, interfacce di caricamento predefinite di Electron, plugin Capacitor quando non disponibili in jsdom
  • Evita di mimetizzare le tue interne per impostazione predefinita: hook personalizzati, semplici figli, utilità locali

Se un test passa perché tutti i parti difficili sono stati sostituiti con fake, non ti ha comprato molto fiducia di rilascio.

Per le squadre che vogliono esempi e modelli intorno alle API di esecuzione, il Capgo Categoria Jest è una libreria di riferimento pratica, soprattutto quando si inizia a onboardare i developer che conoscono React ma non le meccaniche di testing ancora.

I test asincroni falliscono quando il timing è vago

Le fallite asincrone solitamente provengono da uno dei tre errori:

  1. Il test afferma troppo presto.
  2. Il test aspetta con timer arbitrari.
  3. Il componente si aggiorna più volte, ma il test modella solo una transizione.

Un test asincrono stabile solitamente ha questa forma:

test('shows user details after data loads', async () => {
  render(<UserProfile userId="42" />);
  expect(screen.getByText(/loading/i)).toBeInTheDocument();

  expect(await screen.findByText(/account owner/i)).toBeInTheDocument();
});

O, quando hai bisogno di aspettare una condizione specifica:

await waitFor(() => {
  expect(screen.getByRole('alert')).toBeInTheDocument();
});

Usa findBy quando l'apparizione di un elemento è l'evento a cui ti preoccupi. Usa waitFor quando la condizione è più ampia o lo stato non può essere espresso con una sola query. Evita setTimeout a meno che non stiate testando esplicitamente il comportamento del timer e non stiate utilizzando timer fittizi.

L'ecosistema di testing di React aspetta anche che rispettiate act() semantica intorno agli aggiornamenti. La libreria di testing gestisce molte di queste cose per voi, ma se state guidando lo stato manualmente o avanzando i timer, ancora dovete pensare a quando gli aggiornamenti si scaricano.

Sapere quale strumento di mocking utilizzare

Gli strumenti di mocking diversi risolvono problemi diversi:

Strumento Miglior uso Mistake comune
jest.fn() Callback fittizi autonomi o funzioni injectate Utilizzarlo per sostituire un intero modulo quando un semplice callback è sufficiente
jest.spyOn() Osservare o sovrascrivere un metodo su un oggetto o modulo reale Dimenticare di ripristinare l'implementazione originale
jest.mock() Sostituisci una dipendenza di modulo al confine di importazione Simulare grandi moduli per impostazione predefinita e perdere comportamento significativo

Esempi aiutano:

  • Raggiungi per jest.fn() quando un componente prende un onSubmit prop.
  • Usa jest.spyOn() quando hai bisogno di verificare console.errorun metodo di archiviazione o una chiamata esportata API.
  • Usa jest.mock() quando l'importazione di un modulo colpirebbe altrimenti I/O, code nativo o comportamento al di fuori del confine di unità.

Un'area avanzata che molti guide trascurano è il testing del percorso di errore in React moderno. Le barriere di errore, le modifiche di stato ritardate e gli UI di fallback asincroni meritano test di prima classe, non solo l'esempio di click 'happy path'. Se un figlio lancia un errore, assicurati che il UI di fallback sia visibile. Se una richiesta fallisce, assicurati che lo stato di recupero visibile sia presente. Se un pulsante è disabilitato durante il caricamento, assicurati che sia così. Sono quei bug che gli utenti ricordano.

Migliorare la qualità e la strategia dei test

Molte squadre ancora inseguono la copertura come se fosse la stessa cosa della fiducia. Non è così.

Puoi raggiungere un obiettivo di copertura e ancora non individuare le regressioni che contano. Una suite piena di affermazioni superficiali, snapshot ampi e interni simulati crea l'apparenza di sicurezza aumentando al tempo stesso il costo di manutenzione.

 Un infographic che confronta i benefici della qualità dei test con l'overhead di manutenzione delle suite di test di alta quantità.

La copertura è una mappa, non il fine

I rapporti di copertura sono utili quando rispondono a una domanda: quali percorsi critici non hanno ancora una protezione?

Non sono utili quando spingono gli sviluppatori a testare wrapper triviali, markup statico o file di passaggio di una riga solo per spostare un percentile. Tratta la copertura come uno strumento di scoperta. Se lo stato di autenticazione, le azioni di fatturazione, le bandiere di feature o le richieste di aggiornamento non hanno test, è un segnale. Se un componente iconico presentazionale non ha test, di solito non è così.

Una domanda di revisione sana è semplice: questo test riduce il rischio di rilascio?

  • Sì: Verifica il comportamento visibile dell'utente su un percorso critico.
  • Forse: Protegge la logica di business che è facile rompere durante la rifattorizzazione.
  • No: Afferma dettagli di implementazione o duplica il valore di un altro test.

Cosa non testare

Molti guide React non dedicano abbastanza tempo all'omissione. Questo gap è importante perché il sovrastegno e il testing dei dettagli di implementazione creano suite fragili che passano mentre l'esperienza utente si rompe, come notato nella guida di BrowserStack su cosa non testare in React.

Svuota o limita drasticamente questi pattern:

  • Affermazioni di stato interno: Non testare isOpen direttamente quando puoi testare se il pannello si è aperto.
  • Comportamento del framework: Non testare che React abbia chiamato un effetto. Testa il risultato di cosa cambia l'effetto.
  • Interni di librerie terze: Verifica l'integrazione con un picker di date o router, non la logica di rendering della libreria.
  • Unità sovraccaricate: Se hai mockato ogni figlio e helper, potresti non essere più in grado di testare un comportamento significativo.

Gli test cattivi sono peggio della mancanza di test quando bloccano i refactor e non riescono a catturare i bug di produzione.

Un utile heuristico è la proprietà dei confini. Testa cosa il tuo code possiede. Non testa cosa React, il browser o una libreria matura già possiedono a meno che il tuo layer di integrazione non cambi il contratto.

Dove i snapshot sono utili e dove li danneggiano

I snapshot non sono inutili. Sono solo facili da abusare.

Usali con parsimonia per i componenti con un output stabile e semplice dove una diff strutturale ampia è significativa. Evitali per i componenti interattivi o dinamici perché diventano rumore. I developer smettono di leggerli e iniziano a modificarli a riflessi.

Alternativi migliori esistono:

  • Per la rendering condizionale, assicurati della presenza o assenza di un testo chiave.
  • Per i cambiamenti di stato visivi, assicurati del ruolo, del label o dell'attributo che conta.
  • Per gli errori e i fallback, assicurati del messaggio o della regione di allarme effettivo.

If il tuo team ha bisogno di un processo di qualità più ampio oltre ai test unitari, un solido compagno è un flusso di garanzia della qualità dell'applicazione che tratta test, controlli di rilascio e pianificazione del rollback come un sistema unico. È questo lo spostamento di mentalità che migliora la qualità dei test più velocemente. Fermati a chiederti quanti test hai. Inizia a chiederti quali fallimenti potrebbero ancora raggiungere gli utenti. Integrare i Test in un Flusso di Rilascio Continuo e Automatizzato Un suite di test che si esegue solo su un laptop di sviluppatore è una proposta, non un controllo.

La suite diventa operativa quando ogni richiesta di pull esegue gli stessi controlli in un ambiente pulito e blocca le fusioni quando quei controlli falliscono. Sembra ovvio, ma molti team lasciano ancora dei vuoti critici. I test vengono eseguiti manualmente. I rapporti di copertura sono facoltativi. I job di packaging e rilascio iniziano prima che i job di test siano terminati. È così che le piccole regressioni dell'interfaccia utente finiscono in fallimenti di rilascio più grandi.

Un diagramma a cinque passaggi che illustra il processo di integrazione dei test automatizzati React in un flusso di rilascio continuo e automatizzato.

Una richiesta di pull dovrebbe attivare lo stesso gate ogni volta

Per testare React come un sistema di sicurezza, il CI ha bisogno di alcuni elementi essenziali:

Esegui i test su ogni richiesta di pull

Installa le dipendenze dal file di lock

  • Utilizza lo stesso comando di test ogni volta
  • __CAPGO_KEEP_0__
  • __CAPGO_KEEP_0__
  • Falli rapidamente in caso di fallimenti dei test
  • Pubblica gli artefatti solo dopo che i test passano

Questo è il nucleo delle pratiche di distribuzione continua per i team di app. Costruisci la fiducia prima della release, non dopo.

Un semplice workflow di GitHub Actions è sufficiente per molti team:

name: test

on:
  pull_request:
  push:
    branches:
      - main

jobs:
  react-tests:
    runs-on: ubuntu-latest

    steps:
      - name: Check out code
        uses: actions/checkout@v4

      - name: Set up Node
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm

      - name: Install dependencies
        run: npm ci

      - name: Run unit tests
        run: npm run test:ci

Questo non è un caso, e questo è il punto. Le pipeline più forti sono spesso le meno sorprendenti.

Perché questo conta di più per Capacitor e Electron

Le app React cross-platform presentano un rischio di rilascio maggiore rispetto alle app browser-only perché la stessa UI code spesso viene distribuita in contenitori diversi con diverse assunzioni di runtime.

Un paio di esempi mostrano dove le pipeline aiutano:

  • Capacitor app: Le app web code possono passare localmente ma fallire quando cambia il comportamento di un ponte di plugin, uno stato offline o un caso di ciclo di vita dell'app dopo la confezione.
  • Applicazioni Electron: Un componente renderer può dipendere da API preload, messaggi di finestra o stato desktop esclusivo che non esisteranno in test di browser puro a meno che non vengano deliberatamente simulati.
  • Treni di rilascio condivisi: Un singolo bundle danneggiato può influenzare più target se il processo di distribuzione non limita strettamente la pubblicazione.

Ecco perché i test unitari dovrebbero eseguirsi prima delle attività di packaging, e le attività di packaging dovrebbero eseguirsi prima delle attività di distribuzione. Ogni fase riduce il rischio. I test unitari individuano le regressioni locali velocemente. La verifica del packaging della piattaforma verifica le assunzioni sull'ambiente. L'approvazione manuale o il rilascio in fase di test gestisce la fiducia finale nel rilascio.

Un workflow pratico GitHub Actions

Un pipeline più maturo divide spesso le responsabilità:

  1. Attività di test: Test unitari e hook veloci
  2. Attività di costruzione: Costruzione di produzione solo dopo che i test passano
  3. Attività di packaging: Capacitor sincronizzazione, packaging di Electron o bundle di artefatti
  4. Lavorazione di rilascio: Pubblica solo da rami o tag approvati

Per le squadre che distribuiscono aggiornamenti in tempo reale a Capacitor o applicazioni di Electron, questo è dove la strumentazione di rilascio conta. Una delle opzioni in quel workflow è Capgo, che pubblica bundle web firmati per applicazioni CapacitorJS e Electron con supporto per il rollback e controlli di distribuzione basati su canali. In pratica, ciò significa che il tuo test di React può agire come la prima porta di uscita prima che qualsiasi bundle web sia promosso alla consegna di staging o produzione.

La regola operativa è semplice. Non lasciare che l'infrastruttura di rilascio compensi per test deboli. Utilizza l'infrastruttura di rilascio dopo che i test affidabili hanno già eliminato le modifiche difettose.

Un sistema di testing affidabile cambia il comportamento della squadra. Gli ingegneri si uniscono con meno esitazione. I revisori si concentrano sui casi di confine invece di ripetere le basi manualmente. I responsabili delle rilascio smettono di trattare ogni deploy come un gioco di roulette. È questo l'esito di fare il testing unitario di React bene.


Se la tua squadra distribuisce React attraverso Capacitor o Electron, la sicurezza del rilascio dipende da più di test locali verdi. Capgo dà alle squadre un modo controllato per pubblicare aggiornamenti web firmati, targettizzare i canali di distribuzione e tornare indietro sui bundle difettosi senza dover aspettare la revisione del negozio, il che si adatta naturalmente dietro una pipeline CI che richiede già di superare i test unitari prima della distribuzione.

Aggiornamenti in tempo reale per le app Capacitor

Quando un bug nel layer web è attivo, invia la correzione attraverso Capgo invece di aspettare giorni per l'approvazione della store. Gli utenti ricevono l'aggiornamento in background mentre le modifiche native rimangono nel normale percorso di revisione.

Inizia subito

Ultimi articoli dal nostro Blog

Capgo ti offre le migliori informazioni che ti servono per creare un'app mobile veramente professionale.