9. Luento: Ohjelmistotyö Tommi Mikkonen, tommi.mikkonen@tut.fi
Agenda Johdanto Ristikäännös Testaus ja virheen jäljitys Yleensä Kehitysympäristössä Käyttöympäristössä Laitteiston testaus Iteratiivisesta kehityksestä Yhteenveto
Johdanto Kehitystyö ja usein myös testaus ei yleensä tuotantoympäristössä Paitsi ohjelmiston myös laitteiston oikea toiminta usein varmennettava ohjelmallisesti Useita eri ongelmien lähteitä Eri käyttöjärjestelmäpalvelut, kääntäjät, kirjastot, jne. Usein kätevää rakentaa minimaalinen ohjelmisto, jonka toiminnan voi todentaa, ja käyttää sitä kehitysympäristön, työkaluketjun ja kohdelaitteen toiminnan varmentamiseen
Ristikäännös Ohjelma siis kirjoitetaan eri koneessa kuin mitä ajetaan Yleensä eri käskykannat ja laitteisto Joka tapauksessa kohdekoneelle ei yleensä voi suoraan kehittää ohjelmaa Usein useita kääntäjiä, joista osaa voidaan hyödyntää esim. moduulitestauksessa kehitysympäristössä Ongelmia: Kääntäjien erilaisuudet (virheet, rekisterirakenteen käsittely, jne) Käyttöjärjestelmien rajapinnat Käytettävissä olevat kirjastot
Ristikäännös yksinkertaisimmillaan Kehitystyöasema Laite Lähdekoodi Ristikäännös Laitteelle käännetty Siirto (asennus) Laitteessa suoritettava
Testaus ja virheiden jäljitys Yleensä ei (ainakaan kokonaan) mahdollista suorittaa siinä ympäristössä kuin missä kehitetään Muutokset ajoituksissa voivat aiheuttaa ongelmia joka tapauksessa Ei aina selvää testataanko laitteistoa vai ohjelmistoa Sulautettujen järjestelmien määritelmän mukaan itse asiassa molempien yhteistoimintaa! Virheettömyyteen kova pyrky erilaisin keinoin Cleanroom; työn organisointi; formaalit menetelmät, jne.
Virheiden paikantamisesta Vaikutus ja varsinainen vika eivät välttämättä lähellä toisiaan Jäänneviittaukset, roskaantuminen, fragmentoituminen Moniprosessiympäristö Ajoitus Joskus vikoja ei edes vaivauduta korjaamaan Ei kriittinen Riittävän harvinainen -> ei ilmene ehkä koskaan todellisessa käytössä Ylläpidon kannalta tämä tietysti tuo haasteita!
Pöytätestaus 2 versiota Kevyt: Ohjelman tekijä selittää toiselle ohjelmoijalle (tai jollekin joutilaalle!) mitä ohjelman pitäisi tehdä Kuuntelijan ei edes tarvitse ymmärtää, riittää että tekijä kertoo ja samalla huomaa omat ongelmansa Tyhmät kysymykset usein parhaita Raskas: Käydään ohjelmaa läpi rivi riviltä Ohjelma suoritetaan käsin Löytää usein myös muita ongelmia
Testipedit Ohjelmisto, jolla testattavan ohjelmiston moduuleja voidaan testata Interaktiivisesti käyttäjän ohjaamana Eräajotyyppisesti automaattisesti Muutoksen jälkeen voidaan tehdä regressiotestit koko aineistolla Usein ei päästä lähellekään sataa prosenttia ilman erityistoimenpiteitä Musta/valkoinen laatikko testit eri tilanteissa Usein valmisohjelmisto tai testaustarkoitukseen rakennettu sovelluskehys Usein suositeltavaa myös pöytäkoneissa ajettaville ohjelmille!
Profilointi Pyrkii löytämään ohjelman osat, joissa vietetään eniten aikaa Ei varsinaisesti testausta, mutta usein käyttökelpoinen menettelytapa sulautettujen ohjelmistojen yhteydessä Ei kuitenkaan kannata ylioptimoida tarpeettomasti Yleensä tehdään kehitysympäristössä (profilointitiedon keruu laitteella voi olla vaikeaa; muistinkulutus voi olla liika; jne) Ei siis välttämättä sama tulos kohdeympäristössä Profilointioperaatiot voivat myös siirtää pullonkaulaa (esim. profilointitulosten tiedostoonkirjoittamiseen!)
Kehitysympäristön työkaluista Yleensä kannattaa aloittaa näillä Nopeampaa (prosessori nopeampi, ei tarvita siirtoja) Työkalut monipuolisempia Ei kuitenkaan voi olla ainoa vaihtoehto Eroavaisuuksia joka tasolla Kääntäjä Kirjastot Käyttöjärjestelmä Prosessorin käskykanta Muistiavaruus Nyrkkisääntö: Looginen toiminta kuntoon kehitysympäristössä
Järjestelmän simulointi Ohjelma käännetään kohdekoneen ymmärtämään muotoon, mutta kohdelaitteen sijasta sitä suoritetaan kehitysympäristössä simulaattorissa Simulaattorissa mahdollista kuvata myös oheislaitteet, joten niihinkin liittyviä ominaisuuksia voidaan simuloida Ongelma: Jos monimutkainen kokonaisuus, simulaatioympäristö ei aina pysty tuottamaan tarpeeksi aitoja reaktioita Sopii kuitenkin perustestaukseen ennen varsinaiseen kohdelaitteeseen siirtoa
Virtualisointi Kuten simulointi, mutta yleensä pidemmälle vietynä Taustalla esim. järjestelmä joka toimii kuten kohdejärjestelmä (riittävällä tarkkuudella) Usein soveltuu myös kehitysympäristöksi Tavallinen ratkaisu sulautettujen Linuxohjelmistojen kehityksessä Virtuaali-imageja ladattavissa suoraan Webistä eri tarkoituksiin Ongelmiakin on, esim. näppäimistön lokalisointi jne.
Testaus ja jäljitys kohdejärjestelmässä Peräkkäisohjelman debuggaustyyli ei toimi kovin hyvin sulautetussa ympäristössä Ideana ei laskea inputista sopivaa outputtia Rivi kerrallaan eteneminen paljastaa vain osan totuudesta (yleensä rinnakkaisia suorituksia) Tarvitaan erilaisia apulaitteita Logiikka-analysaattorit, emulaattorit, seurannan apuvälineet ja erilliset testijärjestelmät, jopa led-valot
Logiikka-analysaattori Voidaan tutkia suorittimen tai väylän liikennettä Kopio väyläliikenteestä ja askelittainen tulkinta Jotkut laitteet jopa muuntavat bittivirran symboliseen konekoodimuotoon Muistikartta auttaa! Kaikkea ei kuitenkaan voi nauhoittaa; erilaiset nauhoitusehdot usein tarpeen Välimuistin käyttö voi aiheuttaa ongelmia
Emulaattori Esim. suorittimen paikalle asennetaan välikannan avulla piirikortti, joka toimii ulkoisesti kuten suoritin Suoritus tyypillisesti mahdollista askelittain Muuttujien arvojen tarkastelut Monessa mielessä kuten järjestelmätason debuggeri Ei kuitenkaan pure kaikkeen Ajastusongelmat Muistinkulutukseen liittyvät asiat (emulaattorissa on usein enemmän muistia kuin kohdejärjestelmässä) Joskus ohjelma voi toimia kohdelaitteessa mutta ei emulaattorissa (esim. lukumuistin korvaaminen luku-kirjoitusmuistilla voi aiheuttaa tällaisia ongelmia)
Erillinen testijärjestelmä Muistuttaa ohjelmistotuotannon V-mallin ideaa Laitekohtainen vs. yleiskäyttöinen testijärjestelmä Edellinen usein mahdollista vain kaikkien kalleimpien järjestelmien yhteydessä, sillä Vaatii pahimmassa tapauksessa oman projektinsa, jossa järjestelmälle rakennetaan sitä täysin vastaava testiympäristö Tyypillisesti myös testijärjestelmä on itse asiassa sulautettu järjestelmä Toteutus ja testijärjestelmä siis verifioivat toistensa oikean toiminnan!
Tiedon siirto koneelta toiselle analysoitavaksi Vaatii yleensä erityisen liitynnän Analysointi joko välittömästi (on-line) tai jälkikäteen (off-line) Tiedonkeruu ei välttämättä näkyvää Kerätään tapahtumatietoa väylältä; Usein kuitenkin tarvitaan lisäinfoa (mikä taas vaatii lisäsanomia) Lisäliitynnän avulla tiedonsiirto on kuitenkin usein yksinkertaisempaa Voi vaikuttaa ohjelman toimintaan Ehdollinen kääntäminen mahdollistaa erilliset debug/tuotantoversiot Joskus myös ongelmia sillä suoritettava ohjelma ei ole täysin sama
Laitteiston testaamisesta Tyypillisten laitteistovikojen tuntemus Huonot kontaktit Oikosulut Katkenneet johdot Sähkömagneettisesta induktiosta johtuva signaalin ylikuuluminen Väärät signaalitasot Ajoitusvirheet Työkaluina sähköiset mittalaitteet (esim. oskiloskooppi) Onneksi ohjelmallisestikin voi tehdä yhtä ja toista Nyrkkisääntö: Jos useampi kuin 1 vika, peli usein menetetty!
Muistien testaamisesta Lukumuistin testaus käymällä läpi muistipaikat ja laskemalla tarkistussumma (joka on myös tallennettu lukumuistiin) Luku/kirjoitusmuistin testaus ensin kirjoittamalla ja sitten lukemalla (esim. ensin 5555 hex ja sitten AAAA hex ) Jos väylien johdotus tavallisesta poikkeava, kannattaa pohtia testiarvoja joilla ylikuulumiset voidaan havaita HUOM: Välimuisti kannattaa kytkeä pois päältä!
Oheislaitteiden testaus Monimutkaisissa laitteissa erityisiä testitiloja Yksinkertaisissa piireissä testein voi kokeilla onnistuuko keskeyttäminen, tilarekisterien käsittely jne. Yleensä oheislaitteiden testaus onnistuu parhaassakin tapauksessa vain osittain Nyrkkisääntö: Käynnistyksen yhteydessä aina perustesti; tarvittaessa kattavampi huolto- ja valmiustilatesti
Iteratiivisuudesta Kätevää myös muita ohjelmistoja kehitettäessä, lähes välttämätöntä sulautetussa ympäristössä
Vähän pidempi selitys Yleensä kokonaisjärjestelmälle löytyy perinteinen määrittely Työnjakoon liittyvät syyt; laitteiston valmistustekniikkaan liittyvät syyt Kokonaismäärittely kattaa sekä laitteiston että ohjelmiston yhteistoiminnan Tämän jälkeen on suoritettu jako eri tekniikoin toteutettuihin osiin, jotka toteutetaan erikseen Ensimmäinen yritys yhteistoiminnasta harvoin osuu nappiin! Virheiden jäljitys myös helpompaa kun on pienempi toteutus
Ohjelmiston määrittely Ohjelmiston suunnittelu Ohjelmiston toteutus Kokonaismäärittely Kokonaissuunnittelu Työn jako osiin Laitteiston määrittely Laitteiston suunnittelu Laitteiston toteutus Ohjelmiston testaus Laitteiston testaus Integrointi ja testaus
Suunnittelun etenemisestä Ensimmäinen versio usein yksinkertaisin toteutus joka tekee jotain verifioitavaa Mukana usein myös laitetestit, mutta ei välttämättä Tarkoitus varmentaa työkaluketju Usein jo laitteen henkiin saaminen on melkoinen suoritus, vaikkei se tekisikään vielä mitään Seuraavat iteraatiot lisäävät toiminnallisuutta pieni pala kerrallaan jotta mahdolliset ongelmat on mahdollista korjata osittaen Usein insinöörityön hienous on juuri pienimpien muutosten löytämisessä (ja mahdollisuuksien mukaan erikseen testaamisessa ja toiminnan varmentamisessa!) Henkiin herääminen Laitteiston testaus Algoritmit Laitteiston ongelmien piilottaminen/kiertäminen Onnistunut suoritus ei kuitenkaan ole riittävä ehto ohjelmiston valmistumiselle
Yhteenveto Kehitys- ja käyttöympäristöt eivät ole samat Suuri joukko erilaisia avustavia työkaluja; eivät kuitenkaan voi kokonaan korvata oikean laitteen käyttöä kehityksen aikana Laitteiston testaus on osa ohjelmiston tehtävää oikeastaan lähes aina Iteratiivinen kehitystyyli lähes välttämätöntä ohjelmistotyössä