Kmom05: Planeringsverktyg MyPlanner
Du ska göra ett planeringsverktyg som innehåller en “Att göra-lista”. Du ska lösa det med arv och testa dina klasser. Läs igenom hela uppgiften så att du får hela bilden av hela uppgiften innan du börjar.
Förkunskaper
Section titled “Förkunskaper”Du har jobbat igenom Kmom05 eller har motsvarande kunskaper.
Introduktion
Section titled “Introduktion”Du ska skapa ett planeringsverktyg med arv och klasser med följande menyalternativ. Det finns två olika typer av uppgifter; arbetsuppgift och personlig uppgift.
Menyalternativ:
- 1 - Skapa en uppgift
- 2 - Uppdatera en uppgift
- 3 - Ta bort en uppgift
- 4 - Skriv ut alla uppgifter
- 5 - Sätt en uppgift till klar
- e - Avsluta programmet
Dina klasser ska uppfylla beskrivningarna nedanför. Beskrivningarna är vad som måste finnas, du får och är rekommenderad att skapa ytterligare metoder och attribut där du tycker att det behövs. Vilken konstruktor behöver du ha? Eller är det någon setmetod som saknas?
Tips: Under utvecklingen av programmet så använd gärna huvudprogrammet till att testa så att varje klass funkar som du tänkt.
Kodregler
Section titled “Kodregler”- Använd this och base
- Använd namngivningsreglerna
- Minst en konstruktor i varje klass
- Använd hjälpmetoder för att få ner antalet kodrader. En vanlig rekommendation är max 20 rader per metod.
- Inte tillåtet med lambda-funktioner, paket som LINQ, dynamiska typer, goto och extension metoder.
- Varje uppgift ska lösas med de C# konstruktioner som vi går igenom i respektive kmom och tidigare kmom.
MyTask
Section titled “MyTask”Klassen MyTask innehåller en uppgift med titel, beskrivning, datum den ska vara klar och om den är klar eller inte.
Klassdiagram MyTask
Section titled “Klassdiagram MyTask”
Klassen MyTask innehåller:
- MyTask(string title, string description, DateTime dueDate) skapar uppgiften. Du kan förutsätta att alla attribut innehåller värden, inget är tomt. En uppgift är inte klar när den skapas.
- Update(string description, DateTime dueDate, string specifics="") uppdaterar uppgiften. Metoden ska överskuggas i subklasserna. Om uppdateringen går bra så returneras
true. Uppdateringen går bra om attribut uppdateras till ett nytt värde eller till samma värde som det hade innan.
Om uppdateringen inte går bra returnerasfalse. Ingen uppdatering ska ske om parameterndescriptionär en tom sträng eller om parameterndueDateär tidigare än dagens datum.
Den tredje parameternspecificshanteras av subklassen. - Completed() ändrar uppgiften till klar.
- GetDescription() returnerar en sträng med en beskrivning av uppgiften med all information (uppgiftens namn, beskrivning, datum den ska vara klar och om den är klar). Datumet ska vara på enligt ISO 8601 vilket är svensk standard. Om uppgiften är klar eller inte specificeras med “klar/inte klar” eller “done/not done”.
PrivateTask
Section titled “PrivateTask”Subklassen PrivateTask specificerar att det är en privat uppgift med en plats som egenskap. PrivateTask ärver från MyTask.
Klassdiagram PrivateTask
Section titled “Klassdiagram PrivateTask”
Subklassen PrivateTask innehåller:
- Update(string description, DateTime dueDate, string specifics="") överskuggar basklassens metod. Innehållet i
specificsmotsvarar det_locationska ersättas med, endast möjligt omspecificsinte är en tom sträng. Tänk på att anropa basklassens metodUpdateavseendedescriptionochdueDate. Om uppdateringen går bra så returnerastrue, annarsfalse. - GetDescription() överskuggar basklassens metod och returnerar inte bara basklassens information utan också platsen.
WorkTask
Section titled “WorkTask”Subklassen WorkTask specificerar att det är en arbetsuppgift med egenskaperna estimerad tid och arbetad tid. WorkTask ärver från MyTask.
Klassdiagram WorkTask
Section titled “Klassdiagram WorkTask”
Subklassen WorkTask innehåller:
- Update(string description, DateTime dueDate, string specifics="") överskuggar basklassens metod. Innehållet i
specificsmotsvarar det_timeWorkedoch_estimatedTimeska ersättas med. Formatet ispecificsär “timeWorked:estimatedTime”, till exempel “10:20”. Uppdatering är endast möjlig omtimeWorkedär mindre eller lika medestimatedTime. Tänk på att anropa basklassens metodUpdateavseendedescriptionochdueDate. Om uppdateringen går bra så returnerastrue, annarsfalse. - GetProgression() beräknar hur klar uppgiften är i procent. Om beräknad tid är 40 timmar och arbetad tid är 10 timmar, så är progressionen 25% och metoden ska då returnera 25. Korrekt avrundning ska göras till närmaste heltal.
- Completed() överskugga basklassen metod eftersom uppgiften inte kan sättas till klar förrän progressionen kommit upp i 80%. Annars anses uppgiften felplanerad och behöver uppdateras innan den kan sättas i completed.
- GetDescription() överskuggar basklassens metod och returnerar inte bara basklassens information utan också progressionen.
MyTaskHandler
Section titled “MyTaskHandler”Klassen MyTaskHandler innehåller (äger) en lista med uppgifter. Du kan lägga till uppgifter i listan, ta bort uppgifter ur listan och uppdatera uppgifter i listan. Du kan också få en lista med strängar som representerar en uppgift givet titeln på uppgiften. Klassen är till viss del implementerad men du behöver lägga till en del kod.
Planner
Section titled “Planner”Klassen Planner innehåller (äger) ett objekt av klassen MyTaskHandler. Här tänkte din kollega göra testdriven utveckling därför är klassen stubbad, med tomma metoder. Metoden Run() innehåller en loop som körs tills användaren väljer att avsluta. Klassen är klar men det är tillåtet att lägga till relevanta attribut och metoder om du tycker det behövs.
OBS! All in- och utmatning i terminalen ska ske i klassen Planner.
Huvudprogrammet
Section titled “Huvudprogrammet”Huvudprogrammet, Program.cs, använder bara klassen Planner och startar planeringsverktyget med metoden Run.
- Skapa klassen MyTask och använd huvudprogrammet för att testa hur klassen funkar i huvudprogrammet (Program.cs).
Exempel på tester av MyTask i huvudprogrammet
MyTask myTask = new MyTask("städa", "rengör badrummet", DateTime.Today);string before = myTask.GetDescription();Console.WriteLine(before);
bool updateOk = myTask.Update("rensa avloppet", DateTime.Today);string after = myTask.GetDescription();Console.WriteLine(after);if (updateOk && before != after){ Console.WriteLine("Uppdatering verkar funka! Kolla innehållet i strängarna!");}else{ Console.WriteLine("Inget uppdaterades, FEL!");}MyTask myTask = new MyTask("städa", "rengör badrummet", DateTime.Today);string before = myTask.GetDescription();Console.WriteLine(before);
bool updateOk = myTask.Update("", DateTime.Today);string after = myTask.GetDescription();Console.WriteLine(after);if (!updateOk && before == after){ Console.WriteLine("Uppdatering genomfördes inte och det var väntat.");}else{ Console.WriteLine("FEL!");}MyTask myTask = new MyTask("städa", "rengör badrummet", DateTime.Today);string before = myTask.GetDescription();Console.WriteLine(before);
bool updateOk = myTask.Update("", new DateTime(2025, 11, 11));string after = myTask.GetDescription();Console.WriteLine(after);if (!updateOk && before == after){ Console.WriteLine("Uppdatering genomfördes inte och det var väntat.");}else{ Console.WriteLine("FEL!");}- Skapa ett testprojekt MyPlanner.Tests och skapa en testklass för MyTask och gör testfall.
- testfall 1: skapa MyTask och verifiera innehållet
testfall 2: verifiera att Completed sätter attributetOBS hoppa över testfall 2 Completed sätter bara till true och inte tvärtom._completedtill false om uppgiften inte är klar- testfall 3: verifiera att Completed sätter attributet
_completedtill true om uppgiften är klar. Behövs kanske en getmetod här? - tesfall 4: givet ett visst tillstånd för MyTask, returnerar MyTask rätt info med
GetDescription(). - testfall 5: uppdatera MyTask och verifiera att uppdateringen går ok
- testfall 6: uppdatera MyTask med en felaktig beskrivning (parametern
description) och verifiera att uppdateringen inte går igenom. - testfall 7: uppdatera MyTask med datumet 2025-11-11 (parametern
dueDate) och verifiera att uppdateringen inte går igenom.
├── MyPlanner└── MyPlanner.Tests-
Då är det dags för subklassen PrivateTask.
- Implementera subklassen.
- Testa den i huvudprogrammet
- Gör en testklass för PrivateTask med minst 2 relevanta testfall
-
Då är det dags för subklassen WorkTask.
- Implementera subklassen.
- Testa den i huvudprogrammet
- Gör en testklass för WorkTask med minst 3 relevanta testfall. När du testar metoderna
GetProgression()använder du minst 3 olika indata till samma testfall.
-
Ladda ner klassen Planner med
task download-code -- kmom05/Planner.cs. Titta igenom klassen och ta reda på vad den gör. Klassen Planner har ett objekt av klassen MyTaskHandler och anropar dess metoder. -
Implementera klassen MyTaskHandler som hanterar alla uppgifter. Du laddar ner klassen med
task download-code -- kmom05/MyTaskHandler.cs. Vissa av metoderna är implementerade och andra ska du implementera. För att det inte ska bli kompileringsfel finns det dummy-returer i en del metoder. Du förväntas förstå vad du behöver lägga till i koden. -
Testkör ditt planeringsverktyg manuellt så att alla menyalternativ funkar.
Demo på MyPlanner
Section titled “Demo på MyPlanner”Så här ser det ut när vi kör programmet i terminalen:
Så här kan det se ut när det är klart.
Extrauppgift
Section titled “Extrauppgift”-
Se till att kodtäckningen funkar. Skapa en kodtäckningsrapport för MyPlanner.Tests. Generera en webbsida med ReportGenerator och kolla på kodtäckningen.
-
Se till att kodtäckningen blir 100% för MyTask. Utöka testplanen med dina testfall, implementera dem och testkör dem. Generera en ny rapport och kolla att alla kodrader i MyTask är testade.
-
Uppdatera testplanen med ett kapitel om testerna för klassen MyTaskHandler. Tänk ut minst 3 testfall och beskriv de och dess utfall.
-
Gör en testklass för MyTaskHandler och implementera ett testfall på
GetNoOfTasks()genom att använda “Moq”. -
Försök att nå 100% testtäckning för hela projektet.
Tips från coachen
Section titled “Tips från coachen”Felsöka med hjälp av utskrifter av Console.WriteLine(). Använd gärna debugger i VS Code.
Glöm inte att använda ‘dotnet format’ för att formatera din kod.
Lycka till och hojta till i forumet om du behöver hjälp!