Ohjelmistokehitys

Mitä on ohjelmistotestaus? Yksikkö- ja E2E-testit

Käymme läpi yksikkö-, integraatio- ja päästä päähän -testien eron, kuinka paljon mitäkin testiä kannattaa kirjoittaa ja mitä testiautomaatio tuo projektille.

Aurora YazılımToimitustiimi 6 min lukuaika
Mitä on ohjelmistotestaus? Yksikkö- ja E2E-testit
Mitä on ohjelmistotestaus?

Ohjelmistotestaus on joukko tarkistuksia, joilla varmistetaan, että ohjelma toimii odotetusti eikä sisällä virheitä. Testit voidaan tehdä käsin tai automaattisesti koodilla. Kolme yleisintä tyyppiä ovat yksikkötesti (unit test), integraatiotesti ja päästä päähän (E2E) -testi; terveessä projektissa ne tasapainotetaan pyramidin muotoon.

Mitä on ohjelmistotestaus ja miksi sitä tarvitaan?

Ohjelmistotestaus on tapa todistaa, että kirjoittamasi koodi todella tekee sen, mitä haluat. Se, että verkkokaupassa alennuskoodi lasketaan oikein, että hotelliohjelmistossa samaan huoneeseen ei voi tehdä kahta varausta tai että lomake hylkää virheellisen datan, varmistetaan testeillä.

Projekteissa ilman testejä jokainen uusi ominaisuus voi rikkoa jotain, mikä aiemmin toimi. Tätä kutsutaan regressioksi. Automaattiset testit vähentävät tätä riskiä; kun muutos tehdään, ne näyttävät minuuteissa, mikä meni rikki.

Kustannuksen ratkaisee se, milloin virhe löytyy. Kehityksen aikana kiinni jäänyt virhe korjataan muutamassa minuutissa; tuotantojärjestelmässä asiakkaan löytämä virhe maksaa rahaa, aikaa ja luottamusta.

Testityypit: yksikkö, integraatio, E2E

Testityypit jaotellaan kattamansa alueen ja ajonopeutensa mukaan. Pienten osien testaaminen on nopeaa ja halpaa; koko järjestelmän testaaminen on hidasta mutta realistista.

TyyppiKattavuusNopeusYlläpitokustannus
YksikkötestiYksittäinen funktio / komponenttiErittäin nopeaMatala
IntegraatiotestiYhdessä toimivat osatKeskitasoKeskitaso
E2E-testiKoko käyttäjäpolkuHidasSuuri

Mitä on yksikkötesti?

Yksikkötesti (unit test) testaa yksittäistä funktiota tai luokkaa eristettynä ulkomaailmasta. Tietokanta, verkko tai tiedostojärjestelmä eivät ole mukana; tarvittaessa ne jäljitellään valeobjekteilla (mock). Se ajetaan millisekunneissa ja osoittaa virheen paikan tarkasti.

Integraatiotesti

Integraatiotesti varmistaa, että useampi osa toimii oikein yhdessä: sovellus ja tietokanta, palvelu ja palvelu, järjestelmä ja ulkoinen API. Artikkelissamme mikä on API käsitellyt rajapinnat testataan eniten tällä tasolla. Maksun, kuljetuksen ja markkinapaikkaintegraation kaltaisissa poluissa nämä testit ovat kriittisiä.

E2E-testi

E2E-testi (päästä päähän -testi) käyttää järjestelmää kuin oikea käyttäjä: avaa selaimen, lisää tuotteen ostoskoriin, siirtyy maksuvaiheeseen ja tarkistaa, että tilaus syntyi. Se on realistisin testi, mutta myös hitain ja hauraimman.

Testipyramidi: kuinka paljon mitäkin testiä?

Testipyramidi on yleinen malli, joka kertoo, kuinka paljon mitäkin testityyppiä pitäisi kirjoittaa. Pohjalla on paljon nopeita yksikkötestejä, keskellä vähemmän integraatiotestejä ja huipulla vain pieni määrä E2E-testejä, jotka kattavat kriittiset polut.

Pyramidin kääntyminen ylösalaisin, eli kaiken yrittäminen varmistaa E2E-testeillä, on yleinen virhe. Silloin testiaika pitenee, testit hajoavat syyttä ja tiimi alkaa ajan myötä olla luottamatta testeihin.

Tarkkaa suhdetta ei ole; projektin tyyppi ratkaisee. Laskentapainotteisessa ohjelmistossa yksikkötestit painavat eniten, kun taas projektissa, joka yhdistyy moniin ulkoisiin järjestelmiin, integraatiotestien osuus kasvaa.

Esimerkki Jestillä ja Playwrightilla

JavaScript-maailmassa Jest ja Vitest ovat yleisiä valintoja yksikkötesteihin sekä Playwright ja Cypress E2E-testeihin. Alla näet yksinkertaisen alennusfunktion yksikkötestin.

Jos haluat napata tyyppivirheet jo ennen testien kirjoittamista, katso myös artikkelimme mikä on TypeScript; tyyppijärjestelmä keventää testien kuormaa jonkin verran mutta ei korvaa niitä.

javascriptYksikkötesti Jestillä
// indirim.js
export function indirimUygula(tutar, oran) {
  if (oran < 0 || oran > 100) throw new Error('Virheellinen prosentti');
  return Math.round(tutar * (100 - oran)) / 100;
}

// indirim.test.js
import { indirimUygula } from './indirim.js';

test('20 prosentin alennus lasketaan oikein', () => {
  expect(indirimUygula(200, 20)).toBe(160);
});

test('virheellinen prosentti aiheuttaa virheen', () => {
  expect(() => indirimUygula(200, 120)).toThrow();
});
javascriptE2E-testi Playwrightilla
import { test, expect } from '@playwright/test';

test('tuote lisätään ostoskoriin', async ({ page }) => {
  await page.goto('https://ornek-magaza.test/urun/zeytinyagi');
  await page.getByRole('button', { name: 'Sepete Ekle' }).click();
  await expect(page.getByTestId('sepet-adet')).toHaveText('1');
});

Testiautomaatio ja CI-prosessi

Testiautomaatio tarkoittaa, että testit ajetaan jokaisen koodimuutoksen yhteydessä automaattisesti eikä käsin. Kun koodi lähetetään repositorioon, CI (jatkuva integraatio) -putki ajaa testit; jos yksikin testi epäonnistuu, muutosta ei viedä tuotantoon.

Tämä järjestely muuttuu entistä arvokkaammaksi tiimin kasvaessa. Kaikkia koskee sama laatuvaatimus ja virheet jäävät kiinni ennen kuin ne ehtivät asiakkaalle.

  1. Kehittäjä tekee muutoksen omaan haaraan ja lähettää sen repositorioon.
  2. CI-putki asentaa riippuvuudet ja ajaa yksikkö- ja integraatiotestit.
  3. Kriittisten polkujen E2E-testit ajetaan testiympäristössä.
  4. Jos kaikki testit läpäistään, koodi viedään katselmoinnin jälkeen tuotantoon.

Muut testityypit

Pelkkä oikein toimiminen ei riitä; ohjelmiston on oltava myös nopea, turvallinen ja käytettävä. Siksi toiminnallisten testien rinnalla on muitakin testityyppejä.

  • Suorituskykytesti: Mittaa, miten järjestelmä käyttäytyy kuormituksessa. Sivun nopeus kuuluu myös nopeuden ja suorituskyvyn hallinnan työhön.
  • Tietoturvatesti: Etsii luvattoman pääsyn, injektion ja vastaavat aukot.
  • Käytettävyystesti: Tarkastaa, pystyvätkö oikeat käyttäjät käyttämään käyttöliittymää vaikeuksitta; luonnollinen osa UI/UX-suunnittelun prosessia.
  • Saavutettavuustesti: Tarkastaa sopivuuden ruudunlukijan ja näppäimistön käyttäjille.
  • Visuaalinen regressiotesti: Vertaa kuvakaappauksia ja nappaa odottamattomat ulkoasumuutokset.
  • Käännettyjen moduulien testit: Myös artikkelissa mikä on WebAssembly käsitellyn Wasm-moduulin kaltaiset osat tarvitsevat oman testiputkensa.

Yleiset testausvirheet

Testien kirjoittaminen on taito; huonosti kirjoitetut testit voivat olla apuna olemisen sijaan taakka. Yleisimmät virheet ovat nämä.

  • Kattavuusprosenttiin juuttuminen: Korkea luku ei tarkoita hyviä testejä; tärkeää on, että kriittinen käyttäytyminen testataan.
  • Sovelluksen sisäisen rakenteen testaaminen: Kun koodia refaktoroidaan, testit hajoavat syyttä. Testaa käyttäytymistä.
  • Hauraat E2E-testit: Käytä kiinteiden odotusaikojen sijaan rakenteita, jotka odottavat elementin ilmestymistä.
  • Testien kytkeminen tuotantodataan: Testien tulee valmistella oma datansa ja siivota se sen jälkeen.
  • Epäonnistuneen testin poistaminen käytöstä ja unohtaminen: Tämä tuhoaa nopeasti luottamuksen testeihin.

Mistä testaus kannattaa aloittaa?

Ei ole realistista lisätä projektiin, jossa ei ole yhtään testiä, yhtäkkiä satoja testejä. Tehokkaampaa on aloittaa riskialttiimmasta kohdasta ja edetä vaiheittain. Jo yhden testin kirjoittaminen jokaisesta korjatusta virheestä muodostaa muutamassa kuukaudessa merkittävän turvaverkon.

Alussa tavoitteena ei pidä olla täydellinen kattavuus vaan luotettavat testit. Vähäiset testit, jotka antavat joka kerta johdonmukaisen tuloksen, ovat arvokkaampia kuin lukuisat epävakaat testit.

  1. Listaa rahaan, varastoon ja käyttäjädataan liittyvät funktiot.
  2. Kirjoita näille funktioille ensin yksikkötestit.
  3. Lisää integraatiotestit kohtiin, jotka yhdistyvät ulkoisiin järjestelmiin.
  4. Pystytä E2E-testit kriittisimpiin kahteen tai kolmeen käyttäjäpolkuun.
  5. Kytke testit CI-putkeen äläkä vie tuotantoon punaisella testillä.

Mitä testit tuovat yritykselle?

Yrityksen omistajalle testaus on näkymätön mutta tuntuva investointi. Siksi räätälöityjä ohjelmistoratkaisuja kehitettäessä kriittisten polkujen saattaminen testien piiriin on tärkeää. Kampanjapäivänä kaatuva maksusivu tai väärää varastotilannetta näyttävä kauppa tulee paljon kalliimmaksi kuin testauksen kustannus.

Kun tilaus-, lasku- ja varastoprosessit kiertävät usean järjestelmän välillä, virheen todennäköisyys kasvaa. Siksi verkkokauppaintegraatio- ja verkkokaupan alusta -projekteissa testatun, ennustettavan rakenteen pystyttäminen laskee ylläpitokustannuksia pitkällä aikavälillä.

Usein kysytyt kysymykset

01Pitääkö pienessä projektissa kirjoittaa testejä?

Jokaista riviä ei tarvitse testata, mutta rahaan tai dataan liittyvät kriittiset funktiot on ehdottomasti testattava. Pienestä aloittaminen antaa myöhemmin projektin kasvaessa mahdollisuuden tehdä muutoksia luottavaisesti.

02Onko manuaalinen testaus täysin tarpeetonta?

Ei. Tutkivat manuaaliset testit löytävät ongelmia, joita automaatio ei ennakoinut. Toistuvat tarkistukset kannattaa automatisoida, ja ihmisen silmä kannattaa varata uusien ominaisuuksien ja kokemuksen arviointiin.

03Mitä on TDD?

Testivetoinen kehitys (TDD) on menetelmä, jossa kirjoitetaan ensin epäonnistuva testi ja sitten koodi, joka saa testin läpi. Se yksinkertaistaa suunnittelua ja estää testittömän koodin jäämisen; tiimillä kuitenkin kestää aikansa tottua tähän kuriin.

04Pitäisikö käyttää Jestiä vai Vitestiä?

Kumpikin on kypsä työkalu yksikkötesteihin ja niiden syntaksi on samankaltainen. Vite-pohjaisissa projekteissa Vitest integroituu helpommin; olemassa olevissa suurissa projekteissa Jest erottuu yleisyydellään.

Ohjelmistotestaus on tapa napata virheet ennen asiakasta ja kasvattaa ohjelmistoa luottavaisesti. Tasapainoinen rakenne, joka ottaa perustaksi yksikkötestit ja varmistaa kriittiset polut E2E-testeillä, on pitkällä aikavälillä edullisin tie. Testatun, ylläpidettävän ohjelmiston saamiseksi voit tutustua Auroran ohjelmistoratkaisuihin ja integraatiopalveluihin.