Vous faites une petite modification de l'interface utilisateur avant le déjeuner. Elle semble sans danger. L'étiquette d'un bouton change, une condition de rendu se simplifie et une fonctionnalité de hook prend une nouvelle branchée. La demande de tirage est propre, la revue est rapide et le déploiement est effectué.
An hour later, support reports that login stopped working on one platform. Web looks fine. The desktop shell has a stale render path. The mobile build behaves differently after an async state change. Nobody caught it because the code had tests, but not the right tests, and definitely not a reliable system around those tests.
Le principal problème avec les tests unitaires React dans les équipes de production est que l'écriture de quelques tests fonctionnels n'est pas difficile. Cependant, construire un ensemble de tests qui vous protège encore pendant les réfacteurs, les trains de livraison, les correctifs chauds et la mise en paquet cross-plateforme est la partie difficile. Les applications React ne se cassent pas parce que l'équipe a oublié comment appeler render()Les applications React se cassent parce que les tests se dirigent vers les détails d'implémentation, le comportement asynchrone est dissimulé et le CI traite les tests comme une case à cocher au lieu d'une porte de livraison.
Les tests unitaires modernes React fonctionnent lorsque cela se comporte comme un système de sécurité. Feedback rapide localement. Contrôles déterministes dans le CI. Les limites claires autour de ce qui appartient à un test unitaire et ce qui ne l'appartient pas. Cela compte encore plus lorsque le même code React est exécuté à travers les navigateurs, les conteneurs Capacitor ou les coquilles d'Electron.
Sommaire
- Pourquoi les tests unitaires React constituent votre meilleure sécurité
- Configurer votre environnement de test React moderne
- Écrire des tests de composants significatifs
- Testez les fonctions personnalisées et la logique d'application
- Maîtriser les techniques avancées : simulation et asynchrone
- Améliorer la qualité et la stratégie des tests
- Intégration des tests dans une chaîne de production CI/CD cross-plateforme
Pourquoi le test unitaire de React est votre meilleure protection
Les tests unitaires gagnent leur pain quand ils détectent l'erreur que vous étiez convaincu ne pouvait pas se produire. Dans React, cela signifie généralement que le composant continue de s'afficher, mais le comportement dont les utilisateurs ont besoin a changé. Un bouton désactivé devient cliquable. Un état de chargement ne se déclenche jamais. Un message de remplacement disparaît après une refacteur. Ces erreurs sont petites en code et coûteuses en production.
Le testage React a changé d'une manière importante quand Le React Testing Library est devenu le modèle principal de testage du comportement au lieu des détails internes, poussant les équipes vers des tests qui reflètent le comportement des utilisateurs plutôt que les propriétés ou l'état des composants, comme le montre la guidance de testage de React Native à L'aperçu de testage de React Native. Cette évolution compte car le React code se réorganise constamment. Les hooks se déplacent. Les composants se séparent. Le contexte est introduit. Un test lié à la structure interne se brise pendant des refacteurs sains. Un test lié au comportement visible survit généralement.
A quoi une unit test devrait protéger
Une bonne unit test React protège un petit contrat :
- Sortie de rendu : L’utilisateur voit-il le bon texte, l'étiquette, l'état ou le fallback ?
- Comportement d'interaction : La saisie, la sélection ou la modification changent-elles l’UI correctement ?
- Gestion des limites : Le composant se comporte-t-il correctement lorsqu'il reçoit les entrées attendues, les données manquantes ou une voie d'erreur ?
Une faible test protège la mauvaise chose :
- Intégrales du composant : Forme de l'état, méthodes privées, props d'implémentation uniquement
- Mécanismes du framework : Quoi qu'il en soit, React a-t-il mis à jour une boucle de manière exacte comme vous le souhaitiez internement ?
- Informations sur les enfants : La mise en forme est détenue par des composants imbriqués que vous n'avez pas l'intention de vérifier ici
Règle pratique : Si vous pouvez refacturer le composant sans changer ce que voit ou fait l'utilisateur, le test ne devrait pas non plus changer.
Les tests unitaires s'insèrent également dans un système de test plus large. Ils ne visent pas à prouver que l'application fonctionne de bout en bout. Ils constituent la couche rapide qui repère les régressions avant que vous n'ayez besoin d'un test au niveau du navigateur ou d'une validation au niveau du dispositif. C'est pourquoi ils constituent la première ligne de défense dans tout empilement raisonnable de tests automatisés pour les applications de production Pour les équipes React qui livrent souvent, la confiance provient de cette division du travail. Les tests unitaires repèrent rapidement les régressions locales. Les tests d'intégration vérifient les articulations. Les tests fin-à-fin confirment les chemins critiques. Omettre la couche unitaire et tout ce qui est plus lent en aval doit supporter trop de poids..
Configuration de votre environnement de test React moderne
Un environnement de test fragile crée des tests flous avant même que vous n'ayez écrit une seule assertion. Beaucoup de développeurs blâment Jest, jsdom ou React lorsque le problème sous-jacent est une configuration incohérente sur les machines locales et CI. La solution est de rendre l'environnement banal. Banal est bon ici.
Un espace de travail propre avec un moniteur de bureau affichant les tests unitaires de React __CAPGO_KEEP_0__ dans un éditeur __CAPGO_KEEP_1__.

__CAPGO_KEEP_0__
Pour une application React moderne, en particulier une créée avec Vite, le setup de base devrait inclure :
- Un exécuteur de tests : Jest reste commun, en particulier dans les anciens codebases React et les stacks CI d'entreprise.
- Un environnement simulant un navigateur :
jsdompermet aux tests de composants de rendre la sortie DOM. - Utilitaires de Testing Library :
@testing-library/reactet@testing-library/jest-dom - Un point d'entrée de configuration unique : Un seul fichier pour enregistrer les matcheurs et les mocks globaux
Le workflow clé que la guidance de test de React renforce est simple : rendre le composant dans un environnement jsdom, interroger l'interface utilisateur avec des sélecteurs comme getByText ou getByRoleDéclencher l'interaction, et vérifier le changement de la sortie DOM, comme décrit dans le Documentation de test ReactCela ne reste fiable que si chaque machine exécute le même environnement de test.
Un setup Jest pratique ressemble généralement à ceci :
// 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',
},
};
Si votre équipe utilise SWC au lieu de Babel, cela ne pose pas de problème. Le point n'est pas le transformateur. Le point est la cohérence. Choisissez une voie et standardisez-la dans le dépôt. Si vous souhaitez une référence complémentaire pour les conventions de test JavaScript plus larges, le guide des tests unitaires de Capgo est un document de transmission d'équipe utile. Ajoutez le fichier de configuration que votre ensemble de tests dépendra
Un setup approprié
économise beaucoup de bruit répétitif : setupTests.js Ce fichier est là où vous résolvez les écarts d'environnement une fois au lieu de les résoudre à l'intérieur de vingt fichiers de test. Ajoutez des mocks pour les APIs dont votre interface utilisateur a besoin, comme
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(),
})),
});
ou matchMedia, ResizeObserversi votre bibliothèque de composants les attend. IntersectionObserverAdd the setup file your suite will depend on
Sans cela, les développeurs patcheront les globaux ad hoc. Cela crée des tests incohérents et des échecs difficiles à suivre. Une personne local passe parce qu'ils ont ajouté un mock manuel dans un fichier. Le CI échoue parce que la configuration n'a pas été partagée.
Maintenez le comportement local et CI aligné
La commande locale devrait correspondre à la commande CI le plus possible. Si les développeurs exécutent la commande watch avec des paramètres permissifs mais que CI exécute une configuration plus stricte, vous obtiendrez des échecs inattendus après fusion. Gardez les scripts explicites :
{
"scripts": {
"test": "jest",
"test:watch": "jest --watch",
"test:ci": "jest --runInBand --coverage"
}
}
Un court parcours aide les nouveaux membres de l'équipe à obtenir la même base rapidement :
La plus grande décision d'implémentation est la discipline autour des paramètres par défaut. Mettez les alias dans la configuration. Mettez les mocks d'environnement dans un fichier de configuration unique. Utilisez jsdom pour les tests UI et un environnement plus léger pour les utilitaires purs lorsque possible. Moins de comportement personnalisé que chaque test individuel nécessite, plus votre système devient fiable.
Écrire des tests de composants significatifs
Les organisations n'ont pas de problème pour écrire des tests. Elles ont un problème pour écrire des tests qui ont encore de l'importance six mois plus tard.
Le modèle standard pour les tests unitaires des composants React est toujours le bon : afficher le composant, interroger l'interface utilisateur avec des sélecteurs centrés sur l'utilisateur, déclencher une interaction et affirmer le changement de DOM résultantqui maintient les tests à l'écart des détails d'implémentation comme l'état ou les propriétés, comme décrit dans le guide de test ReactLa clé est d'appliquer ce modèl’avec modération.
Testez l'accordéon comme un utilisateur l'utilise.
Prenez un composant de base. Accordion Ce composant affiche un bouton avec un titre. Le contenu du panneau commence caché. Lorsque vous cliquez sur le bouton, le contenu est révélé et l'état d'accèsibilité est mis à jour.
Cela suffit pour plusieurs tests utiles :
- La première mise en page affiche le titre mais pas le contenu.
- Le clic sur le déclencheur révèle le contenu.
- Le clic à nouveau le fait reculer.
- Les attributs d'accèsibilité reflètent l'état visible.
Cette dernière point est souvent négligé. Si votre composant utilise des rôles ou une structure basée sur des rôles, vérifiez-les. Ce ne sont pas des détails d'implémentation. C'est partie de la convention utilisateur. aria-expanded, aria-controlsLes meilleures tests de composants lisent comme un rapport de bug que vous n'avez jamais voulu recevoir.
Le dernier point est souvent négligé. Si votre composant utilise des rôles ou une structure basée sur des rôles, vérifiez-les. Ce ne sont pas des détails d'implémentation. C'est partie de la convention utilisateur.
Choisissez les requêtes en fonction de votre intention
La bibliothèque de test React vous offre plusieurs styles de requêtes, mais ils ne sont pas interchangeables. Le choix du mauvais style rend les tests bruyants ou trompeurs.
| Type de requête | Lorsque l'élément est trouvé | Lorsque l'élément n'est pas trouvé | Exemple d'utilisation |
|---|---|---|---|
getBy |
Renvoie l'élément immédiatement | Lance une erreur immédiatement | Assurez-vous que le bouton ou l'en-tête doit déjà être affiché sur l'écran |
queryBy |
Renvoie l'élément immédiatement | Renvoie null |
Assurez-vous que le contenu caché n'existe pas avant l'interaction |
findBy |
Résout lorsque l'élément apparaît | Rejette après avoir attendu | Assurez-vous que le contenu chargé en parallèl’apparaisse après une requête ou une mise à jour retardée |
Un modèle mental simple vous aidera :
- Utilisez
getBypour les choses qui doivent déjà exister. - Utilisez
queryBypour les choses qui ne doivent pas exister encore. - Utilisez
findBylorsque les modifications de l'interface utilisateur ont lieu plus tard.
Si un test commence par findBy pour tout, cela signifie généralement que l'auteur n'est pas sûr de quand le composant se met à jour. Cette incertitude devient ensuite de la flambabilité.
Avec un exemple d'accordéon pratique
Ici, un composant représentatif :
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>
);
}
Et voici la forme de tests à conserver :
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');
});
Ce qui manque est tout aussi important. Il n'y a pas d'affirmation contre l'état interne. Pas de vérification de l'appel. Pas d'empreinte de l'arbre rendu entier. Ces tests ajouteraient de la maintenance, pas de confiance. setOpen Un certain nombre de habitudes rendent les tests de composants plus solides :
Préférez les requêtes basées sur le rôle :
- Les boutons, les titres, les dialogues, les avertissements et les champs de saisie devraient généralement être trouvés par leur rôle. Conservez chaque test étroit :
- Un comportement visible par l'utilisateur par test garde les échecs lisibles. Nommez les tests après les résultats :
- « Met à jour aria-expanded lors de l'ouverture » est beaucoup plus utile que « fonctionne correctement ». Avec un exemple d'accordéon pratique
Si un composant est difficile à tester à travers le DOM, cela révèle souvent un problème de conception. Peut-être qu'il cache l'état dans le mauvais endroit. Peut-être qu'il manque de balises de sens. Les bonnes tests poussent souvent les équipes vers de meilleurs composants.
Testez les Hooks personnalisés et la logique d'application
Les applications React cachent beaucoup de comportements importants en dehors des composants. Les transitions d'état vivent dans les hooks. La validation et la mise en forme vivent dans les fonctions d'aide. La mise en forme des données se produit souvent avant que quoi que ce soit ne s'affiche. Si vous n'avez que des composants visibles, vous manquerez une grande partie de la code qui peut encore casser le comportement de production.
Les hooks ont besoin d'un harnais React-aware
Un hook personnalisé a toujours besoin de React pour s'exécuter correctement, testez-le donc avec renderHook et enveloppez les appels modifiant l'état dans act().
Un petit useToggle hook est un bon exemple:
import { useState, useCallback } from 'react';
export function useToggle(initialValue = false) {
const [value, setValue] = useState(initialValue);
const toggle = useCallback(() => setValue(current => !current), []);
return { value, toggle };
}
Son test doit rester axé sur le contrat public:
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);
});
Ce test est utile car le hook lui-même est l'unité. Vous n'êtes pas en train de tester les internes de React. Vous vérifiez le comportement externe du hook.
Pour les équipes de produits créant des UI ou des primitives de fonctionnalités réutilisables, ce modèle compte beaucoup. Les hooks deviennent souvent l'interface partagée entre les applications, les systèmes de conception ou les outils internes. Si vous concevez du comportement réutilisable avec une intention commerciale, consultez les ressources sur les hooks pour les produits des créateurs peut aider à présenter les hooks comme des blocs de construction standardisés plutôt que comme des détails d'implémentation.
La logique pure doit rester pure dans les tests.
Ce n'est pas nécessaire pour tout. jsdom, React, ou Testing Library. Si une fonction est pure, testez-l’avec Jest pur dans un environnement Node.
Exemple :
export function formatDisplayName(firstName: string, lastName: string) {
return `${firstName.trim()} ${lastName.trim()}`.trim();
}
Ce test devrait être très simple :
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');
});
La victoire ici est la vitesse et la clarté. Lorsqu'une fonction n'a pas besoin d'un arbre de rendu, ne lui en donne pas. Les outils spécifiques à React ajoutent un surcoût. Conservez les tests de logique métier petits, rapides et proches de la fonction qu'ils vérifient.
Un split pratique fonctionne bien :
- Les hooks : Utilisez
renderHook,act(), et les fournisseurs de wrapper lorsque cela est nécessaire. - Les utilitaires : Utilisez Jest simple et sans DOM.
- Logique transversale étatique : Extraigez-le dans des aides testables lorsque le test de composant commence à faire trop de choses.
Les équipes ont souvent surchargé les tests de composant de logique d'assertion qui appartiennent plus bas dans la pile. En extraignant cette logique, vous obtenez deux avantages. Le test de composant devient plus propre, et le test de logique devient plus rapide.
Maitriser les techniques avancées : Mocking et Async
La plupart des suites de tests React les plus instables se cassent en deux endroits. Ils se cassent aux limites de dépendance, et ils se cassent autour du temps.
C'est pourquoi le test asynchrone et le mocking sont la ligne de démarcation entre une suite de tests de jouet et une que vous pouvez vous fier avant la mise en production. Une analyse attribue 46,5 % de la flottabilité des tests aux problèmes liés à l'environnement ou aux ressources, comme le timing asynchrone en cerapport d'analyse de test React

Simulez les limites, pas chaque couche
La façon la plus rapide de rédiger un test trompeur est de simuler la moitié de votre arbre de composants et d'affirmer ensuite que vos propres simulations ont fonctionné.
Pour un composant qui récupère des données de compte, simulez le client de réseau ou le module API. N'ayez pas peur de simuler le hook, le composant enfant, le chargeur de chargement et trois fonctions d'utilité, à moins que le test nécessite vraiment une isolation à ces points de jonction.
Utilisez ce jeu de règles :
- Simulez les services externes : Les clients HTTP, les analyses, les API du navigateur uniquement, les ponts natifs
- Simulez les API de plateforme instables :
matchMediaLes temporisateurs, les interfaces de préchargement Electron, les plugins Capacitor lorsqu'ils ne sont pas disponibles dans jsdom - Évitez de simuler vos propres internes par défaut : Les hooks personnalisés, les enfants simples, les utilitaires locaux
Si un test passe parce que toutes les parties difficiles ont été remplacées par des faux, il n'a pas beaucoup acheté de confiance dans la mise en production.
Pour les équipes qui souhaitent des exemples et des modèles autour des API de l'exécuteur, Capgo tutoriels de test s'agit d'une bibliothèque de référence pratique, en particulier lors de l'inscription des développeurs qui connaissent React mais pas encore les mécanismes de test.
Les tests asynchrones échouent lorsqu'il y a un manque de précision dans le timing
Les échecs asynchrones proviennent généralement de l'une des trois erreurs suivantes :
- Le test affirme trop tôt.
- Le test attend avec des temporisations arbitraires.
- Le composant se met à jour plus d'une fois, mais le test ne modélise qu'une seule transition.
Un test asynchrone stable a généralement cette forme :
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();
});
Ou, lorsque vous avez besoin d'attendre une condition spécifique :
await waitFor(() => {
expect(screen.getByRole('alert')).toBeInTheDocument();
});
Utilisez findBy lorsque l'apparition d'un élément est l'événement que vous souhaitez. waitFor Utilisez setTimeout à moins que vous ne testiez explicitement le comportement du chronomètre et que vous utilisiez des timers faux.
l'écosystème de test de React attend également que vous respectiez act() les sémiotiques autour des mises à jour. La bibliothèque de test gère une grande partie de cela pour vous, mais si vous avancez manuellement l'état ou les timers, vous devez encore réfléchir à quand les mises à jour se mettent à jour.
Savoir quelle outil de simulation utiliser
Different mocking tools solve different problems:
| Outil | Meilleur usage | Erreur commune |
|---|---|---|
jest.fn() |
Appels de callback faux ou fonctions injectées | Utiliser pour remplacer un module entier lorsqu'un simple appel de callback est suffisant |
jest.spyOn() |
Observer ou surcharger une méthode sur un objet ou module réel | Oublier de restaurer l'implémentation d'origine |
jest.mock() |
Remplacez une dépendance de module à la limite de l'importation | Simuler des modules importants par défaut et perdre un comportement significatif |
Exemples d'aide :
- Recherchez
jest.fn()lorsqu'un composant prend unonSubmitprop. - Utilisez
jest.spyOn()lorsque vous avez besoin de vérifierconsole.error, un méthode de stockage ou une appelle exportée API. - Utilisez
jest.mock()lorsque l'importation d'un module aurait autrement un impact sur l'I/O, le code natif ou le comportement en dehors de la limite de l'unité.
Un domaine avancé que de nombreux guides négligent est la testabilité des chemins d'erreur dans le React moderne. Les limites d'erreur, les changements de l'état retardés et les UI de fallback asynchrones méritent des tests de premier ordre, pas seulement l'exemple de clic « heureux ». Si un enfant lance une erreur, assurez-vous que l’UI de fallback est visible. Si une requête échoue, assurez-vous que l'état de récupération visible est correct. Si un bouton est désactivé pendant le chargement, assurez-vous que c'est le cas également. Ce sont les bugs que les utilisateurs se rappellent.
Améliorer la qualité et la stratégie de test
Beaucoup d'équipes poursuivent toujours la couverture comme si c'était la même chose que la confiance. Ce n'est pas le cas.
Vous pouvez atteindre un objectif de couverture et manquer encore les régressions qui comptent. Un ensemble complet d'assertions superficielles, de captures d'écran larges et d'internes mockés créent l'apparence de la sécurité tout en augmentant le coût de maintenance.

La couverture est une carte, pas le but
Les rapports de couverture sont utiles lorsqu'ils répondent à une seule question : quels chemins critiques n'ont pas encore de protection ?
Ils ne sont pas utiles lorsqu'ils poussent les développeurs à tester des enveloppes triviales, du markup statique ou des fichiers de passage d'une ligne juste pour déplacer un pourcentage. Traitez la couverture comme un outil de découverte. Si l'état d'authentification, les actions de facturation, les drapeaux de fonctionnalité ou les invitations à mettre à jour n'ont pas de tests, c'est un signal. Si un composant d'icône présentationnel n'a pas de tests, ce n'est généralement pas le cas.
Une question de revue saine est simple : cette test réduit-t-il le risque de lancement ?
- Oui: Elle vérifie le comportement visible de l'utilisateur sur un chemin critique.
- Peut-être: Elle protège la logique métier qui est facile à briser lors d'une refacturation.
- No : Cela affirme des détails d'implémentation ou duplique la valeur d'un autre test.
Ce qu'il ne faut pas tester unitairement
Beaucoup de guides React ne consacrent pas encore suffisamment de temps à l'omission. Cette lacune compte car la sur-mockage et le test des détails d'implémentation créent des ensembles fragiles qui passent alors que l'expérience utilisateur continue de se rompre, comme le note le guide de BrowserStack sur ce qu'il ne faut pas tester unitairement dans React.
Omettez ou limitez fortement ces modèles :
- Les affirmations d'état interne : N'ayez pas
isOpentesté directement lorsque vous pouvez tester si le panneau s'est ouvert. - Le comportement du framework : N'ayez pas testé que React a appelé un effet. Testez le résultat de ce que l'effet change.
- Les internes de bibliothèques tierces : Testez votre intégration avec un sélecteur de date ou un navigateur, et non la logique de rendu de la bibliothèque elle-même.
- Les unités surchargées : Si vous avez simulé chaque enfant et chaque assistant, vous ne testez peut-être plus un comportement significatif.
Les mauvaises tests sont pires que les tests manquants lorsqu'ils bloquent les réfacteurs et ne parviennent pas à détecter les bogues de production.
Un bon heuristique est la propriété des limites. Testez ce que votre code possède. N'essayez pas de tester ce que React, le navigateur ou une bibliothèque mature possèdent, à moins que votre couche d'intégration change le contrat.
Où les captures d'écran sont utiles et où elles nuisent
Les captures d'écran ne sont pas inutiles. Elles sont juste faciles à mal utiliser.
Utilisez-les avec parcimonie pour les composants avec une sortie stable et simple où une différence structurale large est significative. Évitez-les pour les composants interactifs ou dynamiques car ils deviennent du bruit. Les développeurs cessent de les lire et commencent à les mettre à jour de manière réflexe.
Des alternatives meilleures existent généralement :
- Pour la rendu conditionnel, assurez-vous de la présence ou de l'absence de texte clé.
- Pour les changements d'état visuels, assurez-vous du rôle, de l'étiquette ou de l'attribut qui compte.
- Pour les erreurs et les fallbacks, assurez-vous du message réel ou de la région d'alerte.
Si votre équipe a besoin d'un processus qualité plus large au-delà des tests unitaires, un partenaire solide est un flux de garantie de qualité d'application qui traite les tests, les contrôles de mise en production et la planification de retrait comme un système unique. C'est le changement de mentalité qui améliore la qualité des tests le plus rapidement. Arrêtez de demander combien de tests vous avez. Commencez à demander quelles erreurs pourraient encore atteindre les utilisateurs.
Intégration des tests dans une chaîne de production CI/CD cross-plateforme
Un ensemble de tests qui ne s'exécute que sur un ordinateur de développeur est une suggestion, et non un contrôle.
L'ensemble devient opérationnel lorsque chaque demande de tirage exécute les mêmes contrôles dans un environnement propre et bloque les mises à jour lorsque ces contrôles échouent. Cela semble évident, mais beaucoup d'équipes laissent encore des lacunes critiques. Les tests sont exécutés manuellement. Les rapports de couverture sont optionnels. Les tâches de packaging et de mise en production commencent avant que les tâches de test n'aient terminé. C'est ainsi que les petites régressions d'interface peuvent s'introduire dans des échecs de mise en production plus importants.

Une demande de tirage devrait déclencher le même contrôle chaque fois
Pour que les tests unitaires de React fonctionnent comme un filet de sécurité, la CI a besoin de quelques éléments essentiels:
- Exécuter sur chaque demande de tirage
- Installer les dépendances à partir du fichier de verrouillage
- Utiliser la même commande de test chaque fois
- Échouez rapidement en cas de failures de test
- Publiez les artefacts uniquement après que les tests passent
C'est le cœur des pratiques de déploiement continu pour les équipes d'applications. Construisez la confiance avant la mise en production, et non après.
A simple GitHub Actions workflow is enough for many teams:
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
Cela n'est pas élégant, et c'est justement le point. Les pipelines les plus solides sont souvent les moins surprenants.
Why this matters more for Capacitor and Electron
Cross-platform React apps carry more release risk than browser-only apps because the same UI code often ships in different containers with different runtime assumptions.
Quelques exemples montrent où les pipelines sont utiles :
- Capacitor apps: Web code may pass locally but fail when a plugin bridge, offline state, or app lifecycle edge case changes behavior after packaging.
- Applications Electron : Un composant de rendu peut dépendre d'APIs de préchargement, de messages de fenêtre ou d'état de bureau uniquement qui n'existeront pas dans des tests de navigateur classiques à moins d'être simulés intentionnellement.
- Trains de publication partagés : Une mauvaise mise en bundle peut avoir un impact sur plusieurs cibles si votre processus de déploiement ne bloque pas étroitement la publication.
C'est pourquoi les tests unitaires doivent s'exécuter avant les tâches de packaging, et les tâches de packaging doivent s'exécuter avant les tâches de distribution. Chaque étape réduit le risque. Les tests unitaires détectent rapidement les régressions locales. La vérification de l'environnement par le packaging de plateforme vérifie les hypothèses de l'environnement. L'approbation manuelle ou le lancement étalé gère la confiance finale de la mise en production.
Un workflow d'Actions pratique GitHub
Un pipeline plus mature divise généralement les responsabilités :
- Tâche de test : Tests unitaires rapides et tests de hooks
- Tâche de build : Build de production uniquement après que les tests passent
- Tâche de package : Capacitor synchronisation, packaging Electron ou regroupement d'artefacts
- Job de mise en production : Publiez uniquement à partir de branches ou de tags approuvés
Pour les équipes qui livrent des mises à jour en direct à Capacitor ou Electron, c'est là que les outils de mise en production comptent. Une option dans ce flux de travail est Capgoqui publie des bundles web signés pour les applications CapacitorJS et Electron avec prise en charge de la mise à niveau et de la mise en production basée sur les canaux. En pratique, cela signifie que votre job de test React peut agir comme la première barrière dure avant que tout bundle web ne soit promu vers la livraison de production ou de staging.
La règle opérationnelle est simple. N'obligez pas l'infrastructure de mise en production à compenser les tests faibles. Utilisez l'infrastructure de mise en production après que les tests fiables aient déjà éliminé les changements mauvais.
Un système de test fiable change le comportement de l'équipe. Les ingénieurs fusionnent avec moins de hésitation. Les réviseurs se concentrent sur les cas d'extrémité au lieu de re-réexécuter les bases manuellement. Les gestionnaires de mise en production cessent de traiter chaque déploiement comme un jeu d'hasard. C'est le résultat d'une mise en œuvre réussie de la mise en test unitaire de React.
Si votre équipe livre React à travers Capacitor ou Electron, la sécurité de la mise en production dépend de plus que des tests locaux verts. Capgo offre aux équipes une façon contrôlée de publier des mises à jour web signées, de cibler les canaux de mise en production et de revenir sur des bundles mauvais sans attendre la revue de la boutique, ce qui convient naturellement derrière un pipeline CI qui exige déjà que les tests unitaires passent avant la mise en production.