⚠️ Viikon tehtävien palautuksen deadline on tiistai 25.3. klo 23:59. Tehtävät on tarkoitus tehdä joko pajassa tai omatoimisesti.

Tehtävät palautetaan GitHubin avulla Labtooliin rekisteröimääsi repositorioon. Muista pushata tehtävät GitHubiin ennen palautuksen deadlinea! Klo 00 jälkeen tulevia repositorion päivityksiä ei huomioida pisteytyksessä, eli ne tuovat 0 pistettä.

Palautuksesta saadut pisteet ja palaute löytyy Labtoolista viimeistään deadlinea vastaavan viikon loppuun mennessä. Muista tarkistaa saamasi pisteet ja palaute. Jos pisteytyksestä herää kysymyksiä, lähetä viesti Labtoolin kautta.

Tämän viikon tehtävien palautuksesta on tarjolla 2 pistettä ja harjoitustyön palautuksesta 1 piste.

Tee palautettavia tehtäviä varten repositorion sisällä olevaan hakemistoon laskarit uusi alihakemisto viikko2.

#Tehtävät

#1

  • tutustu JUnit-ohjeeseen
  • lukiessasi tee testit myös itse
  • lisää lopuksi maksukortille seuraavat testit:
    • maukkaan lounaan syöminen ei vie saldoa negatiiviseksi, ota tähän mallia testistä syoEdullisestiEiVieSaldoaNegatiiviseksi
    • negatiivisen summan lataaminen ei muuta kortin saldoa
    • kortilla pystyy ostamaan edullisen lounaan, kun kortilla rahaa vain edullisen lounaan verran (eli 2.5e)
    • kortilla pystyy ostamaan maukkaan lounaan, kun kortilla rahaa vain maukkaan lounaan verran (eli 4e)

HUOM1 on suositeltavaa, että yksi testi testaa vain “yhtä asiaa” kerrallaan. Tee siis jokaisesta ylläolevasta oma testinsä.

HUOM2 Kirjoita assertEquals-komennot aina siten, että ensimmäisenä parametrina on odotettu tulos ja toisena parametrina testatun metodin antama tulos.

#2 Maksukortti ja kassapääte: testit kortille

HUOM tämä tehtävä tehdään eri projektiin kuin edellinen, ja vaikka molemmissa tehtävissä on saman niminen luokka, eli Maksukortti ovat luokat erilaiset, eli älä copypastaa edellisen tehtävän koodia tai tehtäviä tähän tehtävään.

Tämän tehtävän projekti ladataan internetistä hieman alempana olevan ohjeen mukaan.

Ohjelmoinnin perusteiden viikolla 5 tehtävässä 101 toteutettiin “tyhmä” Maksukortti ja Kassapääte.

Rahan käsittely double-tyyppisenä on hiukan ongelmallista. Seuraavassa rahaa käsitellän kokonaislukuna ja kaikki rahamäärät talletetaan eurojen sijasta sentteinä.

Ohjelmointiuransa aloittelevan tuttavasi vastaus seuraavassa:

public class Maksukortti {

    private int saldo;

    public Maksukortti(int saldo) {
        this.saldo = saldo;
    }

    public int saldo() {
        return saldo;
    }

    public void lataaRahaa(int lisays) {
        this.saldo += lisays;
    }

    public boolean otaRahaa(int maara) {
        if (this.saldo < maara)
            return false;

        this.saldo = this.saldo - maara;
        return true;
    }

    @Override
    public String toString() {
        int euroa = saldo/100;
        int senttia = saldo%100;
        return "saldo: "+euroa+"."+senttia;
    }
}

Kassapäätteelle on lisätty metodit, jotka mahdollistavat myytyjen lounaiden määrän ja kassassa olevan rahamäärän kysymisen, toString()-metodi on poistettu:

public class Kassapaate {

    private int kassassaRahaa;
    private int edulliset;
    private int maukkaat;

    public Kassapaate() {
        this.kassassaRahaa = 100000;
    }

    public int syoEdullisesti(int maksu) {
        if (maksu >= 240) {
            this.kassassaRahaa = kassassaRahaa + 240;
            ++this.edulliset;
            return maksu - 240;
        } else {
            return maksu;
        }
    }

    public int syoMaukkaasti(int maksu) {
        if (maksu >= 400) {
            this.kassassaRahaa = kassassaRahaa + 400;
            this.maukkaat++;
            return maksu - 400;
        } else {
            return maksu;
        }
    }

    public boolean syoEdullisesti(Maksukortti kortti) {
        if (kortti.saldo() >= 240) {
            kortti.otaRahaa(240);
            this.edulliset++;
            return true;
        } else {
            return false;
        }
    }

    public boolean syoMaukkaasti(Maksukortti kortti) {
        if (kortti.saldo() >= 400) {
            kortti.otaRahaa(400);
            this.maukkaat++;
            return true;
        } else {
            return false;
        }
    }

    public void lataaRahaaKortille(Maksukortti kortti, int summa) {
        if (summa >= 0) {
            kortti.lataaRahaa(summa);
            this.kassassaRahaa += summa;
        } else {
            return;
        }
    }

    public int kassassaRahaa() {
        return kassassaRahaa;
    }

    public int maukkaitaLounaitaMyyty() {
        return maukkaat;
    }

    public int edullisiaLounaitaMyyty() {
        return edulliset;
    }
}

Hae nyt projektin koodi koneellesi.

Avaa terminaali, mene palautusrepositoriosi hakemistoon laskarit/viikko2 ja suorita seuraavat komennot:

wget https://raw.githubusercontent.com/mluukkai/ohjelmistotekniikka-syksy-2020/main/misc/Unicafe.zip
unzip Unicafe.zip
rm Unicafe.zip

HUOM jos käytät Windowsia ja koneellasi ei ole käytössä komentoa wget lataa tehtävän koodi klikkaamalla tätä linkkiä. Muista siirtää projekti repositorion alle oikeaan hakemistoon!

Lisää ja commitoi hakemisto repositorioon.

Varmista komennolla git status, että working directory on puhdas ja kaikki on commitoitu:

On branch master
Your branch is ahead of 'origin/master' by 3 commits.
  (use "git push" to publish your local commits)
nothing to commit, working tree clean

Olemme tähän asti suorittaneet testit NetBeansilla. Kokeillaan nyt miten testit voidaan suorittaa komentoriviltä.

  • mene hakemistoon, jossa projekti sijaitsee
    • Huom seuraavassa oletetaan että koneellesi on asennettu maven, laitoksen koneilla ja fuksikannettavissa maven löytyy valmiiksi, Linuxiin sekä OSX:n se on helppo asentaa, kenties myös Windowsiin
    • jos et jostain syystä saa mavenia toimimaan komentoriviltä, niin voit käyttää sitä NetBeansin kautta tämän ohjeen avulla
  • suorita testit antamalla komento mvn test
    • huomaa, että komento mvn tulee antaa aina projektin juurihakemistossa, eli samassa hakemistossa, jossa sijaitsee tiedosto pom.xml
    • muista, että näet hakemiston sisällön komennolla ls

Jos kaikki on hyvin, saat raportin läpimenneistä testeistä

Running com.mycompany.unicafe.MaksukorttiTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.248 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.046 s
[INFO] Finished at: 2018-02-27T15:59:21+02:00
[INFO] Final Memory: 19M/311M
[INFO] ------------------------------------------------------------------------

#.gitignore

Kun testien jälkeen suoritat komennon git status, huomaat että projektin juureen on ilmestynyt uusi hakemisto target, joka ei ole gitin alaisuudessa

On branch master
Your branch is ahead of 'origin/master' by 4 commits.
  (use "git push" to publish your local commits)
Untracked files:
  (use "git add <file>..." to include in what will be committed)

	target/

nothing added to commit but untracked files present (use "git add" to track)

maven-projektien hakemisto target, joka sisältää maven-komentojen aikaansaannoksia on tyypillisesti sellainen, jota emme halua versionhallinnan pariin.

git-repositorion juureen on mahdollista lisätä tiedosto .gitignore jossa voidaan määritellä, mitä tiedostoja ja hakemistoja git jättää huomioimatta eli ignoroi.

Mene repositoriosi juureen, luo tiedosto .gitignore, avaa se editorilla ja lisää tiedostoon seuraava rivi:

/laskarit/viikko2/Unicafe/target

Kun nyt teet komennon git status pitäisi tuloksen olla seuraava:

On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	.gitignore

Eli vaikka hakemistossa /laskarit/viikko2/Unicafe on alihakemisto target, ei git niitä huomioi

#Takaisin testeihin

Avaa nyt projekti NetBeansilla.

Tee valmiiseen testiluokkaan *MaksukorttiTest* testit, jotka testaavat ainakin seuraavia asioita:

  • kortin saldo alussa oikein
  • rahan lataaminen kasvattaa saldoa oikein
  • rahan ottaminen toimii
    • saldo vähenee oikein, jos rahaa on tarpeeksi
    • saldo ei muutu, jos rahaa ei ole tarpeeksi
    • metodi palauttaa true, jos rahat riittivät ja muuten false

Voit suorittaa testit NetBeansilla tai komentoriviltä.

#Maven

Suoritimme testit komentoriviltä komennolla mvn test. Mistä on kyse? Maksukortin sisältämä projekti on määritelty maven-formaatissa. Maven on työkalu, jonka avulla voidaan hallita Javalla tehtyjen ohjelmien kääntämistä, testien suorittamista ja paljon muitakin työvaiheita, kuten pian tulemme näkemään. Kurssin ohjelmoinnin perusteet tehtäviä ei ole määritelty mavenilla, vaan hieman vanhemmassa ant-formaatissa. Ohjelmoinnin jatkokurssilla ainakin myöhemmillä viikoilla on käytössä maven, se ei tosin juurikaan näy normaalille NetBeans-käyttäjälle.

Maven-projektien juuressa on tiedosto pom.xml, joka sisältää projektin konfiguraatiot. Katso miltä tiedosto näyttää. Tiedosto löytyy NetBeansista kohdan project files alta.

Tiedostossa on määritelty, että projektilla on testejä suoritettaessa riippuvuutena JUnit-kirjaston versio 4.12:

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Tiedostossa plugin-osiossa on määritelty, että koodi käännetään Javan versiota 8 käyttäen. Maven käyttää Java kasista numeroa 1.8 (kohdat source ja target):

<build>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
            <version>2.5</version>
        </plugin>
        ...
    </plugins>
</build>

#3 Testauskattavuus

Olemme tyytyväisiä, uskomme että testitapauksia on nyt tarpeeksi. Onko tosiaan näin? Onneksi on olemassa työkaluja, joilla voidaan tarkastaa testien rivi- ja haarautumakattavuus. Rivikattavuus mittaa mitä koodirivejä testien suorittaminen on tutkinut. Täydellinen rivikattavuuskaan ei tietenkään takaa että ohjelma toimii oikein, mutta on parempi kuin ei mitään. Haarautumakattavuus taas mittaa mitä eri suoritushaaroja koodista on käyty läpi. Suoritushaaroilla tarkoitetaan esim. if-komentojen valintatilanteita.

Projektiin on valmiiksi konfiguroitu käytettäväksi Jacoco joka mittaa sekä lause- että haarautumakattavuuden. Määrittely on tiedoston pom.xml osiossa plugins:

<build>
    <plugins>
        // ...
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>0.8.3</version>
            <executions>
                <execution>
                    <id>default-prepare-agent</id>
                    <goals>
                        <goal>prepare-agent</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

jacoco suoritetaan komentoriviltä (projektihakemistossa ollessasi) komennolla mvn test jacoco:report

Tulokset tulevat projektihakemistosi alihakemistoon target/site/jacoco/index.html. Avaa tulokset web-selaimella:

Useilla selaimilla tämä tapahtuu komennolla open file. Laitoksen koneella voit myös avata selaimen terminaalissa menemällä ensin projektihakemistoon ja antamalla komennon chromium-browser target/site/jacoco/index.html

Jos maksukortin koodissa on vielä rivejä tai haarautumia (merkitty punaisella) joille ei ole testiä, kirjoita sopivat testit.

#Maven-komentojen suorittaminen NetBeansista

Maven-komentoja on mahdollista suorittaa myös NetBeansin kautta. Tämä tapahtuu klikkaamalla projektin kohdalla hiiren oikealla napilla:

“Remember as”-toiminnolla voit tallettaa konfiguroidun maven-komentosarjan:

#4 Maven-projektin hakemistorakenne

Maven-projektien hakemiston rakenne noudattaa aina samaa logiikkaa. Hakemiston juuressa on projektin konfiguraatiot sisältävä tiedosto pom.xml. Ohjelman lähdekoodi on hakemistossa src/java ja testit hakemistossa src/test. Hakemistoon target generoituvat kaikki maven-komentojen aikaansannokset.

Suorita komento mvn clean. Komento poistaa hakemiston target.

Suorita projektin koodin käännöksen suorittava komento mvn compile. Tutki mitä hakemiston target sisälle syntyy.

Suorita testit komennolla mvn test. Tutki mitä hakemistosta target löytyy komennon suorittamisen jälkeen.

#5 Kassapäätteen testit

Laajennetaan Unicafen testaus kattamaan myös kassapääte.

Tee testiluokka *KassapaateTest* ja tee testit jotka testaavat ainakin seuraavia asioita:

  • luodun kassapäätteen rahamäärä ja myytyjen lounaiden määrä on oikea (rahaa 1000, lounaita myyty 0)
  • käteisosto toimii sekä edullisten että maukkaiden lounaiden osalta
    • jos maksu riittävä: kassassa oleva rahamäärä kasvaa lounaan hinnalla ja vaihtorahan suuruus on oikea
    • jos maksu on riittävä: myytyjen lounaiden määrä kasvaa
    • jos maksu ei ole riittävä: kassassa oleva rahamäärä ei muutu, kaikki rahat palautetaan vaihtorahana ja myytyjen lounaiden määrässä ei muutosta
  • seuraavissa testeissä tarvitaan myös Maksukorttia jonka oletetaan toimivan oikein
  • korttiosto toimii sekä edullisten että maukkaiden lounaiden osalta
    • jos kortilla on tarpeeksi rahaa, veloitetaan summa kortilta ja palautetaan true
    • jos kortilla on tarpeeksi rahaa, myytyjen lounaiden määrä kasvaa
    • jos kortilla ei ole tarpeeksi rahaa, kortin rahamäärä ei muutu, myytyjen lounaiden määrä muuttumaton ja palautetaan false
    • kassassa oleva rahamäärä ei muutu kortilla ostettaessa
  • kortille rahaa ladattaessa kortin saldo muuttuu ja kassassa oleva rahamäärä kasvaa ladatulla summalla

Huomaat että kassapääte sisältää melkoisen määrän “copypastea”. Nyt kun kassapäätteellä on automaattiset testit, on sen rakennetta helppo muokata eli refaktoroida siistimmäksi koko ajan kuitenkin varmistaen, että testit menevät läpi. Refaktoroi koodisi siistimmäksi jos haluat.

#6

Varmista jacocon avulla, että kassapäätteen testeillä on 100% lause- ja haarautumakattavuus.

#7

Talleta kohdassa testikattavuus olevan kuvan tyylinen screenshot projektisi kattavuusraportista palautusrepositoriosi hakemistoon laskarit/viikko2.

Muista tallentaa tekemäsi muutokset gitiin ja työntää ne Githubiin (git push).

#Harjoitustyö

#Alustava määrittelydokumentti

Harjoitustyön tekeminen aloitetaan päättämällä aihe ja kuvaamalla se alustavassa määrittelydokumentissa, eli työlle tehdään vaatimusmäärittely.

Aihetta miettiessäsi kannattaa ehdottomasti lukea ohjeet työn aloittamiseen.

Mikään ei tietenkään estä sitä, että aloitat jo ohjelmoinnin tai vaikkapa koodaat koko työn valmiiksi. Viikon 2 deadlinen pisteytyksessä ollaan kiinnostuneita ainoastaan määrittelydokumentista.

HUOM: jos aloitat jo ohjelmoinnin, muista että ohjelmakoodi tulee kirjoittaa englanniksi! Ohjelman käyttöliittymä ja dokumentaatio voivat olla suomeksi tai englanniksi.

Palautus tapahtuu lisäämällä oman aiheen alustava määrittelydokumentti ensimmäisen viikon laskareiden päätteeksi Labtooliin rekisteröimääsi palautusrepositorioon.

Määrittelydokumentti tehdään samaan tapaan kuin referenssiprojektissa eli markdown-muodossa, sijoitetaan repositorion hakemistoon dokumentaatio ja siihen tulee olla linkki repositorion README.md:stä.

Määrittelydokumenttiin kannattaa ottaa mallia referenssiprojektista, eli sen tulee sisältää:

  • Sovelluksen tarkoitus eli pieni tekstuaalinen yleiskuvaus sovelluksesta
  • Käyttäjät eli tieto erilaisista käyttäjärooleista, joita järjestelmässä on
    • Tosin jos sovelluksessasi on vain yhdenlaisia käyttäjiä, ei kohtaa tarvita. Näin lienee tilanne monissa harjoitustöiden aiheissa kuten peleissä.
  • Suunnitellut toiminnallisuudet
    • Toiminnallisuudet voi kuvata ranskalaisina viivoina samaan tapaan kuin referenssiprojektissa
    • Referenssiprojektissa on kuvattu perusversion eli jo “kurssin alkupuolella” toteutettavan ydintoiminnallisuuden toiminnallisuudet tarkemmin
    • Perusversiota laajentavat jatkokehitysideat ovat omassa listassaan

Voit myös tehdä referenssiprojektin tapaan käyttöliittymäluonnoksen, se ei ole kuitenkaan pakollinen.

#Työaikakirjanpito

Pidä säännöllisesti kirjaa käyttämistäsi työtunneista. Käytettyjen työtuntien määrä ei vaikuta arvosanaan, mutta vajavaisesti pidetty työaikakirjanpito alentaa työn arvosanaa.

  • Tuntikirjanpitoon ei merkitä laskareihin käytettyä aikaa

Lisää repositorion README.md-tiedostoon linkki työaikakirjanpitoon.

#Harjoitustyön toimivuus

  • Kurssilla käytettävän Python version tulee olla vähintään 3.10.
  • Koneiden konfiguraatioissa on eroja, ja tällä kurssilla ei riitä että hajoitustyössä tekemäsi sovellus toimii vain omalla koneellasi
  • Harjoitustyösi pitää pystyä joka viikko suorittamaan, kääntämään ja testaamaan komentoriviltä käsin laitoksen Linux-koneilla (tai uusimmat päivitykset sisältävällä cubbli-linuxilla), muussa tapauksessa työtä ei tarkasteta ja menetät viikon/loppupalautuksen pisteet.
  • Pääset testaamaan ohjelmaasi laitoksen koneella myös kotoa käsin käyttämällä etätyöpöytää, valitse valitse Cubbli Linux

#Älä plagioi tai riko tekijänoikeuksia

Plagiointi

Kurssilla seurataan Helsingin yliopiston opintokäytäntöjä. Plagiarismi ja opintovilppi, eli esimerkiksi netissä olevien tai kaverilta saatujen vastausten kopiointi ja niiden palauttaminen omana työnä on kiellettyä. Todettu opintovilppi johtaa kurssisuorituksen hylkäämiseen ja toistuva opintovilppi voi johtaa opinto-oikeuden määräaikaiseen menettämiseen.

Mitä plagiointi tarkoittaa harjoitustyön yhteydessä? Koodin suora kopioiminen on kiellettyä poikkeuksena muutaman rivin mittaiset algoritmit ja ChatGPT:n tai vastaavien välineiden generoima koodi (ks. alla). Myös koodin rakenteen suora kopioiminen esim. siten että muuttujien ja funktioiden nimet muutetaan lasketaan plagioinniksi. Toisaalta esim. verkosta löytyneitä kuvia saa käyttää, jos tähän on oikeus (ks. kohta tekijänoikeudet), mutta näin tehtävessä tulee työn dokumentaatioon tehdä “lähdeviite”, eli mainita mistä lainaus on tehty.

Samat plagiaattisäännöt koskevat työn dokumentaatiota ja erityisen kiellettyä on copy pasteta referenssisovelluksen dokumentaatiota.

ChatGPT ja vastaavat

Myös ChatGPT:n ja vastaavien tekoälyyn perustuvien välineiden (kuten esim. Microsoft Copilotin, Google Geminin, CurreChatin tai GitHub Copilotin) generoiman koodin tai tekstin esittäminen itse kirjoitetuksi on plagiointia. Generoidun koodin käyttö on kurssilla sallittua, mutta “ympäröi” aina tällainen koodi kommenteilla # generoitu koodi alkaa ja # generoitu koodi päättyy. Tee näin myös silloin, jos olet tehnyt generoituun koodiin vain vähäisiä muutoksia (vaihtanut muuttujien ja funktioiden nimiä tms.). Toisaalta, jos tämä ei käyttötavasta johtuen tunnu mielekkäältä, voit vaihtoehtoisesti liittää dokumentaatioon kuvauksen siitä, että millä tavoin ja missä laajuudessa olet tekoälypohjaisia välineitä harjoitustyösi missäkin osassa käyttänyt.

Muistathan, että ChatGPT:n ja vastaavien välineiden käyttö yksikkötestien koodin generointiin on kurssilla kiellettyä (muuten saa kyllä käyttää testailtaessakin).

Tekijänoikeudet

Kunnioita muutenkin tekijänoikeuksia ja muita immateriaalioikeuksia. Muista, että et saa käyttää mitä tahansa verkosta löytynyttä omassa työssäsi. Tämä koskee monenlaista materiaalia ohjelmakoodista kuviin ja teksteihin. Tarkista siis aina, että onko käyttö sallittua sen lisenssin mukaan, jolla materiaali mahdollisesti on jaettu. Muista, että harjoitustyöt ovat lähtökohtaisesti julkisia GitHubissa. On omalla vastuullasi, ettet riko tekijänoikeuksia.