Je souhaite obtenir des informations sur une formation complète concernant le thème DIVI dispensé
par un organisme de formation certifié par l’état.
Que la formation soit finançable par mon CPF (idéalement) ou autre


Une nouvelle version du système de conception de Toptal a été récemment publiée, ce qui nécessitait des modifications à apporter à presque tous les composants de Picasso, notre bibliothèque de composants interne. Notre équipe a été confrontée à un défi: comment s’assurer qu’aucune régression ne se produit?

La réponse courte, sans surprise, est le test. Beaucoup de tests.

Nous n’allons pas passer en revue les aspects théoriques des tests, ni discuter des différents types de tests, de leur utilité, ni expliquer pourquoi vous devriez tester votre code en premier lieu. Notre blog et d’autres ont déjà couvert ces sujets. Au lieu de cela, nous nous concentrons uniquement sur les aspects pratiques des tests.

Lisez la suite pour découvrir comment les développeurs de Toptal écrivent des tests. Notre référentiel est public, nous utilisons donc des exemples du monde réel. Il n’y a pas d’abstractions ou de simplifications.

Pyramide de test

Nous n’avons pas défini de pyramide de test en soi, mais si nous le faisions, cela ressemblerait à ceci:

Illustration de la pyramide de test

La pyramide de tests de Toptal illustre les tests que nous mettons en évidence.

Tests unitaires

Les tests unitaires sont faciles à écrire et à exécuter. Si vous avez très peu de temps pour écrire des tests, ceux-ci devraient être votre premier choix.

Cependant, ils ne sont pas parfaits. Quelle que soit la bibliothèque de tests que vous choisissez (Jest and React Testing Library [RTL] Dans notre cas) il n’a pas de vrai DOM et il ne vous permet pas de vérifier les fonctionnalités dans différents navigateurs, mais cela vous permet de réduire la complexité et de tester les blocs de construction simples de votre bibliothèque.

Les tests unitaires apportent non seulement une valeur ajoutée en ce qu’ils testent le comportement du code, mais également la testabilité générale du code. Si vous ne pouvez pas simplement écrire des tests unitaires, vous avez probablement du mauvais code.

Tests de régression visuelle

Même si vous avez une couverture de test unitaire à 100%, cela ne signifie pas que les composants auront une belle apparence sur les appareils et les navigateurs.

Les régressions visuelles sont particulièrement difficiles à voir lors de l’exécution de tests manuels. Par exemple, si l’étiquette d’un bouton est décalée de 1 pixel, un technicien QA le remarquera-t-il même? Heureusement, il existe de nombreuses solutions à ce problème de visibilité limitée. Vous pouvez opter pour des solutions tout-en-un pour les entreprises, telles que: LambdaTest ou alors Mabl. Vous pouvez intégrer des plugins comme Percy, dans vos tests existants ainsi que dans des solutions DIY similaires Loki ou alors Livre d’histoires (que nous avons utilisé avant Picasso). Ils ont tous des inconvénients: certains sont trop chers tandis que d’autres ont une courbe d’apprentissage abrupte ou nécessitent trop de maintenance.

acide à la rescousse! C’est un concurrent direct de Percy, mais c’est beaucoup moins cher, prend en charge plus de navigateurs et est plus facile à utiliser. Un autre gros argument de vente? Il prend en charge l’intégration Cypress, ce qui était important car nous ne voulions plus utiliser Storybook pour les tests visuels. Nous nous sommes retrouvés dans des situations où nous devions créer des histoires pour assurer une couverture de test visuel, pas parce que nous devions documenter ce cas d’utilisation. Cela a pollué nos documents et les a rendus plus difficiles à comprendre. Nous voulions isoler les tests visuels de la documentation visuelle.

Tests d’intégration

Même si deux composants ont des tests unitaires et des tests visuels, ce n’est pas une garantie qu’ils fonctionneront ensemble. Par exemple, nous avons trouvé un bogue où une info-bulle ne s’ouvre pas lorsqu’elle est utilisée dans un élément de liste déroulante, mais fonctionne bien lorsqu’elle est utilisée seule.

Pour nous assurer que les composants s’intègrent bien, nous avons utilisé l’expérience Cypress Fonction de test des composants. Au début, nous n’étions pas satisfaits de cela mauvaise performance, mais nous avons pu l’améliorer une configuration webpack personnalisée. Le résultat? Nous avons pu utiliser l’excellente API de Cypress pour écrire des tests haute performance qui garantissent que nos composants fonctionnent bien ensemble.

Application de la pyramide de test

À quoi cela ressemble-t-il dans la vraie vie? Testons ça accordéon Composant!

Votre premier instinct pourrait être d’ouvrir votre éditeur et de commencer à écrire du code. Mon conseil? Passez du temps à comprendre toutes les fonctionnalités du composant et à noter les cas de test que vous souhaitez couvrir.

GIF de démonstration de la bibliothèque de composants Picasso

Que tester

Voici un aperçu des cas que nos tests devraient couvrir:

  • conditions – Les accordéons peuvent être développés et réduits, leur état par défaut peut être configuré et cette fonctionnalité peut être désactivée
  • modes – Les accordéons peuvent avoir des variations de bord
  • contenu – Ils peuvent être intégrés dans d’autres unités de la bibliothèque
  • Adaptation – Les styles du composant peuvent être remplacés et des symboles d’extension personnalisés peuvent être utilisés
  • Rappels – Un rappel peut être appelé à chaque fois que le statut change

GIF de démonstration de la bibliothèque de composants Picasso - Composant accordéon

Comment tester?

Maintenant que nous savons quoi tester, voyons comment procéder. Nous avons trois options de notre pyramide de test. Nous voulons atteindre une couverture maximale avec un chevauchement minimal entre les sections de la pyramide. Quelle est la meilleure façon de tester chaque cas de test?

  • conditions – Les tests unitaires peuvent nous aider à déterminer si les états changent en conséquence. Cependant, nous avons également besoin de tests visuels pour nous assurer que le composant est correctement rendu dans chaque état
  • modes – Les tests visuels doivent être suffisants pour détecter les régressions des différentes variantes
  • contenu – Une combinaison de tests visuels et de tests d’intégration est le meilleur choix car les accordéons peuvent être utilisés en combinaison avec de nombreux autres composants
  • Adaptation – Nous pouvons utiliser un test unitaire pour vérifier qu’un nom de classe a été correctement appliqué. Cependant, nous avons besoin d’un test visuel pour nous assurer que le composant et les styles personnalisés fonctionnent ensemble
  • Rappels – Les tests unitaires sont parfaits pour s’assurer que les bons rappels sont appelés

La pyramide de test d’accordéon

Tests unitaires

La suite complète des tests unitaires peut être trouvée ici Ici. Nous avons couvert tous les changements d’état qui Ajustement et rappels::

  it('toggles', async () => {
    const handleChange = jest.fn()

    const { getByText, getByTestId } = renderAccordion({
      onChange: handleChange,
      expandIcon: <span data-testid='trigger' />
    })

    fireEvent.click(getByTestId('accordion-summary'))
    await waitFor(() => expect(getByText(DETAILS_TEXT)).toBeVisible())

    fireEvent.click(getByTestId('trigger'))
    await waitFor(() => expect(getByText(DETAILS_TEXT)).not.toBeVisible())

    fireEvent.click(getByText(SUMMARY_TEXT))
    await waitFor(() => expect(getByText(DETAILS_TEXT)).toBeVisible())

    expect(handleChange).toHaveBeenCalledTimes(3)
  })

Tests de régression visuelle

Les tests visuels sont en Ce bloc de description Cypress. Les captures d’écran se trouvent dans Tableau de bord Happos.

Vous pouvez voir que tous les différents états, variantes et ajustements des composants ont été enregistrés. Chaque fois qu’un PR est ouvert CI compare les captures d’écran que Happo a sauvegardé les fichiers enregistrés dans votre agence:

  it('renders', () => {
    mount(
      <TestingPicasso>
        <TestAccordion />
      </TestingPicasso>
    )
    cy.get('body').happoScreenshot()
  })
  it('renders disabled', () => {
    mount(
      <TestingPicasso>
        <TestAccordion disabled />
        <TestAccordion expandIcon={<Check16 />} />
      </TestingPicasso>
    )
    cy.get('body').happoScreenshot()
  })
  it('renders border variants', () => {
    mount(
      <TestingPicasso>
        <TestAccordion borders="none" />
        <TestAccordion borders="middle" />
        <TestAccordion borders="all" />
      </TestingPicasso>
    )
    cy.get('body').happoScreenshot()
  })

Tests d’intégration

Nous avons écrit un test « Bad Path » en Ce bloc de description Cypress Cela confirme que l’accordéon fonctionne toujours correctement et que les utilisateurs peuvent interagir avec le composant personnalisé. Nous avons aussi ajout d’assertions visuelles pour une confiance supplémentaire:

describe('Accordion with custom summary', () => {
  it('closes and opens', () => {
    mount(<AccordionCustomSummary />)
    toggleAccordion()
    getAccordionContent().should('not.be.visible')

    cy.get('[data-testid=accordion-custom-summary]').happoScreenshot()

    toggleAccordion()
    getAccordionContent().should('be.visible')

    cy.get('[data-testid=accordion-custom-summary]').happoScreenshot()
  })
  // …
})

Intégration continue

Picasso s’appuie presque exclusivement sur Promotions GitHub pour l’assurance qualité. De plus, nous avons ajouté Crochets Git pour vérifier la qualité du code des fichiers fournis. Nous avons récemment migré de Jenkins vers GHA, donc notre configuration est toujours en phase MVP.

Le flux de travail s’exécute de manière séquentielle avec chaque changement dans la branche distante, l’intégration et les tests visuels étant la dernière étape car il est le plus coûteux à exécuter (à la fois en termes de performances et de coût monétaire). Si tous les tests échouent, la demande d’extraction ne peut pas être fusionnée.

Voici les étapes par lesquelles les actions GitHub passent à chaque fois:

  1. Installation de dépendance
  2. Contrôle de version – Vérifie que le format des commits et le titre PR correspondent conventionnel s’engage
  3. peluche – ESlint garantit un code de bonne qualité
  4. Compilation TypeScript – Assurez-vous qu’il n’y a pas de fautes de frappe
  5. Composition de l’emballage – Si les packages ne peuvent pas être créés, ils ne seront pas publiés avec succès. Nos tests Cypress attendent également du code compilé
  6. Tests unitaires
  7. Intégration et tests visuels

Vous pouvez trouver le flux de travail complet Ici. Actuellement, il faut moins de 12 minutes pour terminer toutes les phases.

Testabilité

Comme la plupart des bibliothèques de composants, Picasso possède un composant racine qui doit englober tous les autres composants et peut être utilisé pour définir des règles globales. Cela rend plus difficile l’écriture de tests pour deux raisons: des incohérences dans les résultats des tests, selon les accessoires utilisés dans le wrapper; et passe-partout supplémentaire:

import { render } from '@testing-library/react'

describe('Form', () => {
  it('renders', () => {
    const { container } = render(
      <Picasso loadFavicon={false} environment="test">
        <Form />
      </Picasso>
    )

    expect(container).toMatchSnapshot()
  })
})

Nous avons résolu le premier problème en ajoutant un Tester Picasso cela suppose les règles globales de test. Mais c’est ennuyeux de devoir le déclarer pour chaque cas de test. C’est pourquoi nous en avons fait un fonction de rendu personnalisée Cela inclut le composant passé dans un TestingPicasso et renvoie tout ce qui est disponible via la fonction de rendu de RTL.

Nos tests sont désormais plus faciles à lire et à écrire:

import { render } from '@toptal/picasso/test-utils'

describe('Form', () => {
  it('renders', () => {
    const { container } = render(<Form />)

    expect(container).toMatchSnapshot()
  })
})

Conclusion

La configuration décrite ici est loin d’être parfaite, mais c’est un bon point de départ pour ceux d’entre vous assez aventureux pour construire une bibliothèque de composants. J’ai beaucoup lu sur les tests pyramidaux, mais ce n’est pas toujours facile à mettre en pratique. Alors je vous invite à explorer notre base de code et apprenez de nos erreurs et de nos succès.

Les bibliothèques de composants sont uniques en ce sens qu’elles desservent deux types d’audience: les utilisateurs finaux qui interagissent avec l’interface utilisateur et les développeurs qui utilisent votre code pour créer leurs propres applications. Lorsque vous investissez du temps dans un cadre de test robuste, tout le monde en profite. Lorsque vous investissez du temps dans l’amélioration de la testabilité, vous bénéficiez en tant que mainteneurs et ingénieurs qui utilisent (et testent) votre bibliothèque.

Nous n’avons pas parlé de choses comme la couverture du code, les tests de bout en bout et les politiques de version et de publication. Le conseil rapide sur ces sujets est le suivant: publiez fréquemment, pratiquez une gestion sémantique correcte des versions, ayez de la transparence dans vos processus et ayez les attentes des ingénieurs qui s’appuient sur votre bibliothèque. Nous pouvons examiner de plus près ces sujets dans les articles suivants.



Source link

Recent Posts