Skip to content
Snippets Groups Projects
Commit a21c6bac authored by Sondre Bolland's avatar Sondre Bolland
Browse files

Remove git history

parents
No related branches found
No related tags found
No related merge requests found
Showing
with 515 additions and 0 deletions
# Compiled source #
###################
*.com
*.class
*.dll
*.exe
*.o
*.so
/bin/
bin
tmp
# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
# Binaries
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
*.war
*.ear
*.sar
*.class
# Maven
target/
/target/
# IntelliJ project files
*.iml
*.iws
*.ipr
*.idea/
# Eclipse project files
.settings/
.classpath
.project
# Logs and databases #
######################
*.log
*.sql
*.sqlite
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
{
"java.configuration.updateBuildConfiguration": "interactive"
}
\ No newline at end of file
# **Lab 5 – Testing**
## **Læringsmål**
🔹 Skrive og forstå enhetstester
🔹 Bruke tester til å identifisere og rette feil i koden
🔹 Evaluere testkvalitet ved hjelp av test-coverage-verktøyet **PIT**
---
## **Introduksjon**
I denne labben skal du skrive tester for en kalkulatorapplikasjon og bruke dem til å finne og rette feil.
Kalkulatoren bygger videre på det du lagde i **Lab 3**, men har nå støtte for flere operatorer. Tidligere implementerte du **binære operatorer**, som tar to argumenter:
-**Addisjon:** `6 + 5 = 11`
-**Multiplikasjon:** `6 * 5 = 30`
-**Subtraksjon:** `6 - 5 = 1`
- ^ **Eksponent:** `4^2 = 16`
Nå har vi utvidet kalkulatoren med **unære operatorer**, som bare tar ett argument:
- **Fakultet:** `5! = 1 * 2 * 3 * 4 * 5 = 120`
- **Tierlogaritmen:** `log(100) = 2`
- **Naturlig logaritme:** `ln(e) = 1`
-**Square root:** `√9 = 3`
📌 **Koden du får utdelt er en utvidet versjon av løsningsforslaget fra Lab 3.** De binære operatorene er allerede godt testet, men unære operatorer mangler tester.
🔍 **Din oppgave:**
✅ Skrive tester for de nye unære operatorene
✅ Bruke testene til å avdekke eventuelle feil
✅ Fikse feilene slik at kalkulatoren fungerer riktig
---
## **Før du starter**
🛠️ **For å gjennomføre denne labben må du ha installert Maven.** Hvis du ikke har gjort dette ennå, kan du følge [denne guiden fra Lab 4](https://git.app.uib.no/ii/inf101/25v/students/lab-4/-/blob/main/guide/maven.md).
---
## **Fremgangsmåte**
Følg stegene nedenfor for å fullføre oppgaven:
1. [📌 Hva er testing?](./guide/01-testing.md)
2. [📊 Test Coverage](./guide/02-testCoverage.md)
3. [🧪 PIT – Mutasjonstesting](./guide/03-PIT.md)
4. [❗ Fakultet](./guide/04-factorial.md)
5. [1️⃣ Unære operatorer](./guide/05-unaryOperators.md)
6. [🤔 Er det nok med coverage?](./guide/06-testCoverageEnough.md)
7. [📈 Øk coverage](./guide/07-fullCoverage.md)
---
## **Fullføring**
**Oppgaven er fullført når alle testene passerer!**
📌 **Husk å levere på CodeGrade før fristen!**
🚀 Lykke til! 🚀
🔙 **Forrige**[📜 Oversikt](../README.md)[🔜 Neste](guide/02-testCoverage.md)
# **🧪 Testing**
Testing er en **essensiell, men ofte undervurdert** del av programvareutvikling.
**Vi skriver tester for å sikre at programmet fungerer som forventet.**
## **🔹 Eksempel på en test**
Her er en av testene som allerede er inkludert i prosjektet:
```java
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class NumberExpressionTest {
@Test
void testConstructWithValidExpression() {
Number expr = new Number(5);
assertEquals(5.0, expr.getNumberValue());
}
}
```
Dette er en **enhetstest** (unit test). **Enhetstester** fokuserer på å teste små, individuelle deler av programmet for å sjekke om de fungerer som forventet.
I dette emnet bruker vi **[JUnit 5](https://junit.org/junit5/)** for å skrive tester.
## **📂 Hvor skal testene ligge?**
Alle testene våre legges i en egen mappe kalt **[`test`](../src/test)**.
Testpakkene må følge **samme struktur** som [`main`](../src/main)-mappen i prosjektet.
### **🛠 Hvordan lage en testklasse?**
1️⃣ Opprett en ny testklasse i **test-mappen**.
2️⃣ Annoter testmetodene med **`@Test`** for å markere dem som tester.
Eksempel:
```java
@Test
void myTest() {
// Testlogikk her
}
```
📌 Det går helt fint om du lager testene public, men det er ikke nødvendig i dette prosjektet, så vi har utelatt det.
## **🎯 Målet med denne labben**
✅ I tidligere labber har du fått en kodebase **med tester** og skrevet kode for å få testene til å passere.
**Denne gangen skal du skrive tester for en eksisterende kodebase.**
Men **det holder ikke bare å ha mange tester – testene må også være gode!** 🔍
---
🔙 **Forrige**[📜 Oversikt](../README.md)[🔜 Neste](guide/02-testCoverage.md)
🔙 **[Forrige steg](guide/01-testing.md)**[📜 **Oversikt**](../README.md)[🔜 Neste steg](guide/03-PIT.md)
# **🛡️ Test Coverage**
Når vi tester kode, ønsker vi å være grundige. **Dårlige tester kan føre til at feil i programmet ikke oppdages, selv om det ser ut til å fungere.**
For å sjekke hvor grundige testene våre er, kan vi bruke et **test coverage-verktøy**.
## **📊 Hva er test coverage?**
Test coverage-verktøy viser **hvor stor del av koden som er dekket av tester**.
De fleste slike verktøy måler hvor mange linjer som er kjørt under testene (**line coverage**), men dette tallet sier ikke nødvendigvis noe om hvor **gode** testene er.
## **🧬 Mutation Testing med PIT**
I denne labben bruker vi **[PIT](https://pitest.org/)**, som ikke bare måler line coverage, men også kvaliteten på testene gjennom **mutation testing**.
### **🔹 Hva er mutation testing?**
Mutation testing fungerer ved at PIT **gjør små endringer i koden din** (f.eks. endrer `+` til `-` eller `true` til `false`) og ser om testene dine oppdager endringen.
- **Dersom testene feiler**, betyr det at testene oppdaget feilen → **mutasjonen er "drept" ✅**
- **Dersom testene fortsatt passerer**, betyr det at testene ikke oppdaget feilen → **mutasjonen "overlevde" ❌**
🎯 **Målet er å drepe så mange mutasjoner som mulig!** Dette viser at testene faktisk verifiserer koden og ikke bare sjekker at den kjører.
## **🏆 Målet med denne labben**
Du skal:
✅ Lære å skrive dine egne tester.
✅ Sikre at testene dine har en **høy mutation coverage-score**.
**Skrive gode tester, ikke bare mange tester!**
---
🔙 **[Forrige steg](guide/01-testing.md)**[📜 **Oversikt**](../README.md)[🔜 Neste steg](guide/03-PIT.md)
\ No newline at end of file
🔙 **[Forrige steg](guide/02-testCoverage.md)**[📜 **Oversikt**](../README.md)**[🔜 Neste steg](guide/04-factorial.md)**
# **🛠️ Steg 1 - Gjør deg kjent med PIT**
I dette steget skal du forstå hvordan **PIT** fungerer og lære å tolke **mutation testing-rapporten**.
## **📑 Generer en PIT-rapport**
For å bruke **PIT** må vi legge til en avhengighet i `pom.xml`, men dette er allerede gjort for deg.
👉 **Merk**: Testene i `mutationCoverage` og `textAnswers` **overses av PIT**, siden de ikke er relevante for kalkulator-programmet.
### **▶️ Kjør PIT i terminalen**
For å sjekke **mutation coverage**, kjør følgende kommando i terminalen:
```sh
mvn test-compile org.pitest:pitest-maven:mutationCoverage
```
**Alle testene må passere for å kunne kjøre denne kommandoen.**
✅ Hvis rapporten genereres riktig, vil du se **"BUILD SUCCESS"** i grønn skrift i terminalen:
![img.png](../images/buildSuccess.png)
Rapporten lagres som en **HTML-fil** i:
📂 **[target/pit-reports](../target/pit-reports)**
*(Denne mappen opprettes automatisk ved første kjøring av PIT.)*
---
## **🔍 Hvordan leser vi PIT-rapporten?**
1. **Åpne rapporten:**
Gå til **[target/pit-reports](../target/pit-reports)** og åpne **[index.html](../target/pit-reports/index.html)** i en nettleser.
2. **Forstå oversikten:**
Øverst ser du prosjektets:
- **Line coverage** (hvor mye kode som kjøres i testene)
- **Mutation coverage** (hvor mange mutasjoner testene dine oppdager)
- **Test strength** (hvor mange mutasjoner som drepes av dine egne tester)
**Test strength er ofte høyere enn mutation coverage** fordi mye kode ennå ikke er testet.
![img.png](../images/PITReport.png)
3. **Se detaljer per pakke:**
Klikk deg inn på en pakke for å se testing av enkeltklasser.
4. **Analyser en testet klasse:**
👉 **Gå til** `Addition.java`.
![img.png](../images/AdditionJava.png)
- **Grønne linjer** ✅ → Mutasjonen ble drept (testen oppdaget feilen).
- **Røde linjer** ❌ → Mutasjonen overlevde (testen fanget ikke feilen).
Nederst ser du en **mutasjonsoversikt** som forklarer hvilke linjer PIT har endret og hvorfor mutasjonen overlevde eller ble drept.
---
## **✅ TODO: Utforsk PIT-rapporten**
1. **Generer en PIT-rapport** og se hvor mutation coverage vises.
2. **Finn mutasjonsoversikten** for en enkeltklasse.
3. **Sjekk at du forstår rapporten** ved å svare på spørsmålene i:
📄 **TextAnswers.java**
🚀 **Du er ferdig med dette steget når testene i `TextAnswerTest` passerer.**
---
🔙 **[Forrige steg](guide/02-testCoverage.md)**[📜 **Oversikt**](../README.md)**[🔜 Neste steg](guide/04-factorial.md)**
\ No newline at end of file
🔙 **[Forrige steg](guide/03-PIT.md)**[📜 **Oversikt**](../README.md)[🔜 **Neste steg**](guide/05-unaryOperators.md)
# **Test fakultet**
I denne delen skal du skrive dine første tester ved hjelp av **JUnit 5**.
---
## **📝 TODO 1 – Opprett testklasse**
📌 **Oppgave:** Opprett klassen **`UnaryOperatorsTest`** i pakken **`no.uib.inf101.calculator.operations`**.
For å skrive tester med **JUnit 5**, må du importere følgende:
```java
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.fail;
```
### **🔹 Struktur på tester i JUnit 5**
Alle tester må:
✅ Merkes med **`@Test`**-annotasjonen for at JUnit skal kjenne dem igjen.
✅ Ha **`void`** som returtype.
✅ Ikke ta noen parametere.
Eksempel:
```java
@Test
void myTest() {
// Testlogikk her
}
```
### **🔹 Verktøy for testing**
JUnit gir oss flere metoder for å sjekke forventede verdier:
**Sammenligning av verdier:**
```java
assertEquals(expected, actual); // Sjekker om to verdier er like
```
**Sjekk om en verdi er sann:**
```java
assertTrue(booleanVariable); // Sjekker om en verdi er sann
```
**Sjekk om en verdi er usann:**
```java
assertFalse(booleanVariable); // Sjekker om en verdi er usann
```
**Tving en test til å feile hvis en betingelse er oppfylt:**
```java
if (someCondition) {
fail(); // Stopper testen med feil
}
```
---
## **📝 TODO 2 – Test klassen `Factorial`**
📌 **Oppgave:** Skriv en test som sjekker at metodene i klassen **`Factorial`** fungerer korrekt.
**Testene skal dekke:**
**`calculate(int n)`**
- Skal returnere fakultet av tallet som gis som argument.
- Eksempel: `calculate(5) == 120`
**`getSymbol()`**
- Skal returnere symbolet **`!`**
**`getDescription()`**
- Skal returnere en **ikke-tom streng** (for eksempel: `getDescription() != ""`).
---
## Fullført?
Når du har skrevet testene skal du sjekke coverage. Kjør PIT i terminalen:
```
mvn test-compile org.pitest:pitest-maven:mutationCoverage
```
🚀 **Du har fullført dette steget av labben når rapporten sier 100% coverage for `Factorial.java`!**
![img.png](../images/factorialCoverage.png)
🔙 **[Forrige steg](guide/03-PIT.md)**[📜 **Oversikt**](../README.md)[🔜 **Neste steg**](guide/05-unaryOperators.md)
\ No newline at end of file
🔙 **[Forrige steg](guide/04-factorial.md)**[📜 **Oversikt**](../README.md)[**🔜 Neste steg**](guide/06-testCoverageEnough.md)
# **Unære operatorer**
I dette steget skal du skrive tester for **unære operatorer** slik at du oppnår **100% coverage**.
## **✅ Oppgave**
📌 **Skriv tester for alle unære operatorer** slik at du får full **coverage**:
![img.png](../images/unaryCoverage.png)
---
## **💡 Hint: Sammenligning av desimaltall**
Når du tester **double**-verdier, må du huske at **små avrundingsfeil** kan forekomme. Derfor sammenligner vi tall med en **margin av feil** i stedet for eksakt likhet.
### **Eksempel**
Denne sjekken vil ofte feile pga. avrundingsforskjeller:
```java
double num1 = 1.0;
double num2 = 0.99999;
assertEquals(num1, num2); // ❌ Kan feile!
```
**Bruk en toleranse (epsilon) for å unngå dette:**
```java
assertEquals(num1, num2, 0.001); // ✅ Passerer hvis forskjellen er mindre enn 0.001
```
Dette sikrer at **testene dine ikke feiler unødvendig** på grunn av små avrundingsavvik.
---
## **📊 Sjekk testdekning**
Når du har skrevet testene, kjør **PIT** for å sjekke coverage:
```sh
mvn test-compile org.pitest:pitest-maven:mutationCoverage
```
🚀 **Du er ferdig med dette steget når PIT-rapporten viser 100% testdekning for alle klassene i `no.uib.inf101.calculator.operations`!**
---
🔙 **[Forrige steg](guide/04-factorial.md)**[📜 **Oversikt**](../README.md)[**🔜 Neste steg**](guide/06-testCoverageEnough.md)
\ No newline at end of file
🔙 **[Forrige steg](guide/05-unaryOperators.md)**[📜 **Oversikt**](../README.md)[**🔜 Neste steg**](guide/07-fullCoverage.md)
# **🔎 Dekker testene alt?**
Vi har nå **100% testdekning** for alle operatorklassene. Det betyr vel at **alt fungerer som det skal** … eller?
## **🤔 Et problem med fakultet**
Hva skjer hvis vi prøver å beregne fakultet for et **desimaltall**?
```java
Operator operator = new Factorial();
double result = operator.calculate(0.5);
System.out.println(result); // ??
```
Fakultet er definert for **heltall** som:
```
n! = n * (n-1) * (n-2) * ... * 1
```
Eksempel:
```
5! = 5 * 4 * 3 * 2 * 1 = 120
```
Men for **desimaltall** som `0.5`, er definisjonen mer komplisert:
```
0.5! = 0.8862269...
```
Utregningen kan du lese om [her](https://math.stackexchange.com/questions/454053/how-do-we-calculate-factorials-for-numbers-with-decimal-places).
---
## **📌 Tester dekker aldri alt**
Selv med **100% coverage og mutation coverage**, kan det fortsatt være **ukjente feil** i programmet. **Gode tester** finner de vanligste feilene, men ikke nødvendigvis **alle**.
---
# **✅ TODO: Fiks fakultet-feilen**
Vi har to valg:
## **🔹 Alternativ 1: Implementer fakultet for desimaltall**
Utvid `Factorial::calculate` slik at den **støtter desimaltall**. Bruk en korrekt utregningsmetode, f.eks. [**Gamma-funksjonen**](https://math.stackexchange.com/questions/454053/how-do-we-calculate-factorials-for-numbers-with-decimal-places).
### **🛠️ Test din implementasjon**
✅ Utvid testene for å sjekke både **heltall** og **desimaltall**.
---
## **🔹 Alternativ 2: Ikke tillat fakultet for desimaltall**
Vi kan **forhindre** bruk av desimaltall i `Factorial::calculate`.
1. **Sjekk om argumentet er et desimaltall**.
2. **Kast en `IllegalArgumentException` hvis det ikke er et heltall**.
### **🛠️ Test din implementasjon**
✅ Utvid testene til å sjekke at metoden kaster en exception for desimaltall. For dette kan vi bruke en ny assert-metode:
```java
import static org.junit.jupiter.api.Assertions.assertThrows;
assertThrows(IllegalArgumentException.class, () -> myMethod());
```
---
🚀 **Når du har valgt og implementert én løsning, og testet den, kan du gå videre!**
🔙 **[Forrige steg](guide/05-unaryOperators.md)**[📜 **Oversikt**](../README.md)[**🔜 Neste steg**](guide/07-fullCoverage.md)
\ No newline at end of file
🔙 **[Forrige steg](06-testCoverageEnough.md)**[📜 **Oversikt**](../README.md)
# Skriv flere tester!
Det er fremdeles ting i programmet vårt som ikke er testet.
I dette steget vil vi at du helt selv skal identifisere noen av disse tingene og skrive tester for dem.
Selv om coverage ikke vil dekke alle feil i programmet så kan det være en god indikasjon på mulige mangler.
## ✅ TODO: Øk mutation coverage
Skriv tester for å øke mutation coverage til **minst 54%**. Dette skal være mulig å gjøre **kun ved å skrive tester for
[Calculator.java](../src/main/java/no/uib/inf101/calculator/Calculator.java)**. Ikke skriv tester for `CalculatorGUI`. Unit tester brukes sjeldent for GUI.
🚀 **Du er ferdig med dette steget når testen i `MutationCoverageTest` passerer!**
***
🥳 Nå er du ferdig! **Husk å levere labben på CodeGrade!**
🔙 **[Forrige steg](06-testCoverageEnough.md)**[📜 **Oversikt**](../README.md)
images/AdditionJava.png

71.6 KiB

images/PITReport.png

63.3 KiB

images/buildSuccess.png

12.1 KiB

images/calculatorTooltip.png

107 KiB

images/factorialCoverage.png

311 KiB

images/finishedCalculator.png

21.2 KiB

images/unaryCoverage.png

47.2 KiB

mvn.windows = mvn.cmd
mvn.unix = mvn
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment