Apua tehtävien tekoon kurssin Discord-kanavalla sekä zoom-pajassa:
- Torstaisin klo 14-16 tällä linkillä
Tämän viikon tehtävissä harjoitellaan ensin muutaman tärkeän ohjelmistokehityksen työkalun (komentorivi, versionhallinta, riippuvuuksien hallinta, automatisoitu testaus, jatkuva integraatio) käyttöä.
Laskarien lopuksi harjoitellaan riippuvuuksien injektointia joka on melko simppeli mutta erittäin käyttökelpoinen tekniikka, jonka avulla sovellusten testattavuutta on mahdollista parantaa.
Typoja tai epäselvyyksiä tehtävissä?
Tee korjausehdotus editoimalla tätä tiedostoa GitHubissa.
Tehtävien palauttaminen
Tehtävät palautetaan GitHubiin, sekä merkitsemällä tehdyt tehtävät palautussovellukseen https://study.cs.helsinki.fi/stats/courses/ohtu-avoin-2022. Käytännössä tällä viikolla tehdään palautusta varten kaksi erillistä GitHub-repositoria, ensimmäinen tehtäviä 2-13 varten ja toinen tehtäviä 14-16 varten. Jos et vielä tiedä mikä on GitHub ja repositorio, niin pian opit.
Tehtävää 1 ei varsinaisesti palauteta minnekään.
1. Komentorivi
Graafisten käyttöliittymien olemassaolosta huolimatta ohjelmistoalalla on edelleen erittäin tärkeää hallita komentorivin eli terminaalin käyttö. Itse asiassa komentorivin merkitys on jopa nousussa.
Varmista, että osaat käyttää “riittävästi” komentoriviä (ks. alla oleva lista).
Jos osaamisessasi on puutteita (ks. alla oleva lista) kertaa haluamastasi resurssista:
- https://www.codecademy.com/learn/learn-the-command-line online-kurssin kaksi ensimmäistä osaa Navigating the File System ja Viewing and Changing the File System
- https://ryanstutorials.net/linuxtutorial/ oppaasta 4 osaa: 1. The Command Line, 2. Basic Navigation, 3.More About Files ja 5. File Manipulation
Myös kurssin Tietokone työvälineenä tämän syksyn komentorivimateriaali käsittelee myös suurta osaa tehtävän komennoista.
HUOM. Codecademy vaatii kirjautumisen Facebook, Google tai GitHub -tunnuksella. Kurssilla käytetään muutenkin GitHubia, eli se tunnus pitäisi kaikilla olla olemassa, jotta pääsee kirjautumaan.
Tämän tehtävän jälkeen sinun tulisi hallita seuraavat asiat:
- Käsitteet
- Root directory
- Home directory
- Parent directory
- Child directory
- Working directory
..
ja\*
- Ja osata käyttää komentoja
pwd
cd
ls
,ls -a
,ls -l
,ls -t
mkdir
touch
cp
rm
,rm -r
mv
Tulet tarvitsemaan komentorivin käyttötaitoja tällä kurssilla ja muutenkin opinnoissasi.
Tehtävää ei palauteta mitenkään. Voit merkitä tehtävän tehdyksi kun osaat yllä luetellut asiat.
2. GitHubiin (versionhallinta)
Jos sinulla ei jostain syystä ole vielä tunnusta GitHubiin, luo se nyt.
Luo githubiin repositorio nimellä ohtu-2022-viikko1
- Klikkaa yläpalkin oikeassa reunassa olevaa “Create a new repo”-ikonia
- Laita rasti kohtaan Initialize this repository with a README
Jos et ole vielä luonut koneellesi ssh-avainta, tee se nyt
- Ohje avaimen luomiseen esim. täällä. Riittää että teet stepit 1 ja 2 tai kurssin Ohjelmistotekniikka-materiaalista
Lisää julkinen avain githubiin:
Näin pystyt käyttämään GitHubia ilman salasanan syöttämistä koneelta, josta juuri luodun avaimen salainen pari löytyy
Jos et ole jo aiemmin niin tehnyt, konfiguroi nimesi ja email-osoitteesi paikallisen koneesi git:iin antamalla komennot:
git config --global user.name "Your Name"
git config --global user.email my.address@gmail.com
Oletuseditoriksi kannattaa Linuxilla ja macOS:lla konfiguroida nano:
git config --global core.editor nano
ja Windowsilla notepad:
git config --global core.editor notepad
Tosin jos olet vimin käyttäjä, voit jättää edellisen tekemättä.
Kloonaa nyt githubiin tehty repositorio paikalliselle koneelle. Tämä tapahtuu antamalla komentoriviltä komento:
git clone git@github.com:omatunnustahan/ohtu-2022-viikko1.git
missä komennon git clone
parametrina on repositoriosi sivulla näkyvä merkkijono (huomaa, että formaatin on oltava SSH):
Nyt paikalliselle koneellesi syntynyt hakemisto ohtu-2022-viikko1 (hakemiston nimi on sama kuin repositoriosi), joka on on GitHubissa olevan repositorion klooni.
3. Gitin alkeet (versionhallinta)
Olet jo todennäköisesti käyttänyt Gitiä aiemmilla kursseilla. Tässä tehtävässä harjoitellaan seuraavia komentoja:
git add
git commit
git status
git checkout -- file
-
git reset HEAD
- Jos et vielä hallitse komentoja, käy läpi kurssin Ohjelmistotekniikka Git-tutoriaali. Pelkän lukemisen sijaan kannattanee myös tehdä itse tutoriaalin git-operaatiot.
Lisää git-ohjeita löytyy runsaasti internetistä, esim:
- Pro Git -opas, kannattaa lukea näin alkuun luku 2
- Githubin helpit
- https://www.atlassian.com/git/tutorials
- https://we.riseup.net/debian/git-development-howto
- http://www.ralfebert.de/tutorials/git/
Tee nyt seuraavat:
- Mene edellisessä tehtävässä luotuun repositorion klooniin (eli komennon
git clone
luomaan hakemistoon) - Lisää ja committaa repositorioon kaksi tiedostoa ja kaksi hakemistoa, joiden sisällä on tiedostoja
- Muista hyödyllinen komento
git status
- Muista hyödyllinen komento
- Muuta ainakin kahden tiedoston sisältöä ja committaa muutokset repositorioon
- Tee .gitignore-tiedosto, jossa määrittelet, että repositorion juurihakemistossa olevat tiedostot, joiden pääte on tmp ja hakemistot joiden nimi on __pycache__ ja .pytest_cache ignoroidaan
- Toinen ignoroitava hakemisto on siis .pytest_cache, jonka nimi alkaa pisteellä
- Pistealkuiset hakemistot ja tiedostot eivät näy oletusarvoisesti komennon
ls
listauksissa, saat ne näkyville komennollals -a
- Lisää tmp-päätteisiä tiedostoja hakemistoon ja varmista että git jättää ne huomioimatta
- Saat asian tarkastettua komennolla
git status
- Saat asian tarkastettua komennolla
- Lisää myös hakemisto nimeltä __pycache__ ja hakemiston sisälle joku tiedosto. Varmista että hakemisto sisältöineen ei mene versionhallinnan alaisuuteen
- Lisää ja commitoi .gitignore-tiedosto repositorioosi
- Tee muutos johonkin tiedostoon. Älä lisää tiedostoa “staging”-alueelle
- Peru muutos (
git status
-komento antaa vihjeen miten tämä tapahtuu)
- Peru muutos (
- Tee muutos ja lisää tiedosto “staging”-alueelle
- Peru muutos (
git status
-komento antaa vihjeen miten tämä tapahtuu)
- Peru muutos (
git add -p
- Tutoriaaleissa ei valitettavasti käytetä
git add
-komennon hyödyllistä muotoagit add -p
- Tee muutoksia muutamiin tiedostoihin ja lisää muutokset staging-alueelle komennon git add -p avulla
- Jos lisäät projektiin uusia tiedostoja, ei
git add -p
huomaa niitä, eli ne on lisättävä staging-alueelle erikseen - Käytä jatkossa komentoa
git add -p
aina kun se on suinkin mahdollista!
komennolla man git add
saat lisätietoa optiosta ja mm. vastausvaihtoehtojen selitykset.
4. Tiedostojen lisääminen GitHubiin (versionhallinta)
Tehtävässä 2 tehtiin GitHubiin repositorio, joka liitettiin paikalliselle koneelle luotuun repositorioon “remote repositoryksi”. Synkronoidaan paikallisen repositorion ja githubin tilanne:
- “Pushaa” nämä GitHubissa olevaan etärepositorioon antamalla komento
git push
- Varmista selaimella, että lisätyt tiedostot menevät GitHubiin
GitHubissa pitäisi näyttää suunilleen seuraavalta
5. Monta kloonia samasta repositoriosta (versionhallinta)
Yleensä on tapana pitää GitHubissa olevaa repositorioa tiedostojen “keskitettynä” sijoituspaikkana ja liittää paikallisella koneella oleva repositorio GitHubissa olevan repositorion etärepositorioksi, kuten teimme tehtävässä 1.
Jos työskennellään useammalta koneelta, on githubissa olevasta repositoriosta monta kloonia ja kloonien tila on pidettävä ajantasalla.
Luodaan nyt harjoituksen vuoksi paikalliselle koneelle repositoriosta toinen klooni:
- Mene komentoriville ja esim. kotihakemistoosi (tai johonkin paikkaan, joka ei ole git-repositorio)
- Anna komento
git clone git@github.com:githubtunnus/repositorionNimi.git nimiKloonille
- githubtunnus ja repositorionNimi selviävät GitHubista repositoriosi tehtävän 2 toisen kuvan osoittamasta paikasta
- nimiKloonille tulee olemaan kloonatun repositorion nimi, varmista että annat nimen, jonka nimistä tiedostoa tai hakemistoa ei jo ole kansiossa
- Mene kloonattuun repositorioon ja lisää sinne jotain tiedostoja. Committaa lopuksi
- “Pushaa” muutokset GitHubiin
- Varmista selaimella, että lisätyt tiedostot menevät GitHubiin
Mene nyt tehtävässä 1 tehtyyn GitHub-repositorion klooniin.
- Alkuperäinen paikallinen klooni ei ole enää ajantasalla, “pullaa” sinne muutokset komennolla
git pull
- Varmista että molempien paikallisten repositorioiden sisältö on nyt sama
- Lisää alkuperäiseen kopioon joitain tiedostoja ja pushaa ne GitHubiin
- Mene jälleen kloonattuun kopioon ja pullaa
6. Repositorion siivous (versionhallinta)
Valmistaudutaan seuraavaan tehtävään siivoamalla repositoriostamme ylimääräiset tiedostot
- Mene repositoriosi alkuperäiseen, tehtävässä 2 tekemääsi klooniin
- Voit poistaa tehtävää 5 varten tekemäsi harjoituskloonin
- Poista repositorioistasi kaikki hakemistot sekä muut tiedostot paitsi .gitignore ja README.md
- Committaa muutokset
- Varmista komennolla git status että kaikki muutokset ovat versionhallinnassa, eli että git ei ilmoita joidenkin tiedostojen olevan Changes not staged for commit
- Joudut ehkä kertaamaan tehtävän 3 linkittämistä tutoriaaleista sitä miten tiedostojen poistaminen gitistä tapahtuu
- Pushaa muutokset githubiin. Katso selaimella, että GitHubissa kaikki on ajan tasalla, eli että repositoriossa ei ole mitään muuta kuin tiedostot .gitignore ja README.md
Haetaan sitten seuraavissa tehtävissä käytettävä koodi:
- Hae osoitteesta https://github.com/ohjelmistotuotanto-hy-avoin/python-kevat-2022/blob/master/koodi/viikko1/varasto.zip?raw=true löytyvä zipattu paketti
- Pura paketti sopivaan paikkaan
- Siirrä paketin sisällä olevat tiedostot kloonattuun repositorioon siten, että paketissa olevat tiedostot ja hakemistot tulevat repositorion juureen
- Repositoriosi sisältävän hakemiston tulee nyt näyttää seuraavalta
- Lisää ja committoi zipistä puretut tavarat repositorioosi ja pushaa ne GitHubiin
- Katso vielä kerran selaimella, että GitHubissa kaikki on ajan tasalla
Huomaa, että repositoriosi tulee näyttää tehtävän jälkeen suunnilleen seuraavalta:
Jos hakemisto src ja tiedostot pyproject.toml ym. eivät ole repositorion juuressa, siirrä ne sinne ennen kuin siirryt eteenpäin.
7. Poetry
Tämän kurssin ohjelmointitehtävissä käytetään Pythonia. Python asennuksen löytymisen koneeltasi voit tarkistaa komennolla:
python3 --version
Jos Python on asennettu, komennon suorittaminen tulostaa asennetun Pythonin version. Varmista, että käytössä oleva versio on vähintään 3.8.0. Jos python3
-komentoa ei löydy, kokeile komentoa python
. Varmista kuitenkin, että python
-komento suorittaa tarpeeksi uutta versiota. Jos asennusta ei löydy, tai käytössä on vanhempi versio, seuraa ohjelmointikurssien ohjeita Pythonin asentamiselle.
Asennusohjeista löytyy myös ohjeet Visual Studio Code -editorin asentamiselle. Kurssin tehtäviä ei kuitenkaan palauteta TMC-liitännäisen avulla, joten VS Code -liitännäinen ei ole välttämätön kurssin suorittamiselle. Voit siis halutessasi käyttää kurssilla myös mitä tahansa muuta editoria.
Ohjelmoinnin peruskursseilla olet saattanut suorittaa koodia painamalla VS Coden nuoli-painiketta, ja testejä painamalla silmä-painiketta. Ammattimaisessa ohjelmistokehityksessä koodin suorittaminen ja testaamisen on tapahduttava toistettavalla tavalla, ja siten että operaatiot pystytään suorittamaan millä tahansa koneella, skriptatusti komentoriviltä, eli riippumatta VS Coden kaltaisista kehitysympäristöistä.
Koodin suorittaminen komentoriviltä python3
-komennolla ei itsessään ole kovin hankalaa. Ongelmia alkaa syntyä vasta, kun projekti tarvitsee ulkoisia riippuvuuksia erilaisten asennettavien kirjastojen muodossa. Kirjastojen asennukseen ja hallintaan tarvitaan erilisiä työkaluja. Pythonin kohdalla suosituin komentorivityökalu tähän tarkoitukseen on pip.
Jotta samalla tietokoneella olevien projektien riippuvuuksissa ei syntyisi ristiriitoja, on käytössä usein niin kutsuttuja projektikohtaisia virtuaaliympäristöjä. Näitä virtuaaliympäristöjä luodaan ja käytetään venv-moduulin kautta. Jotta saisimme helposti käyttöömme pipin ja virtuaaliympäristön tuomat edut, voimme käyttää Poetry-komentorivityökalua. Poetryn dokumentaation antama kuvaus on seuraava:
Poetry is a tool for dependency management and packaging in Python. It allows you to declare the libraries your project depends on and it will manage (install/update) them for you.
- Edellisessä tehtävässä lisättiin repositorioon Poetry-muodossa oleva varasto-projekti. Projekti sisältää erittäin yksinkertaisen varaston hallintaan soveltuvaa koodia. Varaston hallinnasta vastaa src/varasto.py-tiedossa määritelty luokka
Varasto
. Luokkaa käyttää src/index.py-tiedossa määritelty funktiomain
- Tutki Poetry-muotoisen projektin hakemistorakennetta esim. antamalla komento
tree
projektin sisältävän hakemiston juuressa (tree
ei ole Poetryyn liittyvä käsky vaan normaali shell-komento)- Windowsissa komennosta käyttökelpoisin muoto on
tree /F
Jos käytössäsi on Windowsissa git bash komento on muotoacmd //c tree
- HUOM: macOS:ssä ei ole oletusarvoisesti
tree
-komentoa - Mikäli koneellasi on Homebrew asennettuna, saat
tree
-komennon asennettua komennollabrew install tree
- Myöskään kaikissa Linuxeissa ei komento
tree
ole oletusarvoisesti asennettu. Debian-pohjaisissa Linuxeissa (esim Ubuntussa) saat asennettuatree
-komennon komennollasudo apt-get install tree
- Windowsissa komennosta käyttökelpoisin muoto on
- Tarkastele projektin määrittelevän tiedoston pyproject.toml sisältöä
- Tiedosto määrittelee mm. projektin käyttämät riippuvuudet
- Tarkastele juurihakemistossa olevan poetry.lock-tiedoston sisältöä
- Tiedoston sisällön ei ole tarkoitus olla ihmisluettava, eikä sitä pitäisikään missään nimessä muokata. Tiedosto on täysin Poetryn ylläpitämä. Poetry tallentaa tiedostoon projektiin asennettujen riippuvuuksien versiot, jotta jokaisen asennuksen yhteydessä riippuvuuksista voidaan asentaa juuri oikeat versiot
Ohjelmakoodin editointi kannattaa tehdä järkevällä editorilla, esim. Visual Studio Codella, mutta Poetry-komentojen suorittaminen onnistuu helpoiten komentoriviltä. Ennen siirtymistä tehtävien pariin, tutustu Poetryn asennus- ja käyttöohjeisiin lukemalla Ohjelmistotekniikka-kurssin Poetry-ohje.
Tee nyt seuraavat toimenpiteet. Ohjeen kaikissa kohdissa Poetry-komennot on annettu muodossa poetry <komento>
.
- Asenna varasto-projektin riippuvuudet suorittamalla sen juurihakemistossa komento
poetry install
- Käynnistä sovellus komennolla
poetry run python3 src/index.py
- Run-komento suorittaa annetun komennon (tässä tapauksessa
python3 src/index.py
) virtuaaliympäristössä
- Run-komento suorittaa annetun komennon (tässä tapauksessa
- Siirry virtuaaliympäristöön komennolla
poetry shell
- Suorita komento
python3 src/index.py
- Virtuaaliympäristössä komentoja voi suorittaa “normaalisti”, eli ilman
run
-komentoa - Kun uutta koodia kehitetään ja suoritetaan tiheissä sykleissä, on komentojen suorittaminen kätevintä tehdä virtuaaliympäristön sisällä
- Virtuaaliympäristössä komentoja voi suorittaa “normaalisti”, eli ilman
- Lähde virtuaaliympäristöstä komennolla
exit
- Suorita testit komennolla
poetry run pytest
- Testien suorittamista varten on käytössä pytest-sovelluskehys
HUOM jos törmäät seuraavaan virheilmoitukseen
Python 2.7 will no longer be supported in the next feature release of Poetry (1.2).
You should consider updating your Python version to a supported one.
Note that you will still be able to manage Python 2.7 projects by using the env command.
See https://python-poetry.org/docs/managing-environments/ for more information.
The currently activated Python version 2.7.16 is not supported by the project (^3.8).
Trying to find and use a compatible version.
eräs tapa korjata tilanne Macilla ja ehkä myös Linuxilla on editoida tiedoston ~/.poetry.bin/poetry
ensimmäisellä rivillä mainittu pythonin polku. Oletusarvoinen polku on todennäköisesti seuraava
#!/usr/bin/python
Polku tulee Macilla muuttaa (todennäköisesti) muotoon
#!/usr/local/bin/python3
Oikea polku kannattaa varmistaa komennolla which python3
.
8. Unittest
Ohjelmistokehityksen ehkä tärkein vaihe on laadunvarmistus, laadunvarmistuksen tärkein keino taas on testaus, joka on syytä automatisoida mahdollisimman pitkälle, sillä ohjelmistoja joudutaan testaamaan paljon. Erityisesti iteratiivisessa/ketterässä ohjelmistokehityksessä samat testit on suoritettava uudelleen aina ohjelman muuttuessa.
Python-maailmassa automatisoidun testaamisen johtava työkalu on unittest, johon olet todennäköisesti jo tutustunut kurssilla Ohjelmistotekniikka. Jos unittest on vieras, tai päässyt unohtumaan, kertaa sen perusteet kurssin Ohjelmistotekniikka unittest-ohjeesta.
Edellisen tehtävän esimerkkisovelluksessa on jo jonkun verran unittest-testejä, laajennetaan nyt testejä.
Muista, että testit voi suorittaa projektin juurihakemistossa komennolla poetry run pytest
tai siirtymällä virtuaaliympäristöön komennolla poetry shell
ja suorittamalla sen jälkeen komennon pytest
.
- Täydennä varasto-projektin testejä siten, että luokan
Varasto
testien haarautumakattavuudeksi (branch coverage) tulee 100%- Joudut huomioimaan ainakin tapaukset, joissa varastoon yritetään laittaa liikaa tavaraa ja varastosta yritetään ottaa enemmän kuin siellä on
- Edellinenkään ei vielä riitä
- Testauksen rivikattavuuden saat selville coverage-työkalun avulla. Tutustu työkaluun lukemalla Ohjelmistotekniikka-kurssin Coverage-ohje
- Ota työkalu projektissasi käyttöön asentamalla se projektin kehityksen aikaiseksi riippuvuudeksi komennolla:
poetry add coverage --dev
- Lisää projektin juurihakemistoon konfiguraatiotiedosto .coveragerc, jossa kerrotaan, mistä projektin tiedostoista testikattavuutta kerätään. Tiedoston sisällön tulee olla seuraava:
[run]
source = src
- Siirry virtuaaliympäristöön komennolla
poetry shell
- Suorita komento
coverage run --branch -m pytest
. Komento suorittaa testit ja kerää testien haarautumakattavuuden - Tämän jälkeen suorita komento
coverage html
. Komento muodostaa raportin kerättyjen tietojen perusteella
- Suorita komento
- Projektin juurihakemistoon pitäisi ilmestyä hakemisto htmlcov. Voit tarkastella HTML-muotoista testikattavuusraporttia avaamalla selaimessa htmlcov hakemiston index.html-tiedoston
- Klikkaamalla raportista yksittäisen tiedoston nimeä näet, mitkä koodin suorituksen haarat on vielä testaamatta
- Lisää projektin .gitignore-tiedostoon tiedosto .coverage ja hakemisto htmlcov
- Kun luokan
Varasto
(tiedoston src/varasto.py) testien haarautumakattavuus (branch coverage) on 100%, pushaa tekemäsi muutokset GitHubiin- Raportissa on luultavasti mukana myös muita tiedostoja, mutta ainoastaan src/varasto.py-tiedoston haarautumakattavuus tarvitsee olla 100%. Opimme myöhemmin, kuinka ylimääräiset tiedostot pystyy jättämään raportin ulkopuolelle
- Kun muokkaat testejä, muista suorittaa komennot
coverage run --branch -m pytest
jacoverage html
uudelleen, jotta raportti päivittyy - Saat suoritettua molemmat komennot “yhdellä napin painalluksella” sijoittamalla ne samalle riville puolipisteellä eroteltuna
coverage run --branch -m pytest; coverage html
9. GitHub Actions, osa 1
Poetryn avulla testien suorittaminen on mahdollista tehdä skriptattavaksi, eli komentoriviltä helposti suoritettavaksi. Seuraava askel on suorittaa buildausprosessi, eli ohjelman suorittamiseen vaadittavat toimenpiteet ja siihen liittyvien testien suoritus, erillisellä build-palvelimella (engl. build server).
Ideana on, että ohjelmistokehittäjä noudattaa seuraavaa sykliä:
- Uusin versio koodista haetaan versionhallinnan keskitetystä repositoriosta ohjelmistokehittäjän koneelle
- Lisäykset ja niitä testaavat testit tehdään paikalliseen kopioon
- Testit suoritetaan paikalliseen kopioon ohjelmistokehittäjän työasemalla
- Jos kaikki on kunnossa, paikalliset muutokset lähetetään keskitettyyn repositorioon
- Build-palvelin seuraa keskitettyä repositoriota ja kun siellä huomataan muutoksia, hakee ja kääntää build-palvelin muuttuneen koodin ja suorittaa sille testit
- Build-palvelin raportoi havaituista virheistä
Erillisen build-palvelimen avulla varmistetaan, että ohjelmisto toimii muuallakin kuin muutokset tehneen ohjelmistokehittäjän koneella. Tätä käytännettä kutsutaan jatkuvaksi integraatioksi (engl. continuous integration). Palaamme asiaan tarkemmin kurssin kolmannessa osassa.
Nykyään alkaa olla yleistä, että erillisen build-palvelimen sijaan käytetään jotain verkossa olevaa “build-ohjelmistoa”, jolloin softakehittäjien ei tarvitse huolehtia ollenkaan buildaukseen käytettävän palvelimen ja sen ohjelmistojen asentamisesta.
Kurssilla käytetään GitHubiin 15.11.2019 julkaistua ja sen jälkeen nopeasti suuren suosion saavuttanutta Actions-ominaisuutta hoitamaan automatisoitu buildaus.
Konfiguroidaan seuraavaksi GitHub Actions huolehtimaan projektistamme.
Valitse GitHub-repositoriostasi välilehti Actions ja klikkaa set up a workflow yourself-linkkiä:
Valinta avaa actionien konfiguraatiotiedoston. Muuta se seuraavaan muotoon:
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install Poetry
run: pip install poetry
- name: Install dependencies
run: poetry install
- name: Run tests
run: poetry run coverage run --branch -m pytest
Paina vihreää Start commit -nappia, ja anna sopiva commit-viesti.
Konfiguraatiotiedosto (jonka nimi on oletusarvoisesti main.yml) tallettuu repositorioosi hakemiston .github/workflows alle:
GitHub siis committoi uuden tiedoston automaattisesti repositorioosi.
Kun nyt pullaat repositorion koodin omalle koneellesi, näkyy konfiguraatiotiedosto myös siellä, esim. Visual Studio Code -editorilla se näyttää seuraavalta:
Kun avaan nyt repositorion välilehden Actions, huomaat että sinne on ilmestynyt hieman tavaraa:
10. GitHub Actions, osa 2
Katsotaan hieman tarkemmin mitä GitHub actionien konepellin alla tapahtuu.
GitHub actionit ovat sarjoja erilaisia “toimenpiteitä”, joita GitHub voi suorittaa repositoriossa olevalle koodille. Actionin toiminta määritellään hakemiston .github/workflows sijoitettavissa .yml-päätteisissä tiedostoissa.
Tarkastellaan äsken määrittelemäämme tiedostoa:
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install Poetry
run: pip install poetry
- name: Install dependencies
run: poetry install
- name: Run tests
run: poetry run coverage run --branch -m pytest
Kohta on määrittelee missä tilanteissa actionit suoritetaan. Konfiguraatiomme määrää, että actionit suoritetaan aina kun repositorion päähaaraan pushataan koodia (sekä silloin jos päähaaraan tehdään ns. pull request).
Osiossa jobs voidaan määritellä yksi tai useampi “työ”, eli useasta askeleesta koostuva tehtäväsarja. Määrittelimme tällä kertaa vain yhden työn, jolle annoimme nimen build. Jos töitä olisi useita, suorittaisi GitHub actions ne yhtä aikaa.
Yksittäinen työ koostuu useista askelista, jotka on määritelty työn alla kohdassa steps.
GitHub varaa työn askelien suorittamista varten virtuaalikoneen. Kohta runs-on määrittelee minkälaisella käyttöjärjestelmällä työn askeleet suoritetaan. Esimerkkimme tapauksessa suoritusympäristö on Ubuntu Linux.
Esimerkkimme tapauksessa työ koostuu viidestä askeleesta. Ensimmäinen askel
- uses: actions/checkout@v2
suorittaa valmiiksi määritellyn actionin checkout, joka dokumentaationsa mukaan tekee seuraavaa
This action checks-out your repository under $GITHUB_WORKSPACE, so your workflow can access it.
Eli checkout action siis hakee repositorion koodin askeleet suorittavalle virtuaalikoneelle.
Toinen askel on action setup-python, joka asentaa työn suorittavalle virtuaalikoneelle haluamamme Python-version.
Molemmat näistä actioneista olivat GitHubin marketplacesta löytyviä valmiita actioneja. Esim. Pythonin asentaminen työn suorittavalle virtuaalikoneelle on itsessään aika monimutkainen toimenpide, mutta valmiiksi määritelty action tekee sen helpoksi.
Kolmas askel on hieman erilainen:
- name: Install Poetry
run: pip install poetry
Se suorittaa komentorivillä komennon, joka asentaa Poetryn.
Neljäs askel asentaa projektin riippuvuudet poetry install
-komennolla.
Viides askel on kaikkein tärkein, se suorittaa poetryn avulla projektin testit ja kerää testikattavuuden:
- name: Run tests
run: poetry run coverage run --branch -m pytest
Tee nyt koodiin muutos, joka hajottaa testit ja committaa muutos GitHubiin.
Hetken kuluttua actions-välilehdellä pitäisi näkyä että commiteja on kaksi (kuvassa niitä on vahingossa kolme), ja että viimeisin on tilaltaan “punainen”:
Klikkaamalla rikki mennyttä committia, päästään tarkastelemaan hieman tarkemmin actionin suorituksen etenemistä:
Kuten odotettua, testi ei mennyt läpi. Riippuen GitHubin asetuksista, olet myös saattanut saada email-muistutuksen rikki menneestä buildista.
Korjaa testi ja pushaa muutokset uudelleen GitHubiin. Tarkkaile jälleen Actions-näkymää ja varmista, että kaikki toimii oikein.
11. GitHub Actions, osa 3
Laita repositiossa olevaan tiedostoon README.md koodin tilasta kertova Status Badge.
Tämän ohjeen mukaan badgen osoite on muotoa
https://github.com/<OWNER>/<REPOSITORY>/workflows/<WORKFLOW_NAME>/badge.svg
WORKFLOW_NAME on määritelty konfiguraatiotiedostossa:
name: CI
on:
push:
branches: [main]
# ...
Olemme käyttäneet nimeä CI, nimi voi kuitenkin olla mikä vaan.
Esimerkiksi omassa tapauksessani badgelinkki on
https://github.com/Kaltsoon/ohtu-2021-viikko1/workflows/CI/badge.svg
Lisää badge editoimalla tiedostoa README.md suoraan GitHubissa:
Oikein toimiva badge näyttää seuraavalta:
Badge toimii siis sen indikaattorina onko repositoriossasi oleva koodi testien puolesta kunnossa!
Tee nyt jokin muutos koneellasi repositorioon ja yritä pushata koodi GitHubiin. Toimenpiteestä seuraa virhe:
To github.com:mluukkai/ohtu-viikko1-s2020.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to 'git@github.com:mluukkai/ohtu-2021-viikko1.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Tulet todennäköisesti törmäämään vastaavaan virheeseen usein. Syynä virheelle on se, että yrität pushata muutoksia GitHubiin vaikka GitHub on “edellä” paikallista repositorioasi (ts. sinne lisättiin tiedosto README.md).
Ongelma ratkeaa, kun teet ensin komennon git pull
ja pushaat koodin vasta sen jälkeen.
Pullauksen yhteydessä syntyy ns. merge commit ja git avaa oletuseditorisi ja haluaa että määrittelet commit messagen. Jos et ole muuttanut gitin käyttämää oletuseditoria, on käytössä vim joka toimii hieman erilaisilla periaatteilla kuin monet muut editorit. Joudut ehkä googlaamaan että pääset vimistä ulos…
12. Codecov
Tehtävässä 8 määrittelimme projektin testauskattavuuden coveragen avulla. https://codecov.io -palvelu mahdollistaa projektien koodikattavuuden julkaisemisen verkossa.
- Kirjaudu Codecoviin (GitHub login)
- Lisää repositorio Codecoviin alaisuuteen:
Saatat joutua odottamaan hetken, ennen kuin Codecov löytää repositoriosi. Jos pieni odottelukaan ei auta, voit mennä suoraan repositoriosi Codecov-osoitteeseen, joka on muotoa https://codecov.io/gh/githubtunnus/repositorio, omassa tapauksessani siis https://codecov.io/gh/Kaltsoon/ohtu-2021-viikko1
Saamme muodostettua Codecovin ymmärtämän testikattavuusraportin käyttämällä coverage html
-komennon sijaan komentoa coverage xml
. Kyseinen komento muodostaa XML-muotoisen testikattavuusraportin. Lisätään konfiguraatiomme loppuun kaksi uutta askelta:
- name: Coverage report
run: poetry run coverage xml
- name: Coverage report to Codecov
uses: codecov/codecov-action@v2
HUOM1 rivit on sisennettävä samalle tasolle kuin muut stepit.
HUOM2 et tarvitse Codecovin tarjoamaa upload tokenia mihinkään:
Käytämme raportin lähettämisessä Codecoviin actionia codecov-action. Kun seuraavan kerran pushaamme koodin GitHubiin, ilmestyy Codecoviin koodin testikattavuusraportti:
Klikkailemalla sivun alalaidassa olevasta kohdasta Files tiedostojen nimiä, pääset katsomaan yksittäisten luokkien testauksen kattamat rivit:
Käytännössä pyydämme nyt GitHub actioneja suorittamaan ensin testit ja keräämään testikattavuuden (komennolla poetry run coverage run --branch -m pytest
), jonka jälkeen muodostetaan XML-muotoinen testikattavuusraportti (komennolla poetry run coverage xml
). Tämä testikattavuusraportti lähetetään Codeviin.
GitHub actionien loki näyttää miten askelten suoritus etenee:
Lisää repositoriosi README.md-tiedostoon myös Codecov-badge. Löydät badgen Codecovin settings-valikosta.
Projektisi GitHub-sivun tulisi lopulta näyttää suunnilleen seuraavalta:
Huomaa, että GitHub actionin ja Codecovin badget eivät päivity täysin reaaliajassa. Eli vaikka projektin testikattavuus nousisi, kestää hetken, ennen kuin badge näyttää tuoreen tilanteen.
13. Parempi testikattavuus
Projektin testauskattavuutta häiritsee nyt se, että myös src/tests-hakemiston testit ja src/index.py-tiedosto lasketaan testikattavuuteen. Voimme määritellä, että joitain tiedostoja tai kokonaisia hakemistoja jätetään huomioimatta kattavuusraportin generoinnissa.
Lisää juurihakemiston .coveragerc-tiedostoon, omit
-konfiguraatio ja määrittele siinä huomioimatta jätettävät tiedostot:
[run]
source = src
omit = src/tests/**,src/index.py
Konfiguraatiossa määritellä pilkulla eroteltuna niin kutsuttaja glob-polkuja. Voimme jättää huomioimatta esimerkiksi yksittäisen tiedoston polun (src/index.py), tai kaikki tietyn hakemiston alla olevat polut (src/tests/**).
Pushaa koodi GitHubiin ja varmista, että Codecov generoi raportin siten, että src/index.py-tiedosto ja src/tests-hakemiston tiedostot jätetään huomioimatta.
Tehtävien palautusrepositoriot
Tehtävät 14-16 kannattaa tehdä eri repositorioon kuin mihin teit tehtävät 2-13. Voit käyttää tehtävien 14-16 repositoriota myös seuraavien viikkojen tehtävien palauttamiseen. Nyt luotavan repositorion rakenne voi tällöin olla esimerkiksi seuraava:
viikko1
riippuvuuksien-injektointi-1
nhl-statistics-1
viikko2
poetry-web
project-reader
verkkokauppa-1
viikko3
nhl-reader
login-robot
web-login-robot
...
Tehtävien 2-13 repositorio (johon lisäsit esim. coverage-badgen) toimii pääpalautusrepositoriona. Lisää sen README.md-tiedostoon tehtävien 14-16 repositorion linkki.
Tehtävien 2-13 repositorion README.md-tiedoston tulisi siis näyttää suunnilleen tältä (poislukien liian alhainen testikattavuus):
14. Riippuvuuksien injektointi osa 1
Tutustumme kurssin aikana muutamiin suunnittelumalleihin (engl. design pattern), eli hyviksi tunnettuihin useisiin erilaisiin tilanteisiin sopiviin ratkaisutapoihin, joiden soveltaminen usein parantaa koodin laatua.
Kurssin ensimmäinen suunnittelumalli riippuvuuksien injektointi (engl. dependency injection), on yksinkertainen periaate, jota noudattamalla koodin automatisoitua testaamista on monissa tilanteissa mahdollista helpottaa ratkaisevalla tavalla.
- Tutustu riippuvuuksien injektointiin lukemalla tämä dokumentti
- Hae esimerkkiprojekti kurssin tehtävärepositorion hakemistosta koodi/viikko1/riippuvuuksien-injektointi-1 ja kokeile että se toimii
- Järkevintä lienee että kloonaat repositorion paikalliselle koneellesi
- Tämän jälkeen kannattaa kopioida projekti tehtävien 14-16 palautukseen käyttämäsi repositorion sisälle
Tutustu riippuvuuksien injektointiin esimerkin avulla. Asenna projektin riippuvuudet sen juurihakemistossa komennolla poetry install
. Tämän jälkeen saat suoritettua koodin virtuaaliympäristön sisällä komennolla python3 src/index.py
. Voit myös halutessasi suorittaa testit virtuaaliympäristön sisällä komennolla pytest
.
15. Riippuvuuksien injektointi osa 2: NHL-tilastot
- Kurssin tehtävärepositorion hakemistossa koodi/viikko1/nhl-statistics-1 on ohjelma, jonka avulla on mahdollista tutkia https://nhl.com-sivulla olevia tilastotietoja (koska uusi kausi on vasta juuri alkanut tilastot ovat edellisen kauden lopusta)
- Kopioi projekti edellisen tehtävän repositorion alle omaksi hakemistoksi
- Asenna projektin riippuvuudet suorittamalla sen juurihakemistossa komento
poetry install
- Ohjelma koostuu kolmesta luokasta.
Statistics
on palvelun tarjoava luokka, se tarjoaa metodit yhden pelaajan tietojen näyttämiseen, pistepörssin näyttämiseen ja yhden joukkueen pelaajien tietojen näyttämiseenPlayer
on luokka, jonka olioinaStatistics
-luokka käsittelee yksittäisen pelaajan tietojaPlayerReader
on luokka, jonka avulla ohjelma käy hakemassa pelaajien tiedot internetistä
- Ohjelma on nyt ikävästi struktoroitu ja esim. yksikkötestaus on kovin hankalaa
- HUOM: kun suoritat koodin ensimmäisen kerran (virtuaaliympäristössä komennolla
python3 src/index.py
), saattaa kestää hetken ennen kuin ohjelman käyttämä palvelin herää. Seuraavat suorituskerrat ovat nopeampia
Itse tehtävä:
- Muokkaa ohjelman rakennetta siten, että
Statistics
-luokka saa konstruktoriparametrinaPlayerReader
-luokan olion. - Muokkaa pääohjelma siten, että se injektoi
Statistics
-oliollePlayerReader
-luokan olion ja kokeile että ohjelma toimii edelleen:
stats = Statistics(
PlayerReader("https://nhlstatisticsforohtu.herokuapp.com/players.txt")
)
16. NHL-tilastot-ohjelman yksikkötestaus
- Tee yksikkötestit luokalle
Statistics
- Muista nimetä testitiedosto, testiluokka ja testimetodit unittest-ohjeiden mukaisesti. Muuten pytest ei löydä suoritettavia testejä
- Testien haarautumakattavuuden tulee
Statistics
-luokan osalta olla 100% (mittaa kattavuus coveragen avulla, katso tehtävä 8)- Huomaa, että kattavuusraportti ei generoidu ennen kun sovellukseen on lisätty testejä
- Testit eivät saa käyttää verkkoyhteyttä
- Verkkoyhteyden tarpeen saat eliminoitua luomalla testiä varten
PlayerReader
-luokkaa muistuttavan “stubin”, jonka sisälle kovakoodaat palautettavan pelaajalistan
import unittest
from statistics import Statistics
from player import Player
class PlayerReaderStub:
def get_players(self):
return [
Player("Semenko", "EDM", 4, 12),
Player("Lemieux", "PIT", 45, 54),
Player("Kurri", "EDM", 37, 53),
Player("Yzerman", "DET", 42, 56),
Player("Gretzky", "EDM", 35, 89)
]
class TestStatistics(unittest.TestCase):
def setUp(self):
# annetaan Statistics-luokan oliolle "stub"-luokan olio
self.statistics = Statistics(
PlayerReaderStub()
)
# ...
Kun injektoit PlayerReaderStub
-olion testissä Statistics
-oliolle, palauttaa se aina saman pelaajalistan.
Tehtävien palautus
Pushaa kaikki tekemäsi tehtävät (paitsi ne, joissa mainitaan, että tehtävää ei palauteta mihinkään) GitHubiin ja merkkaa tekemäsi tehtävät palautussovellukseen https://study.cs.helsinki.fi/stats/courses/ohtu-avoin-2022