TDD ja ATDD. Niklas Collin. Naulakatu 3, 33100 Tampere www.kilosoft.fi

Samankaltaiset tiedostot
TDD Tarina käyttöönotosta

Ohjelmistojen mallintaminen. Luento 11, 7.12.

Yksikkötestaus. import org.junit.test; public class LaskinTest public void testlaskimenluonti() { Laskin laskin = new Laskin(); } }

Tapahtuipa Testaajalle...

Metodien tekeminen Javalla

JReleaser Yksikkötestaus ja JUnit. Mikko Mäkelä

Ohjelmointi 2 / 2010 Välikoe / 26.3

Testivetoinen ohjelmistokehitys

Olio-ohjelmointi Javalla

1 Tehtävän kuvaus ja analysointi

Ohjelmistotekniikan menetelmät, toteutuksesta ja testauksesta

Ohjelmistotekniikan menetelmät, toteutuksesta ja testauksesta

Ohjelmointi 2 / 2008 Välikoe / Pöytätestaa seuraava ohjelma.

1. Mitä tehdään ensiksi?

Ohjelmistotekniikan menetelmät, koe

Rajapinta (interface)

9. Periytyminen Javassa 9.1

812341A Olio-ohjelmointi Peruskäsitteet jatkoa

Mikä yhteyssuhde on?

Javan perusteet. Ohjelman tehtävät: tietojen syöttö, lukeminen prosessointi, halutun informaation tulostaminen tulostus tiedon varastointi

Rinnakkaisohjelmointi kurssi. Opintopiiri työskentelyn raportti

20. Javan omat luokat 20.1

TDD Käytännössä Todellinen työkalu vai lehmipoikien laukkaa? Harri Kulmala Solita Oy

Sisällys. 20. Javan omat luokat. Java API. Pakkaukset. java\lang

Tehtävä 1. Tehtävä 2. Arvosteluperusteet Koherentti selitys Koherentti esimerkki

Test-Driven Development

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

on ohjelmoijan itse tekemä tietotyyppi, joka kuvaa käsitettä

17. Javan omat luokat 17.1

4. Luokan testaus ja käyttö olion kautta 4.1

1.3 Lohkorakenne muodostetaan käyttämällä a) puolipistettä b) aaltosulkeita c) BEGIN ja END lausekkeita d) sisennystä

Metodit. Metodien määrittely. Metodin parametrit ja paluuarvo. Metodien suorittaminen eli kutsuminen. Metodien kuormittaminen

Testilähtöinen ohjelmistokehitys. Testilähtöinen ohjelmistokehitys. TDD Testilähtöinen ohjelmistokehitys. Testi! Testi

Automaattinen yksikkötestaus

Testilähtöinen ohjelmistokehitys. Testilähtöinen ohjelmistokehitys. TDD Testilähtöinen ohjelmistokehitys. Testi! Testi. Test-Driven Development, TDD

Toisessa viikkoharjoituksessa on tavoitteena tutustua JUnit:lla testaukseen Eclipse-ympäristössä.

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

Sisällys. 6. Metodit. Oliot viestivät metodeja kutsuen. Oliot viestivät metodeja kutsuen

15. Ohjelmoinnin tekniikkaa 15.1

Luokka Murtoluku uudelleen. Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista.

Onnistunut ohjelmistoprojekti

Sisältö. 2. Taulukot. Yleistä. Yleistä

KOHDELUOKAN MÄÄRITTELY

Ohjelmoinnin jatkokurssi, kurssikoe

Kompositio. Mikä komposition on? Kompositio vs. yhteyssuhde Kompositio Javalla Konstruktorit set-ja get-metodit tostring-metodi Pääohjelma

Tietorakenteet. JAVA-OHJELMOINTI Osa 5: Tietorakenteita. Sisällys. Merkkijonot (String) Luokka String. Metodeja (public)

Scrumin käyttö ketterässä sovelluskehityksessä

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma.

Ohjelmistotuotanto. Luento

Pakkauksen kokoaminen

Tarjolla tänää: Ohjelmiston toteutuksesta. Kuinka tulla hyväksi ohjelmoijaksi? CRC-kortit. Testilähtöinen kehittäminen JOT2007. Uudelleenrakentaminen

14. Poikkeukset 14.1

Scrumjatkuvan palvelun DWprojektissa-case. Niina Mäkiranta & OP-scrum-tiimi Aureolis Oy

Luokan sisällä on lista

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

T Ohjelmistotuotannon seminaari. Agile Processes. XP:n hyväksymistestit

15. Ohjelmoinnin tekniikkaa 15.1

Ohjelmistojen suunnittelu

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä. Tiedonkätkentä. Aksessorit. 4.2

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä ja ulkopuolelta. Attribuuttien arvojen käsittely aksessoreilla. 4.2

Java-API, rajapinnat, poikkeukset, UML,...

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

Test-Driven Development

Java-kielen perusteita

Ohjelmoinnin perusteet, syksy 2006

Helia Ohjelmointitaito Tuomas Kaipainen Mermit Business Applications Oy Mermit Business Applications

Sisällys. JAVA-OHJELMOINTI Osa 7: Abstrakti luokka ja rajapinta. Abstraktin luokan idea. Abstrakti luokka ja metodi. Esimerkki

Yksikkötestaus. Kattava testaus. Moduulitestaus. Ohjelman testaus. yksikkotestaus/ Seija Lahtinen

public static void main (String [] args)

Ohjelmistojen mallintaminen, kurssikoe esimerkkivastauksia

1.3Lohkorakenne muodostetaan käyttämällä a) puolipistettä b) aaltosulkeita c) BEGIN ja END lausekkeita d) sisennystä

Java-kielen perusteet

Ohjelmointi 2 / 2011 Välikoe / 25.3

Ohjelmistojen mallintaminen, syksy 2011, laskuharjoitus 2

Sisältö Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 26.2

YHTEYSSUHDE (assosiation)

Pakkauksen kokoaminen

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen

Tutkittua tietoa. Tutkittua tietoa 1

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Sisältö. Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 6.2

Ohjelmointi 1 / 2009 syksy Tentti / 18.12

Javan perusteita. Janne Käki

Ohjelmointikielet ja -paradigmat 5op. Markus Norrena

Kokemuksia eri projektityyppien haasteista/sudenkuopista toimittajayhteistyön näkökulmasta. Pekka

9. Periytyminen Javassa 9.1

14. Poikkeukset 14.1

Sisältö. Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 6.2

Ohjelmointi 2, välikoe

T Henkilökohtainen harjoitus: FASTAXON

Vertailulauseet. Ehtolausekkeet. Vertailulauseet. Vertailulauseet. if-lauseke. if-lauseke. Javan perusteet 2004

Ohjelmistoprosessit ja ohjelmistojen laatu Ohjelmistoprosessit ja ohjelmistojen laatu (4op)

KOODAAKO PROJEKTIPÄÄLLIKKÖ?

Sisällys. Metodien kuormittaminen. Luokkametodit ja -attribuutit. Rakentajat. Metodien ja muun luokan sisällön järjestäminen. 6.2

Listarakenne (ArrayList-luokka)

Olion elinikä. Olion luominen. Olion tuhoutuminen. Olion tuhoutuminen. Kissa rontti = null; rontti = new Kissa();

Projekti 1 Säikeet ja kriittisen vaiheen kontrollointi javalla

SEPA REFAKTOROINTI Antti Ahvenlampi, 57408L Erik Hakala, 57509T

Tietokannat II -kurssin harjoitustyö

A) on käytännöllinen ohjelmointitekniikka. = laajennetaan aikaisemmin tehtyjä luokkia (uudelleenkäytettävyys)

Transkriptio:

TDD ja ATDD Niklas Collin Naulakatu 3, 33100 Tampere www.kilosoft.fi

Kilosoft Kilosoft on ohjelmistokehityksen, laadunvarmistuksen ja verkonhallintajärjestelmien asiantuntijayritys. Kilosoft Oy on perustettu vuonna 2002 Toimipaikkamme sijaitsevat Tampereella, Espoossa ja Jyväskylässä Toimimme myös kansainvälisesti yhteistyökumppaneidemme kautta Olemme kannattava kasvuyritys Palveluksessamme on vuoden 2010 syyskuussa noin 70 ohjelmistotuotannon ammattilaista Liikevaihtomme vuonna 2009 oli 2,1 M. Ennusteemme vuodelle 2010 on 3,7 4 M

Luennoija Niklas Collin Ohjelmistoarkkitehti Kilosoftilla Siirtyi Kilosoftin palvelukseen 2010 alkuvuodesta Novaloc Oy:n liiketoiminnan myynnin myötä Myydyn Novaloc Oy:n osaperustaja TTY:n kasvatteja Tutkintouudistus painosti valmistumaan alkuvuodesta :) Menossa Australiaan APSEC 2010:een puhumaan TDD:stä ja CI:stä yhdessä prof. Tommi Mikkosen kanssa loppuvuodesta

Agenda 1) Motivaatio ja käytettyä sanastoa 2) Testiohjattu kehitys (TDD) 3) Hyväksymistestivetoinen kehitys (ATDD)

Olen koodari! Minäkö muka testaisin? Nykyaikaiseen ohjelmistokehitykseen kuuluu oleellisesti automatisoitu testaaminen Valtaosa automatisoiduista testeistä jää yleensä kehittäjien harteille Varsinaiset testaajat keskittyvät käyttöliittymän testaamiseen, suorituskykytesteihin, toiminnallisuuden vertaamiseen määrittelyä vasten jne On siis oleellista osata kirjoittaa hyviä automatisoituja testejä jos aikoo tehdä ohjelmointityötä työkseen nykyaikana Jos osaat kirjoittaa hyviä automatisoituja testejä, niin työpaikan saaminen on kokolailla varmaa

Hieman testaussanastoa Sekaannuksien välttämiseksi kerrataan testaussanastoa Yksikkötesti On yleistä, että kaikkea automatisoituja testejä kutsutaan yksikkötesteiksi Tämä EI pidä paikkaansa! Keskustellessa uuden henkilön kanssa testauksesta on hyvä aina varmistaa, että puhutte samoilla termeillä Testi, joka testaa yhtä koodiyksikköä, kuten esimerkiksi luokkaa Integraatiotesti Testi, joka testaa useamman yksikön yhteistoimintaa Järjestelmätesti Testi, joka testaa koko järjestelmää kerralla Yleensä käyttöliittymätason testi Oikealla esitetään tyypillisimmät automatisoidut testityypit

TDD Test-driven Development Testiohjattu kehitys

Mikä TDD? Test-driven development (TDD) eli testiohjattu kehitys on ohjelmistokehitysmenetelmä, jossa kehittäjä kirjoittaa testin ennen varsinaisen toteutuskoodin kirjoittamista TDD:llä on kahdenlainen tarkoitus: Toimia matalan tason suunnittelun lähtökohtana Taata kattava testaus yksikkö- ja integraatiotestaustasolla Pääasiallisena korkeamman tason motivaationa siis laadun varmistaminen Kattavan testipatteriston avulla minimoidaan regressio ja täten muutosten tekeminen on helpompaa

TDD:n suhtautuminen perinteiseen kehitykseen Perinteinen ohjelmistokehityssykli Suunnittele Toteuta Testaa Testiohjattu ohjelmistokehityssykli Testaa Toteuta Suunnittele Test Code Refactor

Test Code Refactor Toteutus etenee lyhyissä sykleissä Syklin pituus muutamasta kymmenestä sekunnista viiteen minuuttiin Ensin kirjoitetaan testi, joka testaa yksinkertaista osuutta toteutettavasta toiminnasta Tätä testiä vasten kirjoitetaan haluttu toiminnallisuus Lopuksi refaktoroidaan sekä testiä, että sovelluskoodia mikäli sille on tarvetta Refaktoroi Toteuta Testi on TDD:ssä tapa määritellä tulevan ohjelmakoodin sisältö Testillä on siis dualistinen luonne sovelluskoodiin: se sekä määrittelee, että testaa Testaa

Refaktorointi Oleellinen osa TDD:tä on refaktorointi Refaktoroinnilla tarkoitetaan toimintaa, jolla muutetaan olemassaolevan sovelluskoodin sisäistä rakennetta muuttamatta kuitenkaan ulospäin näkyvää toiminnallisuutta public int calculatevalue(int start) { if (start < 0) { throw new InvalidParameterException(); else if (start == 0) { return 0; return (somevalue * myattributevalue) / start; public int calculateanothervalue(int start) { if (start < 0) { throw new InvalidParameterException(); else if (start == 0) { return 0; return (someanothervalue * myattributevalue) / start; Refaktorointi public int calculatevalue(int start) { if (checkstartvaluevalidity()) { return (somevalue * myattributevalue) / start; return 0; public int calculateanothervalue(int start) { if (checkstartvaluevalidity()) { return (someanothervalue * myattributevalue) / start; return 0; private boolean checkstartvaluevalidity(int value) { if (value < 0) { throw new InvalidParameterException(); else if (value == 0) { return false; return true;

Aieperustainen ohjelmointi Aieperustainen ohjelmointi (Programming by Intention) on oleellinen osa TDD:tä, vaikka ei suoraan liitykään mitenkään testaukseen Tarkoituksena on lähestyä ohjelmakoodin kehitystä black-box -ajattelulla Rajapintoja tehdessä ei mietitä toiminnallisuutta, vaan sitä miten kyseistä rajapintaa haluttaisiin käyttää Pyritään jakamaan ohjelmakoodi useisiin metodeihin/funktioihin, joiden nimet ovat mahdollisimman kuvaavia Jaottelua ei tehdä jälkikäteen, vaan ennen varsinaisen toteutuskoodin kirjoittamista Tarkoituksena on esittää ohjelmoijan aie tulevaisuuden toiminnallisuudsta

TDD:n historiaa Nykymuotoisen TDD:n alkujuuret löytyvät Extreme Programming -metodologian määritelmistä Ensimmäisen kerran esitetty erillään XP:stä Kent Beckin kirjassa Test-Driven Development by Example (Addison Wesley, 2003) TDD:n mukaista kehitystä on kuitenkin tehty jo paljon kauemmin Beck toi TDD:n uudestaan esille yhdistäessään sen osaksi XP:tä Samalla TDD sai tarkemman määrittelyn Nykyään TDD on saanut paljon huomiota myös XP:n harrastajien ulkopuolella

TDD:n monet kasvot TDD terminä on nykyisellään hyvin monikäsitteinen Aina kun puhutaan TDD:stä, täytyy myös tietää että mitä muotoa TDD:stä tarkoitetaan Roy Osherov esittää TDD:n esiintyvän neljässä eri muodossa: 1) Testiohjattu kehitys: Ajatus siitä, että kirjoitetaan testi ennen sovelluskoodia. Voidaan noudattaa olemassaolevaa arkkitehtuurisuunnitelmaa. 2) Testisuuntautunut kehitys: Testejä kirjoitetaan paljon, mutta ei välttämättä ennen sovelluskoodia. Arkkitehtuuri on yleensä selvillä ennen testin kirjoittamista. 3) Testiohjattu suunnittelu (alkuperäinen XP-tapa): Käytetään TDD:tä kokonaisvaltaisena suunnittelutyökaluna. Testit ohjaavat koko suunnitteluprosessia ja käytännössä sovellusarkkitehtuuri suunnitellaan lennossa testien ohjaamana. 4) Testiohjattu kehitys ja suunnittelu: Käytetään testit-ensin -periaatetta uuden ohjelmakoodin tuottamisen lähteenä ja samalla annetaan sen muuttaa olemassaolevaa arkkitehtuuria. Suuren linjan arkkitehtuuri on kuitenkin erikseen päätettynä paikallaan ja evolutionääriset muutokset suuntautuvat pienemmän skaalan asioihin.

TDD ja kritiikki TDD on saanut osakseen huomattavan paljon kritiikkiä Suurin osa tästä kritiikistä koskee juurikin alkuperäistä XP:n esittelemää muotoa TDD:stä Ehkä tunnetuin arvostelija on James Cope Coplien. Alkuperäinen XP:n määritelmä TDD:stä määrittelee termin emerging design, joka käytännössä tarkoittaa arkkitehtuurin kasvamista kehityksen myötä ilman etukäteissuunnittelua Tällaisella lähestymistavalla on lähinnä heikentävä vaikutus arkkitehtuuriin ja mm. VTT:llä ovat Abrahamsson ja Sinisalo tehneet tutkimusta aiheesta

Esimerkki: CurrencyConverter package fi.kilosoft.tdd; import java.math.bigdecimal; public class CurrencyConverter { public static void main (String[] args) { String amountstr = args[0]; String startingcurrency = args[1]; String targetcurrency = args[2]; CurrencyConverter converter = new CurrencyConverter(startingCurrency, targetcurrency); BigDecimal amount = converter.converttotargetcurrency(amountstr); System.out.println(amount + " " + converter.gettargettype()); private CurrencyType startingtype; private CurrencyType targettype; public CurrencyConverter(String startingcurrency, String targetcurrency) { startingtype = new CurrencyType(startingCurrency); targettype = new CurrencyType(targetCurrency); Toteutetaan CurrencyConverter -luokan käyttämä CurrencyType testiohjatusti public BigDecimal converttotargetcurrency(string amount) { BigDecimal startingamount = new BigDecimal(amount); return targettype.calculateamount(startingamount, startingtype); public CurrencyType gettargettype() { return targettype;

Esimerkki, jatkuu... @Test public void testcreatingeuro() { String eur = "EUR"; CurrencyType type = new CurrencyType(eur); assertequals(eur, type.gettypeasstring()); public CurrencyType(String type) { public String gettypeasstring() { return "EUR"; @Test public void testcreatingusdollar() { String eur = "USD"; CurrencyType type = new CurrencyType(eur); assertequals(eur, type.gettypeasstring()); private String type; public CurrencyType(String type) { this.type = type; public String gettypeasstring() { return type; private static ResourceBundle currencies; @BeforeClass public static void setupclass() { currencies = ResourceBundle.getBundle("currencies"); /** * http://en.wikipedia.org/wiki/iso_4217 */ @Test public void testvalidiso4217currenciesareaccepted() { Enumeration<String> keys = currencies.getkeys(); while (keys.hasmoreelements()) { new CurrencyType(keys.nextElement()); currencies.properties, sisältää validit valuuttatunnukset Vihreä palkki ei muutoksia toteutukseen luodaan uusi testi

Esimerkki jatkuu edelleen... @Test(expected = CurrencyConversionException.class) public void testinvalidcurrencystring() { new CurrencyType("foo"); public CurrencyType(String type) { if (type.equals("foo")) { throw new CurrencyConversionException(); @Test public void testinvalidcurrenciesthrowexception() { Enumeration<String> keys = ResourceBundle.getBundle("currencies").getKeys(); while (keys.hasmoreelements()) { String elem = keys.nextelement(); try { new CurrencyType(elem.concat("A")); fail("invalid currency type accepted"); catch (CurrencyConversionException cce) { /* all well, we got here */ try { new CurrencyType(elem.substring(1).concat("Ö")); fail("invalid currency type accepted"); catch (CurrencyConversionException cce) { /* all well, we got here */ private static final ResourceBundle currencies; Huono ratkaisu, miksi? Refaktoroidaan seuraavalla kalvolla paremmaksi static { currencies = ResourceBundle.getBundle("currencies"); public CurrencyType(String type) { if (!currencies.containskey(type)) { throw new CurrencyConversionException(); this.type = type;

Esimerkki: refaktorointia Final pois ja setter staattisen rakentajan tilalle private static ResourceBundle currencies = null; public static void setcurrencies(resourcebundle currencies) { CurrencyType.currencies = currencies; public CurrencyType(String type) { if (currencies == null) { currencies = ResourceBundle.getBundle("currencies"); if (!currencies.containskey(type.touppercase())) { throw new CurrencyConversionException(); this.type = type; NullPointerExceptionin välttämiseksi alustetaan currencies jos setteriä ei ole kutsuttu ennen olion luontia Muutos mahdollistaa joustavamman testauksen, sillä nyt CurrencyType ei ole kiinteästi riippuvainen currencies.properties -tiedoston sisällöstä voidaan simuloida helpommin niin virhetilanteita kuin oikeaa toiminnallisuuttakin

...ja esimerkin loppu @Test public void testeurotoeuroconversion() { CurrencyType start = new CurrencyType("EUR"); CurrencyType target = new CurrencyType("EUR"); BigDecimal value = target.calculateamount(new BigDecimal("100"), start); assertequals(new BigDecimal("100"), value); value = target.calculateamount(new BigDecimal("10"), start); assertequals(new BigDecimal("10"), value); public BigDecimal calculateamount(bigdecimal startingamount, CurrencyType startingtype) { if (startingtype.gettypeasstring().equals(this.gettypeasstring())) { return startingamount; return new BigDecimal("100"); @Test public void testeurotousdconversion() { CurrencyType start = new CurrencyType("EUR"); CurrencyType target = new CurrencyType("USD"); BigDecimal usdamount = new BigDecimal("100"); BigDecimal expected = usdamount.multiply(new BigDecimal(currencies.getObject("USD").toString())); BigDecimal value = target.calculateamount(usdamount, start); assertequals(expected, value); Duplikoi sovelluslogiikkaa testeihin, hyvä refaktorointikohde! Ja niin poispäin...

TDD ja CI ne yhteen sopii Jatkuva integraatio (Continuous Integration, CI) on TDD:n tehokkaalle hyödyntämiselle lähes pakollinen CI on hyödyllinen vasta jos on testejä ajettavaksi ja TDD on hyödyllinen vain jos kirjoitettuja testejä ajetaan Luonnollinen yhdistelmä Käytännössä jossain vaiheessa täysien testisettien ajaminen jatkuvasti osana TDD-sykliä muuttuu mahdottomaksi Suoritusaika kasvaa liian pitkäksi Järjestelmä/hyväksymistestivaiheen testejä ei välttämättä edes haluta tai voida ajaa kehityskoneella

ATDD Acceptance Test-driven Development Hyväksymistestivetoinen kehitys

Perinteiset määrittelyt eivät toimi Tiukat vesiputousmallin mukaiset etukäteismäärittelyt eivät ikinä kuvaa täysin sitä, mitä oikeasti halutaan Ideoita tulee matkan varrella lisää niin kehitystiimin kuin asiakkaankin suunnalta Kaikkea ei vain osata ottaa huomioon Ristiriitaisuuksia määrittelyn eri osien kohdalla on lähes aina Eri ihmiset tulkitsevat saman asian eri tavalla Ketterät menetelmät yrittävät vastata tähän ja onnistuvat osittain

Mihin agile ei sitten vastaa? Ketterät menetelmät tuovat määrittelyyn iteratiivisuuden TDD tuo iteratiivisuuden varsinaiseen kehitysprosessiin! Ketterät menetelmät eivät tuo yksikäsitteisiä määritelmiä Päinvastoin, kun määritellään vähemmän asioita kerralla joudutaan myöhemmin muuttamaan asioita Pääsääntöisesti tämä on ihan OK ja hyväksyttävää: sovelluksen laatu paranee kun hyväksytään muutoksien mahdollisuus Suureksi ongelmaksi jää kuitenkin inhimilliset tulkintaerot Tämän ongelman ratkaisemiseksi on yritetty vuosien varrella suurinpiirtein kaikkea: tiukat taulukkomuotoiset käyttötapaukset, käyttötarinat jne jne Ketterät menetelmät (varsinkin Scrum) painottavat valmiuden määritelmää antamatta kuitenkaan mitään eväitä sen määrittelemiseksi!

Vaatimukset ja testit kohtaavat Vaatimus Hyväksymistesti Toteutus Palaute Ohjataan toteutusprosessia joukolla automatisoituja ja suoritettavia hyväksymistestejä

Hyväksymistestit määrittelynä Hyväksymistestivetoinen kehitys (ATDD) on keino tehdä sovellukselle määrittely, jota vasten sovelluksen toiminnallisuus voidaan automaattisesti todeta Tulkintaeroja ei käytännössä voi tulla Perusideana on tehdä automaattisesti suoritettava testi ennen toiminnallisuuden toteuttamisen aloittamista Toiminnallisuus tehdään hyväksymistestiä vasten Kun testi menee läpi toiminnallisuus on tehty Hyväksymistestit tekee asiakas Hetkonen? Miten ei-tekninen ihminen voi tehdä teknisiä automaattisesti suoritettavia testejä?

Asiakas osana hyväksymistestausta On oleellista, että hyväksymistestien pääpihvi on nimenomaan asiakkaan tekemää Asiakas itse (yleensä) tietää parhaiten mitä haluaa Käytännössä lopullista suoritettavaa testiä ei kuitenkaan asiakas voi tehdä Työ tehdään tiiviissä yhteistyössä toimittajan määrittelijän kanssa, aivan kuten ennenkin! Asiakas voi kuitenkin tehdä perinteistä taulukkomuotoista määrittelyä vastaavan ohjeistuksen, jonka tietojen perusteella automaattinen testi voidaan suorittaa Tämän asiakas voi naputella vaikkapa tutulla ja turvallisella Wordillä tai vastaavalla työkalulla

ATDD:n prosessi Määrittelytyöryhmä luo sekä vaatimukset, että suoritettavat hyväksymistestit lyhyiden käyttötarinoiden kautta (User Stories) Mukana liiketoimintaympäristöstä, sekä teknisistä asioista ymmärtäviä henkilöitä Prosessi on jatkuva ja tapahtuu läpi projektin Suoritettavat testit määrittelevät Scrumin Product Backlogin Oleellisena erona perinteiseen hyväksymistestaukseen on asiakkaan suora osallistuminen testien tekemiseen Määrittelytyöryhmä Projektipäällikkö Asiakas Pääsuunnittelija Testausvastaava Määrittelevät Hyväksyy Toteuttaa Vaatimukset Suoritettavat testit Perusteella

ATDD:n työkalut Jotta ATDD:tä voisi käyttää tehokkaasti on sitä varten käytettävä siihen sopivia työkaluja Erilaisiin sovellusympäristöihin on olemassa omia spesifejä työkalujaan Fit, SLIM, Robot Framework... Suurimmalle osalle työkaluista yhteistä on se, että testien syötemateriaali kuvataan taulukoina Helppo lukea Helppo tulkita testikoodissa

Esimerkki (Fit) fi.kilosoft.acceptance.examplefixture change 100 from USD to EUR result should be 71.97 change 50 from SEK to EUR result should be 5.37 public boolean changefromtoresultshouldbe(int amount, String fromtype, String totype, BigDecimal shouldbe) { CurrencyConverter converter new CurrencyConverter(fromType, totype); return shouldbe.equals(converter.converttotargetcurrency(amount)); Työkalut tulkitsevat testisivujen taulukoiden sisällön Kaikki muu sisältö on vapaamuotoista Esimerkki vain yksi tapa käyttää Fit-frameworkia

Miten perustella tiimille? ATDD tuo näennäistä lisätaakkaa tiimille Todellisuudessa työmäärä pienenee koko projektin aikana Ei enää arpomista sen suhteen, että mitä tietyt lausemuodot määrittelyssä oikeasti tarkoittavat Ei enää miettimistä, että tulikohan nyt varmasti tehtyä kaikki vaadittu Kun testi menee läpi, niin vaatimuksen ominaisuudet on tehty Scrum: Definition of Done Ei enää kädenvääntöä asiakkaan kanssa, että mikä on määriteltyä toiminnallisuutta ja mikä on muutospyyntö Yhdessä ketterien menetelmien kanssa todella vahva työkalu!

Miten perustella asiakkaalle? Yhdistettynä jatkuvaan integraatioon on asiakkaalla mahdollisuus nähdä koska tahansa projektin todellinen tila Testit ovat asiakkaan itsensä hyväksymiä Testit eivät valehtele Lisää luottamusta projektin etenemiseen Väärinymmärryksien mahdollisuus pienenee koska määrittelyssä on yksi vaihe lisää, jolla varmistetaan että vaatimus on ymmärretty oikein: suoritettavan hyväksymistestin kirjoittaminen Todennäköisempää saada mitä haluaa

Ongelmat Asiakkaan opettaminen testilähtöiseen lähestymiseen voi olla työn ja tuskan takana Käytännössä asiakkaalla on pakko olla edes hitusen teknistä ymmärrystä Valitettavan usein ATDD:tä ei voida käyttää täysipainoisesti koska asiakas ei siihen suostu Tällöin määrittelyprosessi menee asiakasrajapinnassa kuten ennenkin ja määrittely muunnetaan suoritettaviksi hyväksymistesteiksi Tällöin asiakkaan varmistus testin oikeellisuudesta jää pois Eroavaisuudet perinteiseen hyväksymistestaukseen enää hyvin pienet Riippuen sovellusalustasta voi automatisoitujen järjestelmätason testien kirjoittaminen olla hyvin työlästä Esim. sulautetut järjestelmät

Luettavaa Test-Driven Development by Example, Kent Beck (Addison Wesley, 2003) Test Driven, Lasse Koskela (Manning, 2007) Bridging the Communication Gap, Gojko Adzic (Neuri Limited, 2009) Ja tietysti Google :)

Kysymyksiä, kommentteja, muita murheenaiheita?

Kiitos mielenkiinnostanne! Niklas Collin Software Architect Kilosoft Oy +358 40 058 2757 niklas.collin@kilosoft.fi