summaryrefslogtreecommitdiff
path: root/30-qualitaetsheft/sections
diff options
context:
space:
mode:
Diffstat (limited to '30-qualitaetsheft/sections')
-rw-r--r--30-qualitaetsheft/sections/backend.tex28
-rw-r--r--30-qualitaetsheft/sections/changes.tex67
-rw-r--r--30-qualitaetsheft/sections/codestyle.tex224
-rw-r--r--30-qualitaetsheft/sections/coverage.tex59
-rw-r--r--30-qualitaetsheft/sections/einleitung.tex13
-rw-r--r--30-qualitaetsheft/sections/frontend.tex196
-rw-r--r--30-qualitaetsheft/sections/glossar.tex391
-rw-r--r--30-qualitaetsheft/sections/lasttest.tex105
-rw-r--r--30-qualitaetsheft/sections/problems.tex65
-rw-r--r--30-qualitaetsheft/sections/testfaelle.tex182
-rw-r--r--30-qualitaetsheft/sections/tests.tex21
11 files changed, 1351 insertions, 0 deletions
diff --git a/30-qualitaetsheft/sections/backend.tex b/30-qualitaetsheft/sections/backend.tex
new file mode 100644
index 0000000..19efd65
--- /dev/null
+++ b/30-qualitaetsheft/sections/backend.tex
@@ -0,0 +1,28 @@
+\section{Backend}
+
+Für das Backend wird das \Gls{java}-Framework \Gls{spring} verwendet. Neben seiner Modularität,
+bietet es viele Funktionen, die unter
+anderem die Entwicklung von Backend-Anwendungen vereinfachen.
+Darunter fällt zum Beispiel die Unterstützung von Dependency Injection, dessen
+Vorteile bereits beschrieben wurden.
+Außerdem unterstützt \Gls{java} \Gls{spring} intern eine Verwaltung von \Glspl{db}, sodass
+sich nicht mit dem \Gls{SQL}-Code an sich befasst werden muss.
+Auch bezüglich Authentifizierung und Sicherheit bietet \Gls{spring} eigene Funktionalitäten.
+
+Zusätzlich dazu wird als Build-System für das \Gls{java}-\Gls{spring}-Backend Maven verwendet.
+Maven hilft dabei alle Abhängigkeiten des Projekts zu verwalten und automatisiert
+den Build Prozess.
+Durch die zusätzliche Unterstützung von Versionskontrollsystemen und der Kompatibilität
+zu vielen Continuous Integration-Tools wird außerdem die Entwicklung in einem Team erleichtert
+und optimiert. Denn dadurch können Build- und Deployment-Prozesse automatisiert werden.
+Außerdem bietet Maven Bibliotheken zum Testen sowie zur Generierung von Dokumentationen an.
+
+Vom Backend benötigte Abhängigkeiten:
+\begin{itemize}
+ \item \Gls{spring} Web
+ \item \Gls{spring} Security
+ \item \Gls{spring} Mail Sender
+ \item \Gls{spring} Data JPA
+ \item Lombok
+ \item Rome (\Gls{rss} parsing/fetching)
+\end{itemize} \ No newline at end of file
diff --git a/30-qualitaetsheft/sections/changes.tex b/30-qualitaetsheft/sections/changes.tex
new file mode 100644
index 0000000..27188a7
--- /dev/null
+++ b/30-qualitaetsheft/sections/changes.tex
@@ -0,0 +1,67 @@
+\section{Änderungen zum Implementierungsheft}
+
+Zuallererst werden im Folgenden die Änderungen zum Implementierungsheft aufgelistet und es wird erläutert warum diese
+Änderungen gemacht wurden.
+
+\subsection{Kriterien}
+
+Zwei weitere Kriterien sind nun erfüllt. Diese sind:
+
+\begin{table}[h!]
+\begin{tabularx}{\textwidth}{l|X|c}
+Bezeichner & Zusammenfassung & Implementiert\\\hline
+\textlangle RM7 \textrangle & 50 Anfragen / Sekunde bearbeiten & Ja*\\\hline\hline
+\textlangle RC2 \textrangle & \Glspl{abo} in Weboberfläche deabonnieren & Ja
+\end{tabularx}
+\end{table}
+
+*nicht unter Mindestanforderungen - 2 Kerne, 2GB RAM, 12GB Speicher
+
+\subsection{Aussagekräftige Benachrichtigungen im Frontend}
+
+Zur Implementierungsphase wurden generische Fehlermeldungen angezeigt, falls
+eine Anfrage an den Server fehlschlug. Mit Fehlercodes können Nutzer nicht
+besonders viel anfangen, weshalb wir die Benachrichtigungen überarbeitet haben.
+
+Jetzt werden neben farbenfrohen Symbolen auch verständliche Meldungen angezeigt.
+Fehlermeldungen von Server-Anfragen zeigen dabei einen unterschiedlichen Text
+an, je nachdem welcher HTTP-Code zurück gegeben wurde oder ob der Server
+überhaupt erreichbar ist.
+
+\begin{figure}[h!]
+ \centering
+ \includegraphics[scale=0.5]{assets/notifications.png}
+ \caption{Eine Auswahl von Benachrichtigungen mit Symbol und Nachricht}
+\end{figure}
+
+\newpage
+\subsection{Deabonnieren von Podcasts}
+
+Eine der letzten offenen Kann-Kriterien war das Deabonnieren von Podcasts im
+Dashboard \textlangle RC2 \textrangle. Dies wurde nun nachgeholt. Dabei
+stehen dem Nutzer zwei Optionen zur Verfügung. Die Abonnements können einzeln
+über einen Knopf entfernt werden oder es können mehrere Abonnements mit
+Checkboxen ausgewählt und dann zusammen gelöscht werden.
+Ein weiterer Knopf ermöglicht das gleichzeitige Auswählen aller Abonnements.
+
+Mit beiden Optionen wird der Nutzer erst über die Folgen des Deabonnierens
+in einem Popup-Fenster informiert. Hierbei handelt es sich um den Verlust aller
+Hörfortschritte zu den Abonnements. Dabei wird auf dem Pop-Up zu jedem
+Abonnement auch die Anzahl der gehörten Episoden aufgelistet. Erst bei Bestätigung
+des Popups durch den Benutzer werden die Abonnements und Episoden vom Account entfernt.
+
+\begin{figure}[H]
+ \centering
+ \begin{minipage}{.47\textwidth}
+ \centering
+ \fbox{\includegraphics[width=\textwidth]{assets/select-subscriptions.png}}
+ \caption{Auswählen von Abonnements über Checkboxen}
+ \end{minipage}
+ \hspace{.5cm}
+ \begin{minipage}{.47\textwidth}
+ \centering
+ \includegraphics[width=\textwidth]{assets/unsubscribe-podcasts.png}
+ \caption{Übersicht und Bestätigung des Deabonnements}
+ \end{minipage}
+\end{figure}
+
diff --git a/30-qualitaetsheft/sections/codestyle.tex b/30-qualitaetsheft/sections/codestyle.tex
new file mode 100644
index 0000000..2eb7a0a
--- /dev/null
+++ b/30-qualitaetsheft/sections/codestyle.tex
@@ -0,0 +1,224 @@
+\section{Code-Stil}
+
+\subsection{Server}
+
+% Balkendiagram:
+% zwei Balken: vorher, nachher
+% eine Balken besteht aus verschiedenen Ebenen für jeden Linter Fehler
+\definecolor{error00}{RGB}{255, 0, 0}
+\definecolor{error01}{RGB}{204, 0, 0}
+\definecolor{error02}{RGB}{153, 0, 0}
+\definecolor{error03}{RGB}{102, 0, 0}
+\definecolor{error04}{RGB}{51, 0, 0}
+\definecolor{error05}{RGB}{25, 0, 0}
+
+\definecolor{warning00}{RGB}{255, 255, 0}
+\definecolor{warning01}{RGB}{255, 215, 0}
+\definecolor{warning02}{RGB}{139, 117, 0}
+\definecolor{warning03}{RGB}{238, 201, 0}
+\definecolor{warning04}{RGB}{255, 215, 0}
+\definecolor{warning05}{RGB}{238, 238, 0}
+\definecolor{warning06}{RGB}{139, 139, 0}
+\definecolor{warning07}{RGB}{255, 255, 0}
+\definecolor{warning08}{RGB}{238, 201, 0}
+\definecolor{warning09}{RGB}{205, 173, 0}
+\definecolor{warning10}{RGB}{205, 205, 0}
+\definecolor{warning11}{RGB}{205, 173, 0}
+\definecolor{warning12}{RGB}{238, 238, 0}
+\definecolor{warning13}{RGB}{139, 117, 0}
+\definecolor{warning14}{RGB}{139, 139, 0}
+
+\vspace{-2cm}
+\begin{tikzpicture}
+\begin{axis}[
+ title={Code-Stil-Anmerkungen durch Checkstyle Sun-Checks},
+ ybar stacked, ymin=0,
+ bar width=10mm,
+ symbolic x coords={Vorher,Nachher},
+ legend style={
+ at={(1.3,0.5)},
+ cells={anchor=west},
+ anchor=west
+ },
+ xtick=data,
+ xticklabel style={text width=2cm,align=center},
+ nodes near coords={}
+]
+
+\addplot [fill=error02] coordinates { ({Vorher}, 285 ) ({Nachher}, 0)}; % (sizes) LineLength
+\addplot [fill=error00] coordinates { ({Vorher}, 143 ) ({Nachher}, 0)}; % (misc) FinalParameters
+\addplot [fill=error03] coordinates { ({Vorher}, 101 ) ({Nachher}, 0)}; % (javadoc) JavadocVariable
+\addplot [fill=error04] coordinates { ({Vorher}, 83 ) ({Nachher}, 0)}; % (javadoc) JavadocStyle
+\addplot [fill=error02] coordinates { ({Vorher}, 43 ) ({Nachher}, 0)}; % (design) DesignForExtension
+\addplot [fill=error01] coordinates { ({Vorher}, 39 ) ({Nachher}, 0)}; % (javadoc) MissingJavadocMethod
+\addplot [fill=error01] coordinates { ({Vorher}, 26 ) ({Nachher}, 0)}; % (regexp) RegexpSingleline
+\addplot [fill=error02] coordinates { ({Vorher}, 15 ) ({Nachher}, 0)}; % (whitespace) WhitespaceAround
+\addplot [fill=error01] coordinates { ({Vorher}, 13 ) ({Nachher}, 0)}; % (javadoc) JavadocPackage
+\addplot [fill=error03] coordinates { ({Vorher}, 10 ) ({Nachher}, 0)}; % (whitespace) OperatorWrap
+\addplot [fill=error00] coordinates { ({Vorher}, 10 ) ({Nachher}, 0)}; % (javadoc) JavadocType
+\addplot [fill=error05] coordinates { ({Vorher}, 7 ) ({Nachher}, 0)}; % (imports) AvoidStarImport
+\addplot [fill=error05] coordinates { ({Vorher}, 6 ) ({Nachher}, 0)}; % (coding) MagicNumber
+\addplot [fill=error05] coordinates { ({Vorher}, 4 ) ({Nachher}, 0)}; % (javadoc) JavadocMethod
+\addplot [fill=error04] coordinates { ({Vorher}, 3 ) ({Nachher}, 0)}; % (coding) HiddenField
+\addplot [fill=error02] coordinates { ({Vorher}, 2 ) ({Nachher}, 0)}; % (javadoc) InvalidJavadocPosition
+\addplot [fill=error00] coordinates { ({Vorher}, 2 ) ({Nachher}, 0)}; % (blocks) RightCurly
+\addplot [fill=error03] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % (whitespace) WhitespaceAfter
+\addplot [fill=error04] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % (whitespace) FileTabCharacter
+\addplot [fill=error04] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % (misc) NewlineAtEndOfFile
+\addplot [fill=error01] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % (misc) ArrayTypeStyle
+\addplot [fill=error00] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % (imports) UnusedImports
+\addplot [fill=error03, point meta=y,nodes near coords,nodes near coords align={anchor=south}] coordinates { ({Vorher}, 2 ) ({Nachher}, 1)}; % (design) HideUtilityClassConstructor
+
+\legend{
+sizes: LineLength,
+misc: FinalParameters,
+javadoc: JavadocVariable,
+javadoc: JavadocStyle,
+design: DesignForExtension,
+javadoc: MissingJavadocMethod,
+regexp: RegexpSingleline,
+whitespace: WhitespaceAround,
+javadoc: JavadocPackage,
+whitespace: OperatorWrap,
+javadoc: JavadocType,
+imports: AvoidStarImport,
+coding: MagicNumber,
+javadoc: JavadocMethod,
+coding: HiddenField,
+javadoc: InvalidJavadocPosition,
+blocks: RightCurly,
+whitespace: WhitespaceAfter,
+whitespace: FileTabCharacter,
+misc: NewlineAtEndOfFile,
+misc: ArrayTypeStyle,
+imports: UnusedImports,
+design: HideUtilityClassConstructor,
+}
+\end{axis}
+\end{tikzpicture}
+
+\begin{tabularx}{\textwidth}{X | c | c}
+Regel & Vorher & Nacher \\ \hline
+sizes: LineLength & 285 & 0 \\
+misc: FinalParameters & 143 & 0 \\
+javadoc: JavadocVariable & 101 & 0 \\
+javadoc: JavadocStyle & 83 & 0 \\
+design: DesignForExtension & 43 & 0 \\
+javadoc: MissingJavadocMethod & 39 & 0 \\
+regexp: RegexpSingleline & 26 & 0 \\
+whitespace: WhitespaceAround & 15 & 0 \\
+javadoc: JavadocPackage & 13 & 0 \\
+whitespace: OperatorWrap & 10 & 0 \\
+javadoc: JavadocType & 10 & 0 \\
+imports: AvoidStarImport & 7 & 0 \\
+coding: MagicNumber & 6 & 0 \\
+javadoc: JavadocMethod & 4 & 0 \\
+coding: HiddenField & 3 & 0 \\
+javadoc: InvalidJavadocPosition & 2 & 0 \\
+blocks: RightCurly & 2 & 0 \\
+whitespace: WhitespaceAfter & 1 & 0 \\
+whitespace: FileTabCharacter & 1 & 0 \\
+misc: NewlineAtEndOfFile & 1 & 0 \\
+misc: ArrayTypeStyle & 1 & 0 \\
+imports: UnusedImports & 1 & 0 \\
+design: HideUtilityClassConstructor & 2 & 1 \\
+\end{tabularx}
+
+\subsection{Dashboard}
+
+\vspace{-1.5cm}
+\begin{tikzpicture}
+\begin{axis}[
+ title={Code-Stil-Anmerkungen durch ESLint},
+ ybar stacked, ymin=0,
+ bar width=10mm,
+ symbolic x coords={Vorher,Nachher},
+ legend style={
+ at={(1.1,0.5)},
+ cells={anchor=west},
+ anchor=west
+ },
+ xtick=data,
+ xticklabel style={text width=2cm,align=center},
+ nodes near coords={}
+]
+
+\addplot [fill=error00] coordinates { ({Vorher}, 26 ) ({Nachher}, 0)}; % error vue/html-indent
+\addplot [fill=error01] coordinates { ({Vorher}, 17 ) ({Nachher}, 0)}; % error vue/script-indent
+\addplot [fill=error02] coordinates { ({Vorher}, 6 ) ({Nachher}, 0)}; % error vue/require-v-for-key
+\addplot [fill=error03] coordinates { ({Vorher}, 5 ) ({Nachher}, 0)}; % error vue/multi-word-component-names
+\addplot [fill=error04] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % error vue/valid-v-for
+\addplot [fill=error05] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % error vue/valid-template-root
+\addplot [fill=warning00] coordinates { ({Vorher}, 125 ) ({Nachher}, 0)}; % warning vue/max-attributes-per-line
+\addplot [fill=warning01] coordinates { ({Vorher}, 34 ) ({Nachher}, 0)}; % warning vue/attributes-order
+\addplot [fill=warning02] coordinates { ({Vorher}, 26 ) ({Nachher}, 0)}; % warning vue/singleline-html-element-content-newline
+\addplot [fill=warning03] coordinates { ({Vorher}, 12 ) ({Nachher}, 0)}; % warning vue/require-default-prop
+\addplot [fill=warning04] coordinates { ({Vorher}, 12 ) ({Nachher}, 0)}; % warning vue/html-self-closing
+\addplot [fill=warning05] coordinates { ({Vorher}, 11 ) ({Nachher}, 0)}; % warning vue/first-attribute-linebreak
+\addplot [fill=warning06] coordinates { ({Vorher}, 10 ) ({Nachher}, 0)}; % warning vue/html-closing-bracket-newline
+\addplot [fill=warning07] coordinates { ({Vorher}, 8 ) ({Nachher}, 0)}; % warning vue/multiline-html-element-content-newline
+\addplot [fill=warning08] coordinates { ({Vorher}, 5 ) ({Nachher}, 0)}; % warning vue/html-closing-bracket-spacing
+\addplot [fill=warning09] coordinates { ({Vorher}, 3 ) ({Nachher}, 0)}; % warning vue/require-prop-types
+\addplot [fill=warning10] coordinates { ({Vorher}, 3 ) ({Nachher}, 0)}; % warning vue/attribute-hyphenation
+\addplot [fill=warning11] coordinates { ({Vorher}, 2 ) ({Nachher}, 0)}; % warning vue/html-self-closing
+\addplot [fill=warning12] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % warning vue/v-on-event-hyphenation
+\addplot [fill=warning13] coordinates { ({Vorher}, 1 ) ({Nachher}, 0)}; % warning vue/no-v-html
+\addplot +[fill=warning14, point meta=y,nodes near coords,nodes near coords align={anchor=south}]coordinates { ({Vorher}, 1 ) ({Nachher}, 1)}; % warning vue/mustache-interpolation-spacing
+
+
+\legend{
+error: html-indent,
+error: script-indent,
+error: require-v-for-key,
+error: multi-word-component-names,
+error: valid-v-for,
+error: valid-template-root,
+warning: max-attributes-per-line,
+warning: attributes-order,
+warning: singleline-html-element-content-newline,
+warning: require-default-prop,
+warning: html-self-closing,
+warning: first-attribute-linebreak,
+warning: html-closing-bracket-newline,
+warning: multiline-html-element-content-newline,
+warning: html-closing-bracket-spacing,
+warning: require-prop-types,
+warning: attribute-hyphenation,
+warning: html-self-closing,
+warning: v-on-event-hyphenation,
+warning: mustache-interpolation-spacing,
+warning: no-v-html,
+}
+\end{axis}
+\end{tikzpicture}
+
+\begin{tabularx}{\textwidth}{X | c | c}
+Regel & Vorher & Nachher \\ \hline
+error: html-indent & 26 & 0 \\
+error: script-indent & 17 & 0 \\
+error: require-v-for-key & 6 & 0 \\
+error: multi-word-component-names & 5 & 0 \\
+error: valid-v-for & 1 & 0 \\
+error: valid-template-root & 1 & 0 \\
+warning: max-attributes-per-line & 125 & 0 \\
+warning: attributes-order & 34 & 0 \\
+warning: singleline-html-element-content-newline & 26 & 0 \\
+warning: require-default-prop & 12 & 0 \\
+warning: html-self-closing & 12 & 0 \\
+warning: first-attribute-linebreak & 11 & 0 \\
+warning: html-closing-bracket-newline & 10 & 0 \\
+warning: multiline-html-element-content-newline & 8 & 0 \\
+warning: html-closing-bracket-spacing & 5 & 0 \\
+warning: require-prop-types & 3 & 0 \\
+warning: attribute-hyphenation & 3 & 0 \\
+warning: html-self-closing & 2 & 0 \\
+warning: v-on-event-hyphenation & 1 & 0 \\
+warning: mustache-interpolation-spacing & 1 & 0 \\
+warning: no-v-html & 1 & 1 \\
+\end{tabularx}
+
+Das Attribut \texttt{v-html} wird genutzt, um das Hilfe-Popup zu übersetzen. Die
+Übersetzungen für jede Sprache ist in einer separaten \texttt{HTML}-Datei gespeichert.
+Dies gibt dem Übersetzer einen großen Spielraum dafür, welche Inhalte in den Hilfe-Popups
+ausgegeben werden können.
+
diff --git a/30-qualitaetsheft/sections/coverage.tex b/30-qualitaetsheft/sections/coverage.tex
new file mode 100644
index 0000000..b8ba635
--- /dev/null
+++ b/30-qualitaetsheft/sections/coverage.tex
@@ -0,0 +1,59 @@
+\section{Codeabdeckung}
+
+\subsection{Einleitung}
+
+Die Codeabdeckung ist eine Methodik den Code weitflächig zu durchlaufen, um eine korrekte Verhaltensweise des Synchronisationsservers sicherzustellen.
+Die Knotenabdeckung stellt hierbei sicher, dass möglichst jede Instruktion im Code von mindestens einem Test durchlaufen wird.
+Die Zweigabdeckung stellt sicher, dass möglichst jeder Zweig (bspw. bei Verzweigungen) von mindestens einem Test durchlaufen wird.
+Schließlich gibt es noch die Pfadabdeckung, die sicherstellt, dass möglichst jeder Pfad von mindestens einem Test durchlaufen wird.
+
+In diesem Fall liegt der Fokus auf den ersten beiden Abdeckungen.
+Um die Codeabdeckung zu messen und zu dokumentieren, wurde das Tool JaCoCo verwendet.
+Viele Klassen des Projekts sind lediglich Model-Klassen oder dienen
+ausschließlich als Schicht zur Weiterleitung von Daten, weshalb
+diese bereits implizit abgedeckt sind.
+
+Zusätzlich werden durch das Tool Lombok, dem Framework Spring oder den JPA Repositories
+Methoden implizit eingebunden, welche dadurch nicht selbst implementiert werden müssen
+und bereits ausgiebig getestet sind.
+Dadurch ist eine explizite Abdeckung all dieser Methoden überflüssig,
+weshalb die Codeabdeckung nicht sonderlich hoch erscheint.
+
+In den Klassen erzielt, deren Funktionalität von Hand implementiert worden sind, ergibt sich wiederum mit den Tests eine hohe Codeabdeckung.
+
+\subsection{Insgesamte Abdeckung}
+\begin{figure}[h]
+ \centering
+ \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{assets/coverage/server.png}
+\end{figure}
+Model-Paket und Controller-Klassen sind implizit durch ServiceTests
+abgedeckt.
+
+
+\subsection{Authentication Service}
+\begin{figure}[h]
+ \centering
+ \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{assets/coverage/authenticationService.png}
+\end{figure}
+
+
+\subsection{Subscriptions Service}
+\begin{figure}[h]
+ \centering
+ \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{assets/coverage/subscriptionsService.png}
+\end{figure}
+
+\subsection{EpisodeAction Service}
+\begin{figure}[h]
+ \centering
+ \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{assets/coverage/episodeActionService.png}
+\end{figure}
+
+
+\subsection{Util Paket}
+\begin{figure}[h]
+ \centering
+ \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{assets/coverage/util.png}
+\end{figure}
+UpdateUrlsWrapper ist lediglich ein Platzhalter für die leere UpdateUrls Liste,
+welche zurückgeben wird, da diese Funktion nicht unterstützt wird. \ No newline at end of file
diff --git a/30-qualitaetsheft/sections/einleitung.tex b/30-qualitaetsheft/sections/einleitung.tex
new file mode 100644
index 0000000..b80d952
--- /dev/null
+++ b/30-qualitaetsheft/sections/einleitung.tex
@@ -0,0 +1,13 @@
+\section{Einleitung}
+
+Nach der Planung im Pflichten- und Entwurfsheft und der Implementierung im Implementierungsheft kommt im Qualitätssicherungsheft nun die Qualitätssicherung.
+In dieser wird die Implementierung ausgiebig getestet.
+Dabei werden unter anderem auch die im Pflichtenheft beschriebenen Testfälle abgearbeitet.
+
+Weitere Testfälle sorgen für eine möglichst große Knotenabdeckung des Codes. Dabei wird sichergestellt, dass alle Grundblöcke des Programms mindestens einmal durchlaufen werden.
+
+Ein Lasttest überprüft wie stark der Server belastet werden kann und wie sich die Last auf die Performance des Servers auswirkt.
+
+Es wird auch auf Probleme eingegangen, die während der Qualitätssicherung aufgefallen sind und wie gegen diese Probleme vorgegangen worden ist.
+
+Schließlich folgt noch ein Bericht über die Verbesserung des Code-Stils nach dem Checkstyle von Sun. \ No newline at end of file
diff --git a/30-qualitaetsheft/sections/frontend.tex b/30-qualitaetsheft/sections/frontend.tex
new file mode 100644
index 0000000..ae5be0e
--- /dev/null
+++ b/30-qualitaetsheft/sections/frontend.tex
@@ -0,0 +1,196 @@
+\section{Weboberfläche}
+
+Die Weboberfläche wird mit dem Frontend-Web-Framework Vue.js erstellt. Mit Vue
+werden wiederverwendbare, auf Datenänderungen reagierende Komponenten erstellt.
+Die Komponenten nutzen ein fertiges Aussehen von dem Frontend-CSS-Framework
+Bootstrap. Außerdem werden Icons der freien Schriftart fontawesome
+verwendet.
+
+An der generellen Struktur und wichtigen Komponenten hat sich in der
+Implementierung nichts großes zum Entwurf geändert. Einige Komponenten konnten
+in der Implementierung allerdings abstrahiert werden, sodass weniger Code
+dupliziert werden musste. Dazu gehören zum Beispiel die Komponenten, welche ein
+Eingabefeld bereit stellen.
+
+Durch eine gute Arbeitsteilung blieb genug Zeit, um auch einige Kann-Kriterien
+zu implementieren, weshalb ein paar Abhängigkeiten hinzugekommen sind. So werden
+jszip und file-saver benötigt, um das Kann-Kriterium RC3 umzusetzen, durch
+welches man Nutzerdaten im- und exportieren kann.
+
+Pinia konnten wir als Abhängigkeit entfernen, weil Vue von sich aus genügend
+Funktionalität bietet die Nutzerdaten global allen Komponenten bereit zu
+stellen.
+
+Anfangs überlegten wir den Wrapper \texttt{bootstrap-vue} zu verwenden, welcher
+Bootstrap-HTML-Strukturen als Vue-Komponenten bereit stellt. Dies hätte des
+Vorteil, dass man nur jene Komponenten importieren müsste, die man auch
+benötigt. Es stellte sich heraus, dass \texttt{vue-bootstrap} nicht mit neusten
+Version Vue3 kompatibel ist, weshalb wir uns entschieden Bootstrap wie gewohnt
+komplett einzubinden.
+
+Während der Implementierung sind wir auf die Bibliothek \texttt{VueUse}
+gestoßen, mit der man die Abhängigkeit \texttt{file-saver} und mehrere eigene
+Wrapper für Browser-\Gls{api}s ersetzen könnte. So kann man das \Gls{dashboard} auch in
+Zukunft noch weiter verbessern.
+
+Vom Frontend benötigte Abhängigkeiten:
+\begin{itemize}
+ \item vite
+ \item vue
+ \item vue-router
+ \item \textcolor{red}{\sout{Pinia} wird durch globale Vue-Interne \texttt{ref} ersetzt}
+ \item bootstrap
+ \item fontawesome
+ \item vue-i18n (Support für mehrere Sprachen)
+ \item \textcolor{Green}{dayjs (Rechnen und formatieren von Zeiten)}
+ \item \textcolor{Green}{jszip (erstellen von Im-/Exports)}
+ \item \textcolor{Green}{file-saver (Abstraktion für Datei-Speichern-Dialog)}
+\end{itemize}
+
+\subsection{Komponentendiagramm Web-Frontend}
+\includegraphics[width=\textwidth]{assets/diagrams/componentdiagram}
+
+\subsection{Hinzugefügte Komponenten}
+
+% PasswordInput
+% PasswordValidator
+% FloatingLabelInput
+% Loading
+% ErrorLog
+% ProgressTime
+
+\begin{minipage}{.7\linewidth}
+
+\subsubsection*{FloatingLabelInput}
+
+\begin{description}
+\item[Tag] \texttt{<FloatingLabelInput type label>}
+\item[Props] \mbox{} \\
+ \emph{type} \mbox{} Beschreibt den Inhalt des Eingabefelder. Handelt es sich
+ um eine E-Mail, ein Passwort oder nur Text? \\
+ \emph{label} \mbox{} Das Label wird als Platzhalter und kleine Überschrift
+ angezeigt.
+\item[Beschreibung] Abstrahiert eine HTML-Struktur von Bootstrap, um ein schönes
+ Eingabefeld anzuzeigen.
+\end{description}
+\end{minipage}
+\begin{minipage}{.3\linewidth}
+ \begin{figure}[H]
+ \includegraphics[width=\textwidth]{assets/floatinglabelinput.png}
+ \end{figure}
+\end{minipage}
+
+
+\vspace{.5cm}
+
+\begin{minipage}{.7\linewidth}
+
+\subsubsection*{PasswordInput}
+
+\begin{description}
+\item[Tag] \texttt{<PasswordInput type label>}
+\item[Props] \mbox{} \\
+ \emph{label} \mbox{} Das Label wird als Platzhalter und kleine Überschrift
+ angezeigt.
+\item[Beschreibung] Erweitert den FloatingLabelInput um einen Knopf mit dem die
+ Sichtbarkeit des Eingabefeldes gewechselt werden kann. Dabei wird intern der
+ Typ des Eingabefeldes zwischen Text and Passwort gewechselt.
+\end{description}
+\end{minipage}
+\begin{minipage}{.3\linewidth}
+ \begin{figure}[H]
+ \includegraphics[width=\textwidth]{assets/passwordinput.png}
+ \end{figure}
+\end{minipage}
+
+
+\vspace{.5cm}
+
+\begin{minipage}{.7\linewidth}
+
+\subsubsection*{PasswordValidator}
+
+\begin{description}
+\item[Tag] \texttt{<PasswordValidator>}
+\item[Beschreibung] Besteht aus zwei PasswordInputs und überprüft diese auf
+ Gleichheit und Kriterien für eine gutes Passwort.
+\end{description}
+\end{minipage}
+\begin{minipage}{.3\linewidth}
+ \begin{figure}[H]
+ \includegraphics[width=\textwidth]{assets/passwordvalidator.png}
+ \end{figure}
+\end{minipage}
+
+
+\vspace{.5cm}
+
+\begin{minipage}{.7\linewidth}
+
+\subsubsection*{Loading}
+
+\begin{description}
+\item[Tag] \texttt{<Loading waitingFor>...<Loading/>}
+\item[Props] \mbox{} \\
+ \emph{waitingFor} \mbox{} Eine Referenz auf eine Bedingung wann die Kinder
+ der Komponente gezeigt werden sollen.
+\item[Beschreibung] Zeigt solange ein Ladesymbol an, bis die Bedingung in
+ \texttt{waitingFor} erfüllt ist und stattdessen die Kinder der Komponente
+ gezeigt werden.
+\end{description}
+\end{minipage}
+\begin{minipage}{.3\linewidth}
+ \begin{figure}[H]
+ \includegraphics[width=\textwidth]{assets/loading.png}
+ \end{figure}
+\end{minipage}
+
+
+\vspace{.5cm}
+
+\begin{minipage}{.7\linewidth}
+
+\subsubsection*{ProgressTime}
+
+\begin{description}
+\item[Tag] \texttt{<ProgressTime unix>}
+\item[Props] \mbox{} \\
+ \emph{unix} \mbox{} Anzahl an Sekunden.
+\item[Beschreibung] Nimmt eine Anzahl an Sekunden und gibt an wie viele Stunden,
+ Minuten und Sekunden die Anzahl entspricht.
+\end{description}
+\end{minipage}
+\begin{minipage}{.3\linewidth}
+ \begin{figure}[H]
+ \includegraphics[width=\textwidth]{assets/progresstime.png}
+ \end{figure}
+\end{minipage}
+
+
+\vspace{.5cm}
+
+\begin{minipage}{.7\linewidth}
+
+\subsubsection*{ErrorLog}
+
+\begin{description}
+\item[Tag] \texttt{<ErrorLog>}
+\item[Beschreibung] Zeigt eine Liste von Warnungen an, welche aus einem globalen
+ Zustandsspeicher geladen werden.
+\end{description}
+\end{minipage}
+\begin{minipage}{.3\linewidth}
+ \begin{figure}[H]
+ \includegraphics[width=\textwidth]{assets/errorlog.png}
+ \end{figure}
+\end{minipage}
+
+
+\vspace{.5cm}
+
+\subsubsection*{Dashboard/FormLayout}
+
+\begin{description}
+\item[Tag] \texttt{<DashboardLayout> <FormLayout>}
+\item[Beschreibung] Fügt den Kindern einen Seitenabstand hinzu.
+\end{description}
diff --git a/30-qualitaetsheft/sections/glossar.tex b/30-qualitaetsheft/sections/glossar.tex
new file mode 100644
index 0000000..b664e58
--- /dev/null
+++ b/30-qualitaetsheft/sections/glossar.tex
@@ -0,0 +1,391 @@
+\makeglossaries
+
+\newglossaryentry{spa}
+{
+ name=Single-Page-Application,
+ description={
+ ist ein Webseiten-Modell, bei welchem dem Nutzer nur ein Webdokument
+ bereitgestellt wird. Mit einem Skript wird der Inhalt der Seite
+ dynamisch mit Daten einer API befüllt. Außerdem verwaltet die Seite
+ (nicht der Server), welcher Inhalt bei welchem Pfad angezeigt wird. Dies
+ erzeugt geringere Serverlast und eine bessere Nutzererfahrung, da die
+ Seitenstruktur beim Laden von neuen Inhalten erhalten bleibt}
+}
+
+\newglossaryentry{packagemanager}
+{
+ name=Paketmanager,
+ description={
+ ist ein Programm, welches Pakete und dessen Abhängigkeiten verwaltet,
+ installiert, entfernt und aktualisiert. Pakete können andere Programme,
+ Plugins oder Software-Bibliotheken sein}
+}
+
+\newglossaryentry{bundler}
+{
+ name=Bundler,
+ description={
+ ist ein Programm, welches genutzte Teile von Abhängigkeiten eines
+ Software-Projekts in passender Reihenfolge zusammensucht und daraus
+ Dateien erstellt, die für den Nutzer bereitgestellt werden können. Dabei
+ kann der Bundler mit zusätzlichen Modulen Dateien erzeugen, die
+ rückwärtskompatibel oder für den Nutzer schwerer einsehbar sind}
+}
+
+\newglossaryentry{java}
+{
+ name=Java,
+ description={
+ ist eine objekt-orientierte interpretierte kompilierte
+ Programmiersprache, welche plattformunabhängig auf einer virtuellen
+ Maschine ausgeführt wird}
+}
+
+\newglossaryentry{db}
+{
+ name=Datenbank,
+ plural=Datenbanken,
+ description={
+ ist ein System um Daten persistent zu speichern und effizient zu
+ verwalten. Am meisten verbreitet sind relationale Datenbanken, welche
+ Daten in Tabellen mit Referenzen zu Einträgen anderer Tabellen
+ speichern. Programme können dann über eine Anfragesprache (Structured
+ Query Language - \Gls{SQL}) komplexe Operationen auf den Daten ausführen}
+}
+
+\newglossaryentry{docker}
+{
+ name=Docker,
+ description={
+ ist ein Programm, das virtualisierte Container ausführt. Ein Programm in
+ so einem Container läuft in seiner eigenen virtuellen Umgebung, wodurch
+ das Host-System sicher bleibt. Zudem lassen sich die Container leicht
+ auf andere Systeme verteilen}
+}
+
+% RESTfull-API, JSON, RSS-Feed, Salting and Hasing, OAuth, Cookie, Garbage
+% Collection, DSGVO, Podcast, Podcatcher, Episode, Gpodder,
+
+\newglossaryentry{podcatcher}
+{
+ name=Podcatcher,
+ plural=Podcatchern,
+ description={
+ ist ein Programm, über welches man Podcasts entdecken, abonnieren und
+ Episoden von Podcasts hören kann. Mit einem Account auf einer Plattform,
+ welche eine Gpodder-API zur Verfügung stellt, können Ereignisse, die von
+ einem Nutzer ausgehen, auf anderen Podcatchern des Nutzers
+ synchronisiert werden}
+}
+
+\newglossaryentry{podcast}
+{
+ name=Podcast,
+ description={
+ ist ein RSS-Feed, dessen Einträge die Episoden darstellen}
+}
+
+\newglossaryentry{episode}
+{
+ name=Episode,
+ plural=Episoden,
+ description={
+ ist ein Eintrag in einem Podcast. Eine URL in dem Eintrag zeigt auf eine
+ Medien-Datei, welche vom Podcatcher abgespielt werden kann}
+}
+
+\newglossaryentry{rest-api}
+{
+ name=RESTful-API,
+ description={
+ ist ein Schnittstellenentwurf über das Hypertext Transfer Protocol
+ (HTTP), bei dem die Schnittstellen strukturiert als Pfad an einem
+ Endpunkt erreichbar sind. Mittels verschiedener HTTP-Methoden können an
+ der Schnittstelle Daten abgefragt (GET), gesendet (PUT), gelöscht
+ (DELETE) oder geändert (POST) werden. Die Daten, die über die
+ Schnittstelle gesendet werden liegen meist im JSON-Format vor}
+}
+
+
+\newglossaryentry{gpodder}
+{
+ name=Gpodder-API,
+ description={
+ wird von gpodder.net benutzt und entwickelt. Die API wird als
+ Schnittstelle zwischen Podcatchern und Podcast Synchronisationsservern
+ verwendet. Weitere Details sind unter
+ "https://gpoddernet.readthedocs.io/en/latest/api/" zu finden}
+}
+
+\newglossaryentry{json}
+{
+ name=JSON,
+ description={
+ (JavaScript Object Notation) ist ein Datenformat und wird zur
+ Übertragung von Strukturen und Daten eingesetzt. JSON besteht dabei aus
+ grundlegenden Datentypen sowie Objekten mit Schlüssel-Wert Paaren und
+ Listen}
+}
+
+\newglossaryentry{oauth}
+{
+ name=OAuth,
+ description={
+ (Open Authorization) ist ein offenes Protokoll, welches es Nutzern
+ ermöglicht, sich mit bereits bestehenden Accounts bei anderen Diensten
+ zu registrieren. Dabei werden benötigte Daten für die Registrierung über
+ die bereitgestellte Schnittstelle zur Verfügung gestellt}
+}
+
+\newglossaryentry{garbage-collection}
+{
+ name=Garbage Collection,
+ description={
+ ist eine automatische Speicherbereinigung, welche nicht mehr benötigten
+ Speicherplatz wieder freigibt. Die Bereinigung kann dabei in determinierten
+ Zeitintervallen erfolgen oder durch bestimmte Ereignisse ausgelöst
+ werden}
+}
+
+\newglossaryentry{salt-hash}
+{
+ name=Salting und Hashing,
+ description={
+ ist eine Methode um Passwörter so zu kodieren, dass sie nicht als
+ Klartext gespeichert werden und auch sicher vor Hash-Wörterbüchern sind.
+ Dafür wird dem Passwort ein bekanntes Wort, der Salt, angefügt, bevor
+ aus dem kompletten Wort eine Prüfsumme, ein Hash, generiert wird. Beim
+ Anmelden wird die Prüfsumme der Anmeldung mit der bekannten
+ Prüfsumme des Passworts verglichen}
+}
+
+\newglossaryentry{rss}
+{
+ name=RSS,
+ description={
+ (Really Simple Syndication) zeigt strukturiert Listen von Nachrichten
+ an. Die Änderungen werden im XML-Format in sogenannte RSS-Dateien
+ geschrieben, welche über einen Link abgerufen werden können}
+}
+
+\newglossaryentry{dsgvo}
+{
+ name=Datenschutz-Grundverordnung,
+ description={
+ (DSGVO) ist eine im europäischen Wirtschaftsraum
+ geltende Verordnung. Sie sorgt für eine Reglementierung bei der
+ Verarbeitung personenbezogener Daten. Unter anderem muss einsehbar sein,
+ welche Daten von Nutzern erhoben werden. Außerdem muss für einen Nutzer
+ die Möglichkeit bestehen, seine erhobenen Daten abrufen zu können}
+}
+
+\newglossaryentry{push-pull}
+{
+ name=Push und Pull,
+ description={
+ sind Methoden, um Daten auszutauschen. Bei der Pull-Methode
+ stellt Akteur A einem Akteur B eine Anfrage auf Daten und erhält diese
+ als Antwort. Damit Akteur A und B immer auf dem selben Stand sind, muss
+ Akteur A chronisch Anfragen an Akteur B stellen. Im Gegensatz dazu steht
+ die Push-Methode, bei der Akteur B den Akteuren mitteilt, dass er neue
+ Änderungen hat. Dafür muss Akteur B allerdings wissen mit welchen
+ anderen Akteuren er in Verbindung steht und diese Verbindung aufrecht
+ erhalten}
+}
+
+\newglossaryentry{ui-lib}
+{
+ name=UI-Bibliothek,
+ plural=UI-Bibliotheken,
+ description={
+ kümmert sich um das Layout einer Webseite. Dabei unterscheidet man
+ zwischen Design-Bibliotheken (wie Bootstrap), welche fertige
+ UI-Komponenten bereitstellen, und Layout-Bibliotheken (wie Vue oder
+ React.js), welche die Komponenten basierend auf Daten dynamisch
+ anzeigen}
+}
+
+\newglossaryentry{responsive}
+{
+ name=Responsive,
+ description={
+ Design ist ein Design-Prinzip für Webseiten, bei dem die selbe Webseite ihre
+ Komponenten dynamisch der Bildschirmbreite anpasst}
+}
+
+\newglossaryentry{pseudoprotocol}
+{
+ name=Pseudoprotokoll,
+ description={
+ ist ein URL-Schema, auf das Webseiten hören können, wenn sie sich das
+ URL-Schema im Browser anmelden. Bekannt Pseudoprotokolle sind:
+ ,,mailto:'', ,,tel:'' oder ,,irc:''}
+}
+
+\newglossaryentry{dashboard}
+{
+ name=Dashboard,
+ description={
+ ist die erste Seite auf der man landet, wenn man angemeldet ist}
+}
+
+\newglossaryentry{abo}
+{
+ name=Abonnement,
+ description={
+ ist ein abonnierter Podcast}
+}
+
+\newglossaryentry{discovery}
+{
+ name=Discovery,
+ description={
+ ist ein Feature der Gpodder-API, welches dem Nutzer eine Reihe von
+ Podcasts zum abonnieren anbietet}
+}
+
+\newglossaryentry{session-token}
+{
+ name=Session-Token,
+ description={
+ ist ein Wort, dass vom Client gespeichert wird solange der Nutzer
+ eingeloggt ist und bei jeder Anfrage an den Server mitgeschickt wird.
+ Der Server kann den Session-Token einem Nutzer zuordnen und so mit
+ nutzerspezifischen Daten antworten}
+}
+
+\newglossaryentry{cookie}
+{
+ name=Cookie,
+ description={
+ ist ein kleiner webseitenspezifischer Speicher im Browser, welcher vom
+ Server und von der Webseite gesetzt werden kann und bei jeder weiteren
+ Anfrage an den Server mitgesendet wird. Cookies bleiben entweder
+ temporär im Browserspeicher, bis der Browser geschlossen wird oder
+ permanent, bis ein optionales Verfallsdatum erreicht ist}
+}
+
+\newglossaryentry{uiComponent}
+{
+ name=UI-Komponente,
+ plural=UI-Komponenten,
+ description={
+ In Vue.js werden die grafischen Elemente einer Webseite in einzelne
+ Komponenten zerteilt.
+ Diese reagieren automatisch auf Änderungen und können ohne Neuladen
+ der Seite ihr Aussehen verändern und somit Änderungen direkt anzeigen}
+}
+
+\newglossaryentry{spring}
+{
+ name=Spring,
+ description={
+ Ein Java-Framework, welches die Entwicklung von Web-Applikationen erleichtert.
+ Dazu wird eine Reihe von Werkzeugsets zur Verfügung gestellt.
+ Unter anderem sind das Spring Web für das Erstellen von Webanwendungen,
+ Spring Security für die Verwaltung von Benutzerauthentifizierungen und
+ Spring Data JPA für die Arbeit mit relationalen Datenbanken
+ }
+}
+
+\newglossaryentry{api}
+{
+ name=API,
+ plural=APIs,
+ description={
+ Eine Schnittstelle, welche es ermöglicht auf Funktionalitäten einer Anwendung
+ zuzugreifen. APIs für Webanwendungen heißen WebAPIs.
+ Ein Beispiel für eine WebAPI ist die REST-API
+ }
+}
+
+\newglossaryentry{business}
+{
+ name=Geschäftslogik,
+ description={
+ Eine Schicht in der Anwendungsentwicklung, in der die Art und Weise, wie das
+ Programm auf Eingaben reagiert, wie Daten verarbeitet und wie sie gespeichert
+ werden sollen, festgelegt ist
+ }
+}
+
+\newglossaryentry{solid}
+{
+ name=SOLID,
+ description={
+ Eine Sammlung an Prinzipien, welche zu gutem objektorientierten Design führen soll.
+ Jedes Prinzip steht für einen Buchstaben in SOLID:
+ \textbf{S}ingle-Responsibility Prinzip,
+ \textbf{O}pen-Closed Prinzip,
+ \textbf{L}iskovsches Substitutionsprinzip,
+ \textbf{I}nterface Segregation Prinzip und
+ \textbf{D}ependency Inversion Prinzip
+ }
+}
+
+\newglossaryentry{crud}
+{
+ name=CRUD,
+ description={
+ CRUD steht für \textbf{C}reate, \textbf{R}ead, \textbf{U}pdate und \textbf{D}elete.
+ Hierbei handelt es sich um die grundlegenden Funktionen einer Anwendung,
+ die mit einer Datenbank arbeitet.
+ Hierbei können Daten angelegt, abgerufen, aktualisiert und gelöscht werden.
+ Auch in Web-Applikationen ist CRUD mit HTTP über die Anfragen POST, GET, PUT und DELETE
+ vertreten
+ }
+}
+
+\newglossaryentry{SQL}
+{
+ name=SQL,
+ description={
+ SQL (Structured Query Language) ist eine Sprache, die einen strukturierten Zugriff auf Datenbanken ermöglicht.
+ Daten können hierbei hinzugefügt, abgefragt, geändert und gelöscht werden.
+ Das besondere hierbei ist der strukturierte Zugriff auf Daten, indem explizit Daten mit bestimmten Kriterien und
+ Relationen ausgewählt und bearbeitet werden können.
+ SQL wird fast von allen verbreiteten Datenbanksystemen unterstützt
+ }
+}
+
+\newglossaryentry{Base64}
+{
+ name=Base64,
+ description={
+ Mithilfe von Base64 können 8-Bit-Binärdaten in eine ASCII-Zeichenkette
+ kodiert werden. So werden zum Beispiel E-Mail-Anhänge versendet
+ }
+}
+
+\newglossaryentry{JSONP}
+{
+ name=JSONP,
+ description={
+ JSONP ermöglicht die Übertragung von JSON-Daten zwischen verschiedenen Domains.
+ Dies wäre durch die Same-Origin-Policy nicht möglich.
+ JSONP nutzt allerdings die Tatsache aus,
+ dass sich Skripte domainübergreifend übertragen lassen.
+ Dazu werden die JSON-Daten als Argument einer übergebenen Funktion über
+ ein Skript-Element eingebunden
+ }
+}
+
+\newglossaryentry{Apdex}
+{
+ name=Apdex,
+ description={
+ Der Application Performance Index ist eine Methode zur Bewertung der
+ Benutzerfreundlichkeit von Anwendungen bezüglich ihrer Antwortszeiten.
+ Dabei gibt es die Stufen zufriedenstellend, tolerierbar und
+ frustrierend, welche analog von 1 absteigend bis 0 angegeben werden.
+ }
+}
+
+\newglossaryentry{Lasttest}
+{
+ name=Lasttest,
+ description={
+ ist ein Test, mit welchem man die Stabilität und Robustheit
+ eines Programms testen kann, indem man ihn einer großen Last aussetzt.
+ }
+}
diff --git a/30-qualitaetsheft/sections/lasttest.tex b/30-qualitaetsheft/sections/lasttest.tex
new file mode 100644
index 0000000..ed5d4a9
--- /dev/null
+++ b/30-qualitaetsheft/sections/lasttest.tex
@@ -0,0 +1,105 @@
+\section{\Glspl{Lasttest}}
+
+\subsection{Einleitung}
+
+\Glspl{Lasttest} sind sinnvoll, um das Verhalten eines Programmes unter großer Last
+zu testen um somit dessen Belastungsgrenze zu erreichen.
+Dadurch wird das Programm auf Stabilität getestet und man erhält
+einen Eindruck davon, wie performant das Programm ist.
+Auch kann durch die erhaltenen Ergebnisse abgeschätzt werden,
+welche Hardware für den erwarteten Einsatzzweck benötigt wird.
+
+\subsection{Verwendete Software}
+
+Da der \Gls{podcast}synchronisationsserver ein Webserver ist und über HTTP
+kommuniziert, wird das Tool \enquote{Apache JMeter} verwendet, um
+die \Glspl{Lasttest} durchzuführen.
+Mit diesem Tool kann mithilfe eines sogenannten Testplans
+systematisch HTTP Anfragen an den Server gestellt werden.
+Während dieser Testplan läuft, sammelt das Tool verschiedene Daten über die Performanz des Services,
+wie zum Beispiel die Anzahl der Anfragen, die pro Sekunde bearbeitet werden.
+Im Anschluss werden die Testergebnisse grafisch zur Verfügung gestellt.
+
+\subsection{Tests}
+Um zu testen, ob der Synchronisationsserver unter voller Belastung
+fehlerfrei arbeitet, wurden alle Schnittstellen, die die \Gls{podcatcher} zur
+Synchronisation nutzen, jeweils zum Testplan als eigene Threadgruppe
+hinzugefügt.
+Damit ist es möglich, alle relevanten Schnittstellen
+über einen längeren Zeitraum kontinuierlich zu belasten.
+So wird ausgeschlossen, dass es innerhalb des Programms zu gegenseitigen
+Interferenzen kommt, wenn alle Bereiche zur selben Zeit ausgelastet werden.
+Ein weiterer Vorteil des gleichzeitigen Belastens ist, dass
+Engpässe, welche das Programm ausbremsen, leichter identifiziert werden können.
+
+Um einen Performanzvergleich zwischen unterschiedlicher Hardware zu erhalten,
+wurden die Tests in gleicher Konfiguration einmal auf einem System,
+welches den im Pflichtenheft definierten Mindestanforderungen
+(2 Kerne und 2GB RAM) entspricht und
+einem besseren System (8 Kerne und 32GB RAM) getestet.
+
+\newpage
+
+\subsection{Testergebnisse}
+\subsubsection{Genaue Testwerte}
+\textit{2-Kern System:}
+\begin{figure}[h]
+ \centering
+ \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{assets/lasttest/minimumSpecsTable.png}
+\end{figure}
+
+\textit{8-Kern System:}
+\begin{figure}[h]
+ \centering
+ \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{assets/lasttest/goodSpecsTable.png}
+\end{figure}
+
+\subsection{Anfragen pro Sekunde}
+
+Aus den Testdaten ist ersichtlich, dass die im Pflichtenheft für den Synchronisationsserver
+als Musskriterium aufgeführte Eigenschaft, 50 Anfragen pro Sekunde bewältigen zu können,
+nicht für jede Hardwarekonfiguration möglich ist.
+Denn im Gegensatz zur 8-Kern CPU, welche durchschnittlich 88,93 Transaktionen pro Sekunde
+verarbeitet, sind mit den Mindestanforderungen durchschnittlich nur 10,85 Anfragen
+pro Sekunde möglich.
+
+\newpage
+\subsubsection{Application Performance Index}
+
+\textit{2-Kern System:}
+\begin{figure}[h]
+ \centering
+ \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{assets/lasttest/minimumSpecsApdex.png}
+\end{figure}
+
+\textit{8-Kern System:}
+\begin{figure}[h]
+ \centering
+ \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{assets/lasttest/goodSpecsApdex.png}
+\end{figure}
+
+\newpage
+
+Der Application Performance Index (kurz: \Gls{Apdex}) gibt an, wie benutzerfreundlich
+eine Webseite bezüglich ihrer Antwortzeiten bei Anfragen ist.
+Dabei stellt \enquote{1} die beste Nutzerfreundlichkeit dar und \enquote{0} die schlechteste.
+
+Verglichen mit den genauen Testwerten, ist ersichtlich, dass ein System mit den Mindestanforderungen zwar eine akzeptable Leistung erbringt, allerdings die vom \Gls{Apdex} definierte Frustrationsgrenze überschreiten kann:
+
+\textit{2-Kern System:}
+\begin{figure}[h]
+ \centering
+ \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{assets/lasttest/minimumSpecsResponse.png}
+\end{figure}
+
+\textit{8-Kern System:}
+\begin{figure}[h]
+ \centering
+ \includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{assets/lasttest/goodSpecsResponse.png}
+\end{figure}
+
+Bei Ausführung des Synchronisationsservers auf einem 2-Kern System kann somit
+keine zufriedenstellende Nutzererfahrung garantiert werden, sobald der Server einer starken
+Last ausgesetzt ist.
+
+Um eine zufriedenstellende Erfahrung zu garantieren, ist bessere Hardware eine hinreichende Bedingung. \ No newline at end of file
diff --git a/30-qualitaetsheft/sections/problems.tex b/30-qualitaetsheft/sections/problems.tex
new file mode 100644
index 0000000..fb5bdcb
--- /dev/null
+++ b/30-qualitaetsheft/sections/problems.tex
@@ -0,0 +1,65 @@
+\section{Probleme}
+
+\vspace{-.2cm}
+In diesem Kapitel wird näher auf die Probleme eingegangen, die sich ergeben
+haben, aus welchem Grund sie sich ergeben haben und wie sie schließlich behoben
+wurden.
+
+\vspace{-.2cm}
+\subsection{Falsche Zeitangaben}
+
+\begin{description}
+
+\item[Beschreibung] Im Frontend wurden die Zeiten, wann eine
+\Gls{podcast}episode zuletzt gehört wurde und wann ein \Gls{podcast} abonniert
+worden ist, falsch angezeigt. Hierbei kann eine Aktion entweder zu weit in der
+Vergangenheit oder sogar in der Zukunft liegen.
+\item[Ursache] Die Bibliothek hat die Zeiten in der lokalen, statt der
+universellen Zeit berechnet. Aufgrund der Differenz zwischen Zeitzonen kam es
+hierbei zu größer werdenden Zeitabständen.
+\item[Behebung] Die Bibliotheksfunktionen wurden so angepasst, dass sie die
+Zeiten explizit nach der universellen Zeitzone (UTC) berechnet.
+
+\end{description}
+
+
+\subsection{AntennaPod Fehlermeldung}
+
+\begin{description}
+
+\item[Beschreibung] Beim Hochladen von \Gls{abo}änderungen gab AntennaPod einen Fehler aus.
+\item[Ursache] Es wurde bei der Übertragung ein Parameter mit falschem Parameternamen gesendet.
+Hierbei handelt es sich um den Parameter \texttt{updateURLs}.
+\item[Behebung] \texttt{updateURLs} wurde umbenannt zu
+\texttt{update\textunderscore urls}. Die
+geschah durch das Hinzufügen von \texttt{@JsonProperty(value =
+''update\textunderscore urls'')} in der \texttt{UpdateURLsWrapper} Klasse im
+\texttt{util} Paket.
+
+\end{description}
+
+\subsection{Doppelte Speicherung von EpisodeActions}
+
+\begin{description}
+
+\item[Beschreibung] Beim speichern von \Gls{episode}Actions ergab sich in
+manchen Fällen die Situation, dass \Gls{episode}Actions mehrfach gespeichert
+worden sind. Jede \Gls{episode} besitzt pro Benutzer eine \Gls{episode}Action.
+In diesem Fall gab es mehrere \Gls{episode}Actions pro Benutzer für je eine
+\Gls{episode}.
+\item[Ursache] Es werden alle \Gls{episode}Actions in der \Gls{db} gespeichert,
+die neuer als die aktuellste \Gls{episode}Action in der \Gls{db} sind. Nach
+einem Speichervorgang sollte die ältere \Gls{episode}Action gelöscht werden. Da
+\Gls{spring} jedoch aus Effizienzgründen nach diesem Schema mehrere Daten
+sammelt und erst dann abspeichert, wird nur einer der älteren Einträge gelöscht.
+Dadurch werden im Durchschnitt mehr \Gls{episode}Actions gespeichert, als
+\Gls{episode}Actions entfernt werden.
+\item[Behebung] Die empfangenen \Gls{episode}Actions werden vor dem Speichern in
+der \Gls{db} bereits nach den jeweils aktuellsten \Gls{episode}Actions für eine
+\Gls{episode} aussortiert. Damit wird letztlich nur eine \Gls{episode}Action in
+die \Gls{db} geschrieben und auch nur eine ältere \Gls{episode}Action zu der
+\Gls{episode} gelöscht, womit jede \Gls{episode} für jeden User weiterhin nur
+eine \Gls{episode}Action besitzt.
+
+\end{description}
+
diff --git a/30-qualitaetsheft/sections/testfaelle.tex b/30-qualitaetsheft/sections/testfaelle.tex
new file mode 100644
index 0000000..7d8669c
--- /dev/null
+++ b/30-qualitaetsheft/sections/testfaelle.tex
@@ -0,0 +1,182 @@
+\section{Testfälle}
+
+Dieses Kapitel befasst sich mit allen im Pflichtenheft genannten Tests für den Synchronisationsserver.
+Die Tests werden dabei aufgeteilt in Tests, die im Frontend stattfinden und Tests, die das Backend betreffen.
+
+\subsection{Frontend}
+
+Dieser Abschnitt enthält alle Tests, die das Frontend betreffen.
+
+\subsubsection{Registrierung}
+
+Eine Person möchte sich einen Account auf dem Server anlegen.
+
+\begin{table}[h!]
+\begin{tabularx}{\textwidth}{X|c}
+Teilschritt & Bestanden\\\hline
+Webseite aufrufen & Ja\\
+Registrierungsseite aufrufen & Ja\\
+Daten ohne Passwort zur Wiederholung eintragen & Ja\\
+Daten mit zweimal Passwort eingeben & Ja\\
+Registrierungslink drücken & Ja\\
+Registrierungslink abgelaufen & Ja\\
+Registrierungslink nach 24 Stunden anklicken & Ja\\
+Mit selber E-Mail nochmals registrieren & Ja
+\end{tabularx}
+\end{table}
+
+\subsubsection{Passwort Anforderungen}
+
+Es wird getestet, ob das eingegebene Passwort die Mindestanforderungen erfüllen muss, um akzeptiert zu werden.
+
+\begin{table}[h!]
+\begin{tabularx}{\textwidth}{X|c}
+Teilschritt & Bestanden\\\hline
+Passwort \enquote{test} nicht akzeptiert & Ja\\
+Passwort \enquote{Test123} nicht akzeptiert & Ja\\
+Passwort \enquote{TEST123?} nicht akzeptiert & Ja\\
+Passwort \enquote{Test123!?} akzeptiert & Ja
+\end{tabularx}
+\end{table}
+
+\newpage
+
+\subsubsection{Anmeldung}
+
+Der Benutzer ist registriert und möchte sich nun mit dem registrierten Account anmelden.
+Die Option \enquote{Angemeldet bleiben} wird nicht verwendet.
+Hierbei ist zu beachten, dass die Anmeldung seit der Implementierungsphase mit einem Benutzernamen statt der E-Mail Adresse erfolgt.
+
+\begin{table}[h!]
+\begin{tabularx}{\textwidth}{X|c}
+Teilschritt & Bestanden\\\hline
+Webseite aufrufen & Ja\\
+Ohne Eingabe \enquote{Anmelden} drücken & Ja\\
+Nur Nutzernamen eingeben und \enquote{Anmelden} drücken & Ja\\
+Nutzername und falsches Passwort eingeben, anschließend \enquote{Anmelden} drücken & Ja\\
+Nutzername und richtiges Passwort eingeben, anschließen \enquote{Anmelden} drücken & Ja\\
+\enquote{Angemeldet bleiben} Option testen & Ja\\
+\enquote{Angemeldet bleiben} Option deaktiviert testen & Ja
+\end{tabularx}
+\end{table}
+
+\subsubsection{Passwort ändern}
+
+Der Benutzer ist registriert, kennt seine Anmeldedaten und möchte nun das Passwort ändern.
+Der Benutzer ist zu Beginn bereits angemeldet.
+
+\begin{table}[h!]
+\begin{tabularx}{\textwidth}{X|c}
+Teilschritt & Bestanden\\\hline
+Zu \enquote{Einstellungen} Menü über das Profil wechseln & Ja\\
+Ohne Eingabe \enquote{Passwort ändern} drücken & Ja\\
+Falsches altes Passwort eingeben und \enquote{Passwort ändern} drücken & Ja\\
+\makecell[l]{Richtiges altes Passwort und neues Passwort, das nicht die Kriterien \\ erfüllt eingeben} & Ja\\
+Richtiges altes Passwort und akzeptiertes neues Passwort eingeben & Ja\\
+Der Benutzer kann sich abmelden & Ja\\
+Das alte Passwort wird beim Anmelden nicht mehr akzeptiert & Ja\\
+Der Benutzer kann sich mit dem neuen Passwort anmelden & Ja
+\end{tabularx}
+\end{table}
+
+\newpage
+
+\subsubsection{Passwort vergessen}
+
+Der Benutzer ist registriert, kennt die E-Mail Adresse jedoch nicht das Passwort mit dem er sich registriert hat.
+Ziel hierbei ist es das Passwort zurückzusetzen.
+
+\begin{table}[h!]
+\begin{tabularx}{\textwidth}{X|c}
+Teilschritt & Bestanden\\\hline
+Webseite aufrufen & Ja\\
+\enquote{Passwort vergessen} Seite aufrufen & Ja\\
+E-Mail Adresse eingeben und \enquote{Bestätigen} Knopf drücken & Ja\\
+Gesendeten Link innerhalb von 24 Stunden anklicken & Ja\\
+Auf \enquote{Passwort zurücksetzen} Seite neues nicht akzeptiertes Passwort eingeben & Ja\\
+Auf \enquote{Passwort zurücksetzen} Seite neues akzeptiertes Passwort eingeben & Ja\\
+Auf Anmeldeseite versuchen mit altem Passwort anzumelden & Ja\\
+Auf Anmeldeseite mit neuem Passwort anmelden & Ja\\
+Gesendeten Link nach 24 Stunden anklicken & Ja\\
+Nach Zurücksetzen vom Passwort erneut auf Link klicken & Nein (technisch bedingt)
+\end{tabularx}
+\end{table}
+
+\subsubsection{Account löschen}
+
+Der Benutzer ist registriert und möchte den Account löschen.
+Dazu ist der Benutzer zu Beginn bereits angemeldet und befindet sich in der Einstellungsseite des Profils.
+Es sei zu beachten, dass die Aktion den Account zu löschen in die Einstellungsseite verschoben wurde und nicht über eine extra Seite stattfindet.
+Auch verlangt die Aktion den Account zu löschen nur noch das Passwort.
+
+\begin{table}[h!]
+\begin{tabularx}{\textwidth}{X|c}
+Teilschritt & Bestanden\\\hline
+Ohne Eingabe \enquote{Account löschen} drücken & Ja\\
+Mit falschem Passwort als Eingabe \enquote{Account löschen} drücken & Ja\\
+Mit richtigem Passwort als Eingabe \enquote{Account löschen} drücken & Ja\\
+Versuchen sich mit gelöschtem Account anzumelden & Ja
+\end{tabularx}
+\end{table}
+
+\subsubsection{Anleitung ansehen}
+
+Der Benutzer ist registriert und angemeldet und möchte die Anleitung einsehen.
+
+\begin{table}[h!]
+\begin{tabularx}{\textwidth}{X|c}
+Teilschritt & Bestanden\\\hline
+Auf \enquote{Hilfe} Button im \Gls{dashboard} klicken & Ja
+\end{tabularx}
+\end{table}
+
+\newpage
+
+\subsection{Synchronisation}
+
+Die folgenden Tests betreffen das Synchronisationsfeature des Synchronisationsservers.
+Hierbei ist der Benutzer bereits auf dem Server registriert und bestätigt.
+Auch ist der Benutzer in allen Fällen auf einem \Gls{podcatcher}, der die \Gls{gpodder} unterstützt, über den registrierten Account angemeldet.
+
+\subsubsection{\Gls{podcast} abonnieren}
+
+Der Benutzer abonniert auf einem \Gls{podcatcher} einen \Gls{podcast} und möchte diesen auf einem anderen Gerät einsehen.
+
+\begin{table}[h!]
+\begin{tabularx}{\textwidth}{X|c}
+Teilschritt & Bestanden\\\hline
+Im \Gls{podcatcher} wird ein neuer \Gls{podcast} den \Glspl{abo} hinzugefügt & Ja\\
+Im \Gls{dashboard} des Servers wird der neu abonnierte \Gls{podcast} angezeigt & Ja\\
+\makecell[l]{Auf einem anderen synchronisierten Gerät wird der \\ neu abonnierte \Gls{podcast} angezeigt} & Ja
+\end{tabularx}
+\end{table}
+
+\subsubsection{\Gls{podcast} deabonnieren}
+
+Der Benutzer hat einen \Gls{podcast} abonniert und möchte diesen nun deabonnieren.
+
+\begin{table}[h!]
+\begin{tabularx}{\textwidth}{X|c}
+Teilschritt & Bestanden \\\hline
+Im Podcatcher wird ein abonnierter Podcast deabonniert & Ja\\
+\makecell[l]{Im Dashboard des Servers wurde der deabonnierte Podcast \\ aus der Abonnement Liste entfernt} & Ja\\
+\makecell[l]{Auf einem anderen synchronisierten Gerät wurde der Podcast\\ ebenfalls deabonniert} & Ja
+\end{tabularx}
+\end{table}
+
+\newpage
+
+\subsubsection{Episode anhören}
+
+Der Benutzer hört sich eine Episode eines abonnierten \Glspl{podcast} an.
+
+\begin{table}[h!]
+\begin{tabularx}{\textwidth}{X|c}
+Teilschritt & Bestanden \\\hline
+\makecell[l]{Eine Episode wird für eine beliebige Zeit lang angehört \\ und dann pausiert} & Ja\\
+\makecell[l]{Im Dashboard des Servers wird die zuletzt gehörte Episode \\ unter \enquote{Zuletzt gehört} angezeigt} & Ja\\
+\makecell[l]{Auf einem anderen synchronisierten Gerät kann die \\ Episode weitergehört werden} & Ja\\
+\makecell[l]{Stoppt man die Episode wieder wird der alte Zeitpunkt\\ vom neuen Zeitpunkt überschrieben} & Ja
+\end{tabularx}
+\end{table}
+ \ No newline at end of file
diff --git a/30-qualitaetsheft/sections/tests.tex b/30-qualitaetsheft/sections/tests.tex
new file mode 100644
index 0000000..cdbf163
--- /dev/null
+++ b/30-qualitaetsheft/sections/tests.tex
@@ -0,0 +1,21 @@
+\section{Testfälle}
+
+Für die Erstellung der Testfälle wurde die SpringBoot Testumgebung verwendet und
+diese durch JUnit Testfälle ergänzt.
+
+Für das Testen wurde eine BaseTest Klasse erstellt, die grundlegende Funktionalität
+einiger Kern Komponenten sicherstellt. Weiter Initialisiert sie die Anwendungsumgebung auf
+der alle weiteren Tests aufbauen.
+
+Die Unit Tests erweitern diese BaseTest Klasse und können daher von gewisser Grundfunktionalität
+ausgehen, die durch den BaseTest abgedeckt ist. Dadurch müssen nicht große Teile der
+Anwendung durch Mock Objekte simuliert werden.
+
+Grundsätzlich wurde beim Entwurf der Testfälle nach dem Inside-Out-Prinzip vorangegangenen.
+Die bisher geschriebenen Testfälle haben dabei nicht das Ziel Korrektheit zu garantieren,
+sondern einen gewissen Qualitätsstandart zu sichern und gleichzeitig genug
+Arbeitspunkte bereit zu stellen um im ganzen Team an diesem Projekt parallel arbeite zu können.
+
+Zusätzlich wurden bei der Implementierung auf ausgiebig getestete Annotationen von Spring und
+Lombok zurückgegriffen die helfen die Anzahl an Fehlern bei standardisierten
+\enquote{Boilerplater-Code} Aufgaben zu vermeiden. \ No newline at end of file