diff options
Diffstat (limited to '30-qualitaetsheft/sections')
-rw-r--r-- | 30-qualitaetsheft/sections/backend.tex | 28 | ||||
-rw-r--r-- | 30-qualitaetsheft/sections/changes.tex | 67 | ||||
-rw-r--r-- | 30-qualitaetsheft/sections/codestyle.tex | 224 | ||||
-rw-r--r-- | 30-qualitaetsheft/sections/coverage.tex | 59 | ||||
-rw-r--r-- | 30-qualitaetsheft/sections/einleitung.tex | 13 | ||||
-rw-r--r-- | 30-qualitaetsheft/sections/frontend.tex | 196 | ||||
-rw-r--r-- | 30-qualitaetsheft/sections/glossar.tex | 391 | ||||
-rw-r--r-- | 30-qualitaetsheft/sections/lasttest.tex | 105 | ||||
-rw-r--r-- | 30-qualitaetsheft/sections/problems.tex | 65 | ||||
-rw-r--r-- | 30-qualitaetsheft/sections/testfaelle.tex | 182 | ||||
-rw-r--r-- | 30-qualitaetsheft/sections/tests.tex | 21 |
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 |