Buginmetsästystä Gitillä
Suosittu versionhallintasovellus Git on yllättävän paljon monipuolisempi työkalu kuin ehkä ensisilmäyksellä uskoisi. Git tarjoaa tuttujen perustoimintojen lisäksi komennon nimeltä bisect
. Yhdistettynä esimerkiksi automaatti- tai yksikkötestien kanssa bisect
on tehokas ja nopea tapa löytää versiohistoriasta se hetki, jolloin uusi bugi on päässyt livahtamaan mukaan koodiin.
Bisect
-komentoa apuna käyttäen voidaan analysoida muutoshistoriaa puolitushaun avulla. Puolitushaussa, eli binäärihaussa, ideana on ottaa joukko elementtejä ja jakaa ne toistuvasti kahtia ja tarkastella, löytyykö etsittävä asia valitusta osajoukosta vai ei. Tätä puolittamista tehdään niin kauan kunnes etsittävä asia on löytynyt.
Seuraavassa esimerkissä käytetään Git-komentoja:
git bisect start
git bisect bad
git bisect good
git bisect reset
Oletetaan, että meillä on versiohistoriassa toimiva tuote tagilla “v1.0”, jonka jälkeen kehitystyötä on jatkettu 17 commitin (versionhallintaan tallennetun muutosjoukon) verran ja jossain kohtaa mukaan on livahtanut ei-toivottu ominaisuus. Koodia kuitenkin on syntynyt sen verran paljon, ettei vian tarkka ajallinen paikantaminen onnistu yksinkertaisesti koodia silmäilemällä.
Aloitetaan metsästys komentamalla git bisect start
. Komento aktivoi Gitin haarukointimoodin.
Seuraavaksi kerrotaan Gitille, että nykytilanne on huono: git bisect bad
.
Tähän asti Git on ollut kiltisti hiljaa, eikä ole viestinyt käyttäjälle mitenkään, että jotain erikoista olisi tapahtumassa.
Lopuksi kerromme, mikä on viimeinen tunnettu toimiva versio, meidän tapauksessamme tagi “v1.0”: git bisect good v1.0
.
Nyt Git kertoo meille arvionsa, miten monella askeleella viallinen versio saatetaan löytää:
Bisecting: 8 revisions left to test after this (roughly 3 steps)
Lisäksi Git kertoo, mikä versio historiasta on nostettu aktiiviseksi. Tätä versiota vasten suoritetaan tarvittavat käännösoperaatiot ja ajetaan testit, joilla bugi voidaan havaita.
Oletetaan, että tässä tapauksessa valittu versio sisältää etsimämme bugin: git bisect bad
.
Git kertoo päivitetyn tilanteen:
Bisecting: 3 revisions left to test after this (roughly 2 steps)
Ja taas Git raportoi versiosta, joka on nostettu historiasta testattavaksi.
Pikaisen testauksen jälkeen havaitsemme, ettei tässä versiossa ole mitään vikaa ja kerromme sen Gitille: git bisect good
.
Git antaa jälleen tilannepäivityksensä:
Bisecting: 1 revision left to test after this (roughly 1 step)
Testataan ja todetaan tämänkin version olevan hyvä: git bisect good
.
Bisecting: 0 revisions left to test after this (roughly 0 steps)
Annetusta statistiikasta näemme, että olemme osumassa nyt naulan kantaan. Nopea testaus ja todetaan, että tämä versio on buginen: git bisect bad
.
Nyt Git avaa sanaisen arkkunsa ja kertoo meille, missä versiossa bugi ensimmäistä kertaa esiintyy ja antaa tarkemmat tiedot version SHA-tunnisteesta, tekijästä, päiväyksestä, commit-viestin sekä listan tiedostoista, jotka ovat tässä versiossa muuttuneet.
Olemme löytäneet hetken, jolloin bugi on luiskahtanut mukaan koodiin!
Lopuksi, nyt kun bugi on paikannettu ja toivottavasti ymmärretty miten se korjataan, kerrotaan Gitille, että metsästys on ohi ja voimme palata normaaliin päiväjärjestykseen: git bisect reset
. Git palauttaa versionhallinnan tilan siihen, jossa oltiin ennen kuin git bisect start
-komento ajettiin.
Kuten äskeinen esimerkki havainnollistaa, on Git bisect
näppärä tapa tilanteissa, joissa tiedetään, ettei ohjelma toimi halutulla tavalla, mutta ei välittömästi ole selvää, missä vika on pitkäksi kasvaneen muutoshistorian vuoksi. Edellisessä esimerkissä 17 erillisen muutoksen testaamisen sijasta selvittiin vain neljällä testikierroksella ja vika löytyi lopulta seitsemännestä muutoksesta.
Jos kiinnostus bisect
-komentoon heräsi, voi aiheeseen syventyä lisää vaikkapa perehtymällä git bisect run
-komentoon. Bisect run
mahdollistaa virheen etsinnän automatisoinnin ja avaa mielenkiintoisia uusia ovia testiautomaatiolle.
Lisää luettavaa:
Kirjoittaja on Ouron Senior Developer Matti Kärki