% Ohjelmistotuotanto % Matti Luukkainen ja ohjaajat Kalle Ilves, Silva Perander, Topias Pyykönen, Jussi Laisi, Petrus Peltola, Kristian Krok % syksy 2020
Luento 5
9.11.2020
- 16.11. alkavalla viikolla
- ilmoittautuminen alkanut, päättyy perjantaina
- pakollinen, jos et hyväksilue
- Laadunhallinnan kaksi oleellista kysymystä
- verifiointi: are we building the product right
- validointi: are we building the right product
. . .
- Verifioinnissa varmistetaan, että ohjelmisto toteuttaa vaatimusmäärittelyn aikana asetetut vaatimukset
- Testataan toiminnalliset ja ei-toiminnalliset vaatimukset
. . .
- Validointi: varmistetaan, että ohjelmisto täyttää käyttäjän odotukset
- Vaatimusmäärittelyn aikana kirjatut vaatimukset eivät ole aina se mitä käyttäjä todella tarvitsee
- Tavoitteena on varmistaa että ohjelma on "riittävän hyvä" käyttötarkoitukseensa
- Hyvyys on suhteellista ja riippuu ohjelman käyttötarkoituksesta
- Ohjelman ei yleensä tarvitse olla virheetön ollakseen riittävän hyvä käytettäväksi
. . .
- Verifioinnin ja validoinnin suorittamista käytetään yleisesti nimitystä laadunhallinta (engl. quality assurance, QA)
- Jos laadunhallinta on erillisen tiimin vastuulla, käytetään tästä usein nimitystä QA-tiimi
- Verifioinnissa käytetään kahta erilaista tekniikkaa
- Katselmointeja
- Testausta
. . .
- Katselmoinneissa (review) käydään läpi tuotantoprosessin aikana tehtyjä dokumentteja ja ohjelmakoodia, ja etsitään näistä ongelmia
. . .
- Katselmointi on staattinen tekniikka, suorituskelpoista ohjelmakoodia ei tarvita
- Jos katselmoinnin kohteena on ohjelmakoodi, ei sitä katselmoinnissa suoriteta
. . .
- Testaus on dynaaminen tekniikka, joka edellyttää ohjelmakoodin suorittamista
- tarkkaillaan miten ohjelma reagoi annettuihin testisyötteisiin
- Ohjelmistolle määritellyt vaatimukset on validoitava:
- varmistettava, että määrittelydokumentti määrittelee oikeanlaisen ohjelmiston
. . .
- Vesiputousmallissa määrittelydokumentin kirjattujen vaatimusten validointi suoritetaan katselmoimalla
. . .
- Vaatimusmäärittelyn lopuksi asiakas tarkastaa vastaako määrittelydokumentti mielikuvaa tilattavasta järjestelmästä
. . .
- Katselmoinnin jälkeen määrittelydokumentti jäädytetään ja sen muuttaminen vaatii yleensä monimutkaista prosessia
- Ketterässä ohjelmistotuotannossa vaatimusten validointi tapahtuu sprinttien päättävien demonstraatioiden yhteydessä
. . .
- Asiakkaalle näytetään ohjelman toimivaa versiota
. . .
- Asiakas voi itse verrata onko lopputulos haluttu
- Jos ei, on seuraavassa sprintissä mahdollista ottaa korjausliike
- Koodin katselmointi eli lukeminen jonkun muun kuin ohjelmoijan toimesta on tehokas keino laadun parantamisessa
. . .
- Voidaan havaita koodista ongelmia, joita testaus ei havaitse
- noudattaako koodi sovittua tyyliä
- onko koodi ylläpidettävää
- onko koodissa tietoturvan kannalta vaarallisia piirteitä
. . .
- Perinteisesti käyty läpi onko koodissa tiettyjä checklisteissä listattuja riskialttiita piirteitä
- Joissakin kielissä, esim. Javassa kääntäjän tuki tekee osan näistä tarkistuksista turhaksi
- Nykyään on tarjolla katselmointia automatisoivia staattista analyysiä tekeviä työkaluja
- Javalla Checkstyle
- Javascriptilla ESlint
. . .
- Myös pilvipalveluna toimivia työkaluja kuten Codeclimate
- Suorittavat tarkastukset aina kun uutta koodia pushataan GitHubiin
- Huomaavat koodin laadun muutoksista, esim. jos koodin kompleksisuus kasvaa muutosten yhteydessä
- GitHubin pull requestit tarjoavat hyvän työkalun koodikatselmointiin
. . .
- Työn kulku on seuraava
- Sovelluskehittäjä forkkaa repositorin itselleen, tekee muutokset omaan repositorioon ja tekee pull requestin
- Joku, esim. senior developer tekee katselmoinnin pull requestille
- Jos koodi ei ole riittävän hyvää, annetaan pull requestin tekijälle parannusehdotuksia
- Muutosten ollessa hyväksyttäviä, pull request mergetään päärepositorioon
- Toisin kuin Scrum, eXtreme Programming eli XP määrittelee useita sovelluskehityksen käytänteitä
- Suuri osa XP:n käytänteistä on hyvin tunnettuja best practiseja, vietynä äärimmäiseen (extreme) muotoon
. . .
- Osa käytänteistä tähtää laadun maksimoimiseen, kolmen voidaan ajatella olevan katselmoinnin äärimmäinen muoto
- Pariohjelmoinnissa (pair programming) kaksi ohjelmoijaa työskentelee yhdessä samalla koneella
. . .
- Koodia kirjoittava osapuoli toimii ohjaajana (driver) ja toinen navigoijana (navigator)
- Roolia vaihdetaan sopivin väliajoin
. . .
- Navigoija tekee koodiin jatkuvaa katselmointia
- Parantaa ohjelmoijien kuria ja työhön keskittymistä
. . .
- Hyvä oppimisen väline
- ohjelmoijat oppivat toisiltaan erityisesti noviisit kokeneimmilta, järjestelmän tietyn osan tuntee aina useampi ohjelmoija
. . .
- Todettu vähentävän bugien määrää 15-50%, kokonaisresurssin kulutus nousee hieman
- Pariohjelmointi tai useamman ihmisen versio siitä, mob-programming on melko yleistä
- "Määritelmän" mukaista systemaattista pariohjelmointia tehdään aika harvassa paikassa aamusta iltaan
. . .
- Yleensä ohjelmoidaan yksin, mutta spontaania pariutumista ja ryhmäytymistä tapahtuu
- erityisesti teknisesti haasteellisissa koodin osissa
- tai jos kyse itselle tuntemattomasta osasta koodia
- Koodin yhteisomistajuus (collective code ownership): kukaan yksittäinen ohjelmoija ei hallitse yksin mitään kohtaa koodista
- Kaikilla lupa tehdä muutoksia mihin tahansa kohtaan koodia
. . .
- Pariohjelmointi tukee yhteisomistajuutta
- Yhteisomistajuudessa on riskinsä: koodia tuntematon voi saada pahaa jälkeä aikaan
- XP eliminoi riskejä testauksiin liittyvillä käytänteillä
. . .
- Ohjelmointistandardi (coding standards): tiimi määrittelee koodityylin, johon kaikki ohjelmoijat sitoutuvat
- Tyylillä tarkoitetaan nimeämiskäytäntöä, koodin muotoilua ja myös tiettyjä ohjelman rakenteeseen liittyviä seikkoja
. . .
- Noudattamista kontrolloidaan katselmoimalla sekä automaattisesti staattisen analyysin työkaluilla kuten checkstylellä
- Ohjelmien osoittaminen virheettömäksi on mahdotonta
. . .
- Testauksen tarkoituksena vakuuttaa asiakas ja kehittäjät siitä, että ohjelmisto on tarpeeksi hyvä käytettäväksi
. . .
- Testauksella on kaksi eriävää tavoitetta
- osoittaa, että ohjelmisto täyttää sille asetetut vaatimukset
- löytää ohjelmistosta virheitä
. . .
- Tähtää ohjelman ulkoisen laadun (external quality) eli käyttäjän kokeman laadun parantamiseen
- External Quality is the fitness for purpose of the software.
- It's most obvious measure is the Functional Tests,
- and some measure of the bugs that are still loose when the product is released.
- Yksikkötestaus (unit testing)
- Yksittäisten luokkien, metodien ja moduulien testaus erillään muusta kokonaisuudesta
. . .
- Integraatiotestaus (integration testing)
- Yksittäin testattujen komponenttien liittäminen yhteen eli integrointi ja kokonaisuuden testaus
. . .
- Järjestelmätestaus (system testing)
- Toimiiko ohjelmisto vaatimuksiin kirjatulla tavalla?
- Tutkii järjestelmää kokonaisuudessaan: end to end -testaus
- Jakautuu useisiin alalajeihin
. . .
- Käyttäjän hyväksymistestaus (user acceptance testing)
- Loppukäyttäjän tuotteelle suorittama testaus
- Tarkoitus varmistaa, että järjestelmä toimii vaatimuksiin kirjatulla tavalla
- Kehittäjäorganisaatio suorittaa järjestelmätestauksen
. . .
- Testaus tapahtuu yleensä ilman tietoa järjestelmän sisäisestä rakenteesta eli kyseessä black box -testaus
. . .
- Testataan järjestelmää saman rajapinnan kautta, jonka kautta järjestelmää käytetään
. . .
- Tarkastelevat sovelluksen toiminnalisuutta useimmiten sen kaikilla tasoilla käyttöliittymästä sovelluslogiikkaan ja tietokantaan
- Tämän takia käytetään myös nimitystä End to End -testaus
- Perustuu järjestelmän potentiaalisiin käyttöskenaarioihin
- user storyinä olevista vaatimuksista helppo muotoilla testejä
- jos storyillä hyväksymiskriteeriot, tilanne on vieläkin parempi
. . .
- Kutsutaan myös toiminnallisiksi testeiksi (functional test)
. . .
- Toiminnallisen testauksen lisäksi järjestelmätestaukseen kuuluu
- Käytettävyystestaus
- Suorituskykytestaus
- Kuormitustestaus
- Tietoturvan testaus
- Kattava testaaminen on mahdotonta ja testaus työlästä
- Oleellista löytää kohtuullisen kokoinen testitapausten joukko, jonka avulla löytyy mahdollisimman suuri määrä virheitä
. . .
- Yksi Testitapaus testaa toiminnallisuutta joillakin syötteillä
- Useat syötteet ohjelmiston toiminnan kannalta samanlaisia
- nämä muodostavat ekvivalenssiluokan
. . .
-
Jaetaan syötteet ekvivalenssiluokkiin ja tehdään yksi testitapaus kutakin ekvivalenssiluokkaa
-
Erityisen kiinnostavia syötearvoja ovat ekvivalenssiluokkien väliset raja-arvot
. . .
- Henkilötietoja käsittelevä järjestelmä: henkilön iän ekvivalenssiluokat?
- 06, 7-17, 18-65, 66-
- Mitä testitapauksia kannattaisi valita tekstitv:n sivun valintaikkunan testaamiseen?
- Tekstitv:n sivu vastaa lukua väliltä 100-899
- Osaa välin luvuista vastaavaa sivua ei ole olemassa
. . .
- Testisyötteen ekvivalenssiluokkia olisivat ainakin seuraavat
- Olemassa olevaa sivua vastaavat luvut: 235
- Validit luvut jotka eivät vastaa mitään sivua: ???
- Liian pienet ja liian suuret luvut: 99, 900, 1000
- Syötteet jotka sisältävät kiellettyjä merkkejä: 10X, 100X
- Tyhjä syöte
- Kohteena siis yksittäiset metodit ja luokat
. . .
- Testattavan koodin rakenne otetaan huomioon testejä laatiessa, lasilaatikkotestausta (white box testing)
- Developer testing: sovelluskehittäjien vastuulla
. . .
- Päätarkoitus sisäisen laadun (internal quality) kontrollointi
- onko virheiden jäljitys ja korjaaminen helppoa
- onko koodia helppo laajentaa ja jatkokehittää
- pystytäänkö koodin toiminnallisuuden oikeellisuus varmistamaan muutoksia tehtäessä
- Iteratiivisessa kehityksessä sisäisellä laadulla suuri merkitys (ohjelmistoa laajennetaan koko ajan)
. . .
- Edesauttaa myös ulkoista eli asiakkaan kokemaa laatua
- Yksikkötestit voivat eliminoida joitain asiakkaalle näkyviä virheitä, joita järjestelmätestauksen testitapaukset eivät löydä
. . .
- Bugit on taloudellisesti edullista paikallistaa mahdollisimman aikaisessa vaiheessa
- yksikkötestauksessa löydetty bugi on halvempi ja nopeampi korjata kuin järjestelmä- tai integraatiotestauksessa löytyvä
. . .
- Koska yksikkötestejä joudutaan ajamaan moneen kertaan, tulee niiden suorittaminen ja testien tulosten raportointi automatisoida
- JUnitin kehittäjän Kent Beckin vastaus:
- "Do I have to write a test for everything?"
- "No, just test everything that could reasonably break"
. . .
- Optimitilanteessa testitapaukset
- kaikkien metodit ja niiden kutsukombinaatiot hyväksyttävillä parametrien arvoilla
- ja virheellisillä parametrien arvoilla
. . .
-
Ekvivalenssiluokat ja niiden raja-arvot kannattaa huomioida
-
Koska yksikkötestejä tehtäessä ohjelmakoodi on nähtävillä, testien parametrien ekvivalenssiluokat ja raja-arvot pääteltävissä koodista
public class Varasto {
private double tilavuus;
private double saldo;
public double otaVarastosta(double maara) {
if (maara < 0) return 0.0;
if(maara > saldo) {
double kaikkiMitaVoidaan = saldo;
saldo = 0.0;
return kaikkiMitaVoidaan;
}
saldo = saldo - maara;
return maara;
}
}
- Yksikkötestien (ja toki myös muunkinlaisten testien) hyvyyttä voidaan mitata testauskattavuuden (test coverage) käsitteellä
. . .
- Muutamaa eri tyyppiä
- rivikattavuus
- haarautumakattavuus
- ehtokattavuus
- polkukattavuus
. . .
- Rivi- ja haarautumakattavuudelle hyvä työkalutuki, esim JaCoCo
- Pelkkä kattavuus ei kerro paljoa testien laadusta
. . .
- Hyvien testien pitäisi huomata (ts. mennä rikki) jos ohjelmaan tulee bugi
. . .
-
Mutaatiotestaus (engl. mutation testing) tutkii testien hyvyyttä generoimalla koodiin mutantteja eli pieniä "bugeja" ja tarkastamalla hajoavatko testit
-
Erilaisia mutanttityyppejä:
if ( x<0 ) if (x <= 0) tai if (true)
x += 1 x-= 1
return x return true
olio = new Olio() olio = null
. . .
- Ongelmana on mutaatioiden suuri määrä ja ns. ekvivalentit mutantit
- tulos vaatii aina ihmisen tulkintaa
- Järjestelmän yksittäiset, erillään yksikkötestatut luokat tulee integroida toimivaksi kokonaisuudeksi
- Integroinnin yhteydessä tai sen jälkeen suoritetaan integrointitestaus
- Toimivatko komponentit yhdessä?
. . .
- Kaksi lähestymistapaa: rakenteisiin perustuva ja toiminnallisuuksiin perustuva
- Rakenteeseen perustuvassa integraatiossa keskitytään kerrallaan sovelluksen yksittäisten arkkitehtuurillisten komponenttien integrointiin
. . .
- Verkkokaupassa integroitaisiin sovelluslogiikan luokat, käyttöliittymän luokat ja tietokantarajapinta ensin omina kokonaisuuksinaan
. . .
-
Rakenteeseen perustuvassa integraatiossa keskitytään kerrallaan sovelluksen yksittäisten arkkitehtuurillisten komponenttien integrointiin
-
Verkkokaupassa integroitaisiin sovelluslogiikan luokat, käyttöliittymän luokat ja tietokantarajapinta ensin omina kokonaisuuksinaan
-
Rakenteeseen perustuvassa integraatiossa keskitytään kerrallaan sovelluksen yksittäisten arkkitehtuurillisten komponenttien integrointiin
-
Verkkokaupassa integroitaisiin sovelluslogiikan luokat, käyttöliittymän luokat ja tietokantarajapinta ensin omina kokonaisuuksinaan
-
Rakenteeseen perustuvassa integraatiossa keskitytään kerrallaan sovelluksen yksittäisten arkkitehtuurillisten komponenttien integrointiin
-
Verkkokaupassa integroitaisiin sovelluslogiikan luokat, käyttöliittymän luokat ja tietokantarajapinta ensin omina kokonaisuuksinaan
-
Rakenteeseen perustuvassa integraatiossa keskitytään kerrallaan sovelluksen yksittäisten arkkitehtuurillisten komponenttien integrointiin
-
Verkkokaupassa integroitaisiin sovelluslogiikan luokat, käyttöliittymän luokat ja tietokantarajapinta ensin omina kokonaisuuksinaan
- Ominaisuuksiin perustuvassa integroinnissa liitetään yhteen alikomponentit, jotka toteuttavat järjestelmän loogisen toimintakokonaisuuden
. . .
- Esim. integroidaan kerrallaan kaikki storyn lisää tuote ostoskoriin toteutukseen liittyvä koodi
- Tämän jälkeen integroidaan seuraavan storyn koodi
. . .
-
Ominaisuuksiin perustuvassa integroinnissa liitetään yhteen alikomponentit, jotka toteuttavat järjestelmän loogisen toimintakokonaisuuden
-
Esim. integroidaan kerrallaan kaikki storyn lisää tuote ostoskoriin toteutukseen liittyvä koodi
- Tämän jälkeen integroidaan seuraavan storyn koodi
-
Ominaisuuksiin perustuvassa integroinnissa liitetään yhteen alikomponentit, jotka toteuttavat järjestelmän loogisen toimintakokonaisuuden
-
Esim. integroidaan kerrallaan kaikki storyn lisää tuote ostoskoriin toteutukseen liittyvä koodi
- Tämän jälkeen integroidaan seuraavan storyn koodi
-
Ominaisuuksiin perustuvassa integroinnissa liitetään yhteen alikomponentit, jotka toteuttavat järjestelmän loogisen toimintakokonaisuuden
-
Esim. integroidaan kerrallaan kaikki storyn lisää tuote ostoskoriin toteutukseen liittyvä koodi
- Tämän jälkeen integroidaan seuraavan storyn koodi
- Vesiputuoksen toimintatapa
- Yksittäiset komponentit ohjelmoidaan ja yksikkötestataan erikseen
- Tämän jälkeen ne integroidaan, yleensä rakenteeseen perustuen, kerralla yhteen
. . .
- Tämän tyylinen big bang -integraatio on osoittautunut todella riskialttiiksi
- Seurauksena usein ns. integraatiohelvetti
. . .
- Moderni ohjelmistotuotanto suosii ns. jatkuvaa integraatiota
- Hyvin tiheässä tahdissa tapahtuvaa ominaisuuksiin perustuvaa integrointia
- Iteratiivisessa ohjelmistotuotannossa, jokainen iteraatio tuottaa ohjelmistoon uusia ominaisuuksia
- Tulee huolehtia, että ei rikota jo toimivia osia
. . .
- Testit siis on suoritettava uudelleen aina kun ohjelmistoon tehdään muutoksia
- Tätä käytäntöä sanotaan regressiotestaukseksi
. . .
- Regressiotestijoukko koostuu kaikista ohjelmistolle tehdyistä testeistä
- sisältää yksikkö-, integraatio- ja järjestelmätesteistä
. . .
- Testaus on työlästä ja regressiotestauksen tarve tekee siitä entistä työläämpää
- Testaus kannattaa automatisoida mahdollisimman suurissa määrin