End-to-end testen versus integratietesten: waar hoort elke test thuis

End-to-end-testen verifiëren of een echte gebruiker een echte workflow kan voltooien via de daadwerkelijke interface, met verbonden services. Integratietesten verifiëren of twee of meer componenten correct communiceren via hun interfaces. Beide maken deel uit van een gezonde functionele teststrategie, waarbij elke methode een categorie bugs opvangt die de andere mist.

Het pijnpunt ligt in de ruimte tussen die twee definities. Een testcase belandt op het whiteboard, CI duurt al 40 minuten en de helft van het team wil het als integratietest omdat het goedkoop is, terwijl de andere helft het als E2E-test wil omdat het “de UI aanraakt”. Elk artikel over end-to-end-testen versus integratietesten eindigt met dezelfde schouderophaling: gebruik beide, volg de 70/20/10-piramide, succes ermee. Dat advies zegt niets over de test waar u op dat moment naar kijkt.

Dit artikel wel. Vier vragen, vijf seconden per testcase, voorbeelden uit de checkout. De keuze wordt gepresenteerd als een beslissing gebaseerd op de kosten van feedback, want dat is het in feite.

Waarom de 70/20/10-regel u vast laat lopen

De piramide is een distributiedoel. Het stelt ruwweg 70% unit-tests, 20% integratietests en 10% E2E-tests voor, en daar stopt het. De distributie is het resultaat van goede beslissingen per test, niet iets wat u bereikt door tests tussen lagen te schuiven tot de verhouding er goed uitziet. Dat is waarom de discussie over E2E- versus integratietesten in de meeste teams nooit wordt opgelost: iedereen discussieert over de verhouding, maar niemand is het eens over de regel.

Er ontstaan twee faalmodi wanneer teams de piramide als advies beschouwen. De eerste is E2E-opzwelling. Alles wat de UI aanraakt wordt naar boven verplaatst; de suite zwelt aan tot 45 minuten; ontwikkelaars stoppen met het lokaal draaien ervan; en CI wordt een formaliteit. De tweede is overmatig mocken bij integratietests. Alles onder de browser wordt gemockt om tests snel te houden, de suite blijft groen, en de productie breekt door een wijziging in de Stripe webhook-payload waartegen geen enkele test ooit is uitgevoerd.

Het filter met vier vragen voor testplaatsing

Voer elke nieuwe testcase in deze volgorde langs deze vier vragen. Elke vraag isoleert een enkele beslissing. Als de antwoorden wijzen naar een echte browser, echte services en een omzetpad, dan verdient de test een E2E-plek. Zo niet, dan hoort hij bij de integratielaag en is uw CI-budget u dankbaar.

End-to-end testen versus integratietesten: waar hoort elke test thuis

Vraag 1: Op welke laag vindt de assertie plaats?

De assertie vertelt u waar de test hoort. Neem een kortingscodetest: “het toepassen van een code van 15% korting verlaagt het totaalbedrag in de winkelwagen.”

Als de assertie expect(response.discount).toBe(15) is, dan is dit een integratietest. U controleert of de prijs-service het juiste getal teruggeeft. De browser is irrelevant. Dit is de laag waar ons API-testwerk zich bevindt, en het is de plek waar de meeste verificatie van bedrijfslogica zou moeten plaatsvinden.

Als de assertie expect(page.getByTestId(‘cart-total’)).toHaveText(‘$85.00’) is, dan is dit een E2E-test. U controleert of het getal de DOM bereikte, in het juiste element werd gerenderd en overeenkomt met wat een gebruiker zou zien.

Dezelfde bedrijfslogica. Twee verschillende tests. Twee verschillende huizen. De regel: de laag van de assertie bepaalt de laag van de test. Integratietests die asserties doen op gerenderde tekst zijn frauduleuze integratietests. Ze hebben ofwel een echte browser nodig (in dat geval zijn ze E2E) of een andere assertie (in dat geval zijn ze correcte integratietests).

Vraag 2: Is de derde partij het onderwerp of slechts de ondersteunende techniek?

Elke checkout-flow is afhankelijk van externe services. Stripe, Twilio, Auth0, SendGrid. De vraag is of de derde partij hetgeen is wat u test, of slechts iets wat de test toevallig aanraakt.

Neem een test voor een geweigerde creditcard: “een geweigerde Stripe-kaart toont het scherm om het opnieuw te proberen”.

Als u verifieert of de weigeringscodes van Stripe correct worden gekoppeld aan uw interne foutclassificatie, dan is Stripe het onderwerp. Dit is een integratietest tegen de testmodus van Stripe of een opgenomen fixture. Het gaat erom of card_declined aan uw kant een PaymentFailedError.RetryableDecline wordt.

Als u verifieert of de gebruiker een knop ziet om het opnieuw te proberen, creditcardgegevens opnieuw kan invoeren en een nieuwe poging kan doen, dan is Stripe de ondersteunende techniek. De UI voor de nieuwe poging is het onderwerp. Dit is een E2E-test.

De fout die teams maken, is alles wat een derde partij aanraakt naar E2E duwen omdat “het de echte service nodig heeft”. Dat is niet zo. Het heeft alleen de echte service nodig wanneer de service hetgeen is waarop u de assertie doet. Al het andere kan de techniek mocken en het daadwerkelijke onderwerp op het goedkopere niveau testen.

Vraag 3: Zou een wijziging in het contract deze test breken, zelfs als het gedrag hetzelfde blijft?

Neem een e-mailtest: “De orderbevestigingsmail bevat het order-ID”.

Als een downstream-service orderId hernoemt naar order_id en deze test breekt, terwijl de gebruiker nog steeds de juiste e-mail met het juiste ID ontvangt, dan heeft u een contracttest vermomd als E2E-test. Het foutenlogboek zal zeggen: “verwacht veld orderId, kreeg order_id.” Dat is een integratiefout, en integratie is waar dat naar boven moet komen: snel, goedkoop en direct wijzend naar het gebroken contract.

E2E-tests moeten falen op gedrag, wat betekent dat de gebruiker de verkeerde uitkomst kreeg. Wanneer ze falen op de vorm — wat betekent dat een veld in de payload is hernoemd, maar de gebruikerservaring identiek is — vermenigvuldigen de debugkosten zich met ongeveer 10x, omdat u een JSON-verschil najaagt door een browser-trace, screenshots en netwerklogboeken. Contractfouten horen thuis op de integratielaag en worden geverifieerd met schema-asserties of een contract-testtool.

Vraag 4: Een omzetkritieke flow of een secundaire vertakking?

Niet elke echte gebruikersreis verdient een E2E-test. Neem een instellingentest: “gebruiker werkt meldingsvoorkeuren bij van wekelijks naar dagelijks overzicht”.

Echte workflow. Echte database-schrijfactie. Echte impact op de gebruiker. Het hoort nog steeds bij de integratielaag. Elke E2E-test die u toevoegt, belast elke toekomstige pull request, en die belasting stapelt zich op. Reserveer E2E-slots voor flows waarbij een fout een verlies van omzet betekent: aanmelden, inloggen, checkout, betaling, abonnementsupgrade, accountherstel. Al het andere verdient integratiedekking, tenzij er een specifiek risico is bij het renderen van de UI dat alleen een browser kan opvangen.

Dit is de context die het hele internet mist. Integratietesten versus end-to-end-testen is een beslissing gebaseerd op de kosten van feedback. De economische realiteit bevestigt dit: het rapport van IBM schat de gemiddelde kosten van een datalek in de VS op een recordbedrag van 10,22 miljoen dollar. Hoewel niet elk productie-incident een lek is, geldt dezelfde asymmetrie voor elke fout in het omzetpad. Besteed uw E2E-budget daar waar een fout u een klant kost.

Tests die ten onrechte gepromoveerd zijn naar E2E

Dit is de meest voorkomende vorm van verspilling in een opgeblazen E2E-testsuite. Elke test in deze categorie heeft een specifiek foutpatroon: de test faalt en de oplossing is een wijziging van één regel code die nooit een browser nodig had om geverifieerd te worden.

  • Formuliervalidatietests. “E-mailveld weigert reeksen zonder @”. Dit hoort thuis in de integratielaag en moet worden getest tegen de validator. Als dit in E2E staat, betaal je de kosten voor het opstarten van een browser om een regex te testen.
  • API-foutafhandelingstests. “Een 500-fout van de betalingsdienst toont ‘probeer het later opnieuw.’” Voer een integratietest uit op de foutafhandelaar. De browser is niet verantwoordelijk voor het in kaart brengen van de fout.
  • Databasepersistentietests. “Een ingediend contactformulier verschijnt in het adminpaneel.” Twee integratietests, één voor het wegschrijven en één voor het inlezen, zijn beter dan één instabiele E2E-test die beide omvat en 30 seconden per uitvoering duurt.
  • Feature-flagtests. “Gebruikers met vlag X zien variant B.” Voer een integratietest uit op de laag voor vlagresolutie. Gebruik alleen E2E als de visuele variant zelf risico’s met zich meebrengt.
  • Rechten- en autorisatietests. “Een niet-beheerder kan niet bij /admin.” Voer een integratietest uit op de auth-middleware. Elke beperkte route die in E2E wordt verpakt, is een test die je over zes maanden zult moeten schrappen.

Een diagnose die u deze week op uw eigen team kunt uitvoeren: bekijk de laatste vijf E2E-fouten. Als deze elk opgelost hadden kunnen worden door naar een netwerkreactie te kijken in plaats van naar een screenshot, dan is uw suite in de verkeerde richting afgedreven. De helft ervan hoort thuis in de integratielaag, en de CI-tijd is het bewijs hiervan.

Tests die werden gedegradeerd naar integratie en productie kapotmaakten

De omgekeerde fout is zeldzamer, duurder en blijft meestal onopgemerkt totdat een klant een melding maakt. Een test wordt voor de snelheid naar de integratielaag verplaatst; mocks vervangen echte diensten; alles blijft groen; productie crasht op precies datgene wat de mocks verborgen hielden.

Multi-stepflows waarbij de status in de browser wordt bijgehouden, zijn het klassieke voorbeeld. Winkelwagenpersistentie over pagina’s heen, stapsgewijze wizards, sessiegebaseerd afrekenen. Wanneer u de sessielaag mockt, mockt u ook de bug weg die naar productie gaat. Omleidingen van derden zijn een ander voorbeeld. OAuth-callbacks, Stripe Checkout, PayPal-overdracht. De retourreis van de omleiding is waar dingen misgaan, en dat bestaat niet in een integratietest. CSS-afhankelijk gedrag hoort ook thuis in E2E: een verzendknop die achter een modaal venster verborgen zit omdat een z-index veranderde bij de release van dinsdag, zal op geen enkel niveau onder een echte browser aan het licht komen. Cross-origin-cookiegedrag, SameSite-wijzigingen en iframe-authenticatie vallen allemaal in dezelfde categorie.

De regel: als de bug alleen zou verschijnen in een echte browser die communiceert met echte diensten, kan de integratielaag deze niet opvangen, hoe uitgebreid de mocks ook zijn. Gedistribueerde systemen versterken dit patroon, en daarom behandelen we dit apart in ons artikel over microservices performance testing.

De duidelijke splitsing

Twee uitgangspunten voor eigenaarschap vatten het hele artikel samen. Integratie is verantwoordelijk voor:

  • Communicatie tussen diensten en de vorm van wat de grens overschrijdt
  • Contractcontroles: veldnamen, types, foutcodes, response-schema’s
  • Bedrijfslogica onder de browser: validatie, foutafhandeling, rechten, feature-flagresolutie, database-reads en -writes
  • Elke test waarbij de derde partij het onderwerp van de bewering is
  • Elke test waarbij een fout zou verschijnen als “verkeerde reactie van de dienst” in plaats van “verkeerd item op het scherm”

E2E is verantwoordelijk voor:

  • Gerenderde output: het juiste item op het scherm, op de juiste plek, op het juiste moment
  • Multi-stepflows met status die in de browser wordt meegevoerd
  • Omleidingen van derden en retourrondes (OAuth-callbacks, Stripe Checkout, PayPal-overdracht)
  • CSS- en DOM-afhankelijk gedrag (modals, z-index, verborgen knoppen, cross-origin-cookies)
  • Bedrijfskritieke trajecten waarbij een fout betekent dat er een klant verloren gaat

Eén regel samenvatting: integratie bewijst dat de onderdelen correct communiceren; E2E bewijst dat de gebruiker het proces doorloopt. Als een test beide probeert te doen, splits hem dan in tweeën.

De plaatsingsregel is een praktisch hulpmiddel. Haal elke test door de vier vragen. Als vraag 1 “gerenderde output” beantwoordt, vraag 2 “onderwerp” beantwoordt en vraag 4 “bedrijfskritiek” beantwoordt, dan verdient de test zijn E2E-plek. Zo niet, kies dan standaard voor integratie. De keuze voor een framework is van ondergeschikt belang en is minder belangrijk dan de meeste teams denken. Of uw team nu Cypress, Playwright of Selenium gebruikt, de discipline is leidend, en onze pagina over automated testing beschrijft hoe we dit operationeel inrichten van begin tot eind.

Waar elke test zijn plek verdient

Het verschil tussen integratie- en E2E-testen is geen taxonomievraagstuk. Het is een beslissing per test die bepalend is voor uw CI-tijd, het aantal incidenten in productie en het vertrouwen van uw team in de suite. Vier vragen, consistent toegepast, vervangen de discussie per test door een regel die het hele team kan hanteren.

Als uw suite is afgedreven, als CI 40 minuten duurt terwijl dat voorheen 8 minuten was, of als productie constant crasht op zaken waarvan uw integratietests zeiden dat ze in orde waren, neem dan contact met ons op, en we auditen waar uw tests werkelijk staan versus waar ze zouden moeten staan.

Veelgestelde vragen

Wat is het verschil tussen integratietesten en end-to-end-testen?

Integratietesten verifiëren of twee of meer componenten correct communiceren via hun interfaces. End-to-end-testen verifiëren of een gebruiker een workflow kan voltooien via de daadwerkelijke interface met verbonden echte diensten. Het praktische verschil ligt in waar de bewering (assertion) wordt getoetst: in een reactie van een dienst of in wat een gebruiker ziet.

Hoe beslis ik of een testgeval bij integratie of E2E hoort?

Vraag uzelf af wat de bewering controleert. Als het een reactie van een dienst, een contract of een datastructuur is, hoort het thuis in de integratielaag; als het een gerenderd element of een meerstaps gebruikersflow is, hoort het bij E2E. Elke test die nog steeds zou slagen met een defecte UI is geen E2E-test.

Wanneer zijn integratietesten voldoende en wanneer heb je E2E nodig?

Integratie is voldoende wanneer de derde partij het onderwerp van de test is, wanneer een fout zou verschijnen als een verkeerde reactie van de dienst, of wanneer de flow buiten het inkomstentraject valt. U heeft E2E nodig wanneer de browser status meedraagt over stappen heen, wanneer er omleidingen van derden betrokken zijn, of wanneer een fout betekent dat er een klant verloren gaat tijdens registratie, afrekenen of betaling.

Waarom is mijn E2E-testsuite te traag?

Tests die in de integratielaag thuishoren, zijn naar boven verschoven: formuliervalidatie, foutafhandeling, rechtencontroles en feature-flagresolutie hebben zelden een echte browser nodig. Evalueer de laatste vijf E2E-fouten van uw project en als deze elk opgelost hadden kunnen worden met een netwerkreactie in plaats van een screenshot, staat het grootste deel van uw suite op de verkeerde plek.

Ontdek hoe QAwerk de integraties voor afrekenen en betalingen stabiliseerde en de regressiedekking voor Kazidomi verbeterde vóór de uitbreiding door Europa.

Voer uw zakelijke e-mailadres in