added tests and TOO+
This commit is contained in:
parent
fddbe1f12c
commit
58abce35ff
|
@ -528,102 +528,4 @@ public class DocumentDTO implements Serializable {
|
||||||
\item kapselt und versteckt
|
\item kapselt und versteckt
|
||||||
\item nimmt Komplexität
|
\item nimmt Komplexität
|
||||||
\item steigert Effizienz da weniger Aufrufe über Remotegrenze
|
\item steigert Effizienz da weniger Aufrufe über Remotegrenze
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
\section{Page-Object-Pattern}
|
|
||||||
\begin{itemize}
|
|
||||||
\item stellt Screens der Web-App als Reihe von Objekten dar
|
|
||||||
\item tatsächlich werden nicht alle Seiten sondern wesentliche Elemente in Objekte gekapselt
|
|
||||||
\item eine HTML Seite wird so mitunter mit mehreren Objekten dargestellt (z.B. Header und Footer Page Object)
|
|
||||||
\item Das Page Objekt Design eignet sich besonders gut um Selenium Tests umzusetzen
|
|
||||||
\item Mittels der Page Objekte kann HTML Code verändert werden (Verkapselung)
|
|
||||||
\item ermöglichen die Modellierung der Benutzeroberfläche für Tests
|
|
||||||
\item reduziert Code duplication
|
|
||||||
\item verbessert Testwartbarkeit und macht Tests robuster
|
|
||||||
\end{itemize}
|
|
||||||
\subsection{Page Object Pattern lt. Zahnlücke}
|
|
||||||
\begin{itemize}
|
|
||||||
\item Trennung zwischen Testmethode und Page Code
|
|
||||||
\item Je Page eine Klasse mit Services / Operationen
|
|
||||||
\item Return einer Operation ist ein PageObject
|
|
||||||
\item Einfachere Wartbarkeit (Kapselung in PageObject)
|
|
||||||
\end{itemize}
|
|
||||||
\begin{figure}[!htp]
|
|
||||||
\centering
|
|
||||||
\includegraphics[width=0.8\textwidth]{pics/page-object.png}
|
|
||||||
\end{figure}
|
|
||||||
\subsection{Beispiel aus dem Projekt}
|
|
||||||
\subsubsection{Integration GUI Test mit Selenium}
|
|
||||||
\begin{minted}[linenos,breaklines=true]{java}
|
|
||||||
package at.fhj.swd.psoe.gui.pages;
|
|
||||||
|
|
||||||
import org.openqa.selenium.By;
|
|
||||||
import org.openqa.selenium.WebDriver;
|
|
||||||
import org.openqa.selenium.WebElement;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class DocumentsListPage extends AbstractPage {
|
|
||||||
private List<WebElement> list;
|
|
||||||
|
|
||||||
public DocumentsListPage(WebDriver driver) {
|
|
||||||
super(driver);
|
|
||||||
}
|
|
||||||
public List<WebElement> getList() {
|
|
||||||
list = this.getDriver().findElements(By.xpath("//*[@id=\"documents:comdoctable_data\"]"));
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
\end{minted}
|
|
||||||
\subsubsection{Durch Selenium getestetes Page Objekt}
|
|
||||||
\begin{minted}[linenos,breaklines=true]{java}
|
|
||||||
package at.fhj.swd.psoe.gui;
|
|
||||||
|
|
||||||
import at.fhj.swd.psoe.JdbcTestHelper;
|
|
||||||
import at.fhj.swd.psoe.gui.pages.*;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class ShowDocumentsListITCase extends AbstractChromeTest {
|
|
||||||
final private String roleName = "ADMIN";
|
|
||||||
private LoginPage loginPage;
|
|
||||||
private WelcomePage welcomePage;
|
|
||||||
private DocumentsListPage documentsListPage;
|
|
||||||
private String baseUrl = "http://localhost:8080/chr-krenn-fhj-ws2018-swd16-pse";
|
|
||||||
private static final JdbcTestHelper JDBC_HELPER = new JdbcTestHelper();
|
|
||||||
|
|
||||||
@Before
|
|
||||||
@Override
|
|
||||||
public void setUp() {
|
|
||||||
super.setUp();
|
|
||||||
JDBC_HELPER.executeSqlScript(
|
|
||||||
"src/test/resources/sql/DocumentServiceITCase-addDocument.sql");
|
|
||||||
loginPage = new LoginPage(this.driver, baseUrl, 60);
|
|
||||||
welcomePage = loginPage.login("testdocument@swd.com", "admin");
|
|
||||||
CommunitiesPage communitiesPage = welcomePage.openCommunitiesPage();
|
|
||||||
CommunityPage communityPage = communitiesPage.openCommunityPage();
|
|
||||||
documentsListPage = communityPage.openDocumentListPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTwoDocumentsListed() {
|
|
||||||
String content = documentsListPage.getList().stream().map(x -> x.getText()).collect(Collectors.joining());
|
|
||||||
Assert.assertTrue(content.contains("documentuser123"));
|
|
||||||
Assert.assertTrue(content.contains("DocumentITCase1"));
|
|
||||||
Assert.assertTrue(content.contains("DocumentITCase2"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
@Override
|
|
||||||
public void tearDown() {
|
|
||||||
super.tearDown();
|
|
||||||
JDBC_HELPER.executeSqlScript(
|
|
||||||
"src/test/resources/sql/DocumentServiceITCase-deleteDocument.sql");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
\end{minted}
|
|
|
@ -471,17 +471,181 @@ public void saveUser(UserDTO userDTO) {
|
||||||
}
|
}
|
||||||
\end{minted}
|
\end{minted}
|
||||||
\section{Tests}
|
\section{Tests}
|
||||||
|
\begin{itemize}
|
||||||
|
\item Ziel der Tests ist es, 100\% Codecoverage im Service-Layer zu erreichen (Anforderung für unser Projekt),
|
||||||
|
\item Private und Protected-Methoden müssen per se nicht getestet werden (Rule of Thumb),Wege zum erfolgreichen Test:
|
||||||
|
\begin{itemize}
|
||||||
|
\item Access-Modifier der Methoden auf public (public static) ändern,
|
||||||
|
\item Extrahieren der Methoden in neue Klassen,
|
||||||
|
\item Notfalls Package-Sichtbarkeit in Methode, wenn diese privat bleiben muss, Tests aber unbedingt notwendig sind.
|
||||||
|
\end{itemize}
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\subsection{Testpyramide}
|
\subsection{Testpyramide}
|
||||||
\begin{figure}[h]
|
\begin{figure}[ht!]
|
||||||
\centering
|
\centering
|
||||||
\includegraphics[width=0.9\linewidth]{pics/testpyramide}
|
\includegraphics[width=0.9\linewidth]{pics/testpyramide}
|
||||||
\caption{}
|
\caption{}
|
||||||
\label{fig:testpyramide}
|
\label{fig:testpyramide}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
\subsection{Unit}
|
\subsection{Unit}
|
||||||
\subsection{Integration}
|
\begin{itemize}
|
||||||
\subsection{Selenium bzw. GUI}
|
\item Im Build-Cycle werden zuerst Unit-Tests ausgeführt,
|
||||||
|
\item sie befinden sich im Projekt im Ordner \textit{src/test/at/fhj/swd/psoe/service/*Test.java},
|
||||||
|
\item ein Unit-Test muss jede Methode der Service-Klasse testen
|
||||||
|
\item Mockito imitiert die Methoden, die von der Datenbank abhängen, da diese zu diesem Zeitpunkt noch nicht zur Verfügung steht (Build-Cycle => Compile - Unit-Tests)
|
||||||
|
\item Im Unit-Test wird jeweils die kleinste Einheit getestet
|
||||||
|
\item Exceptions einfach mit Mockito werfen und testen, ob sie geworfen wurden
|
||||||
|
\end{itemize}
|
||||||
|
\begin{minted}[linenos,breaklines=true]{java}
|
||||||
|
@Test(expected = ServiceException.class)
|
||||||
|
public void testGetCommunityByUserMessagesDAOException()
|
||||||
|
{
|
||||||
|
Mockito.when(this.userPrincipal.getId()).thenReturn(-1L);
|
||||||
|
Mockito.when(this.communityService.loadAllCommunitiesByUser(-1L)).thenThrow(new DaoException(new RuntimeException()));
|
||||||
|
|
||||||
|
this.activitystreamService.getCommunityByUserMessages();
|
||||||
|
}
|
||||||
|
\end{minted}
|
||||||
|
\begin{minted}[linenos,breaklines=true]{java}
|
||||||
|
@Test
|
||||||
|
public void getDocumentsFromCommunity_ShouldReturnDocuments() {
|
||||||
|
Community community = Mockito.mock(Community.class);
|
||||||
|
Mockito.when(community.getId()).thenReturn(DOCUMENTID);
|
||||||
|
Documentlibrary doclib = Mockito.mock(Documentlibrary.class);
|
||||||
|
|
||||||
|
Mockito.when(community.getDocumentlibrary()).thenReturn(doclib);
|
||||||
|
Mockito.when(doclib.getCommunity()).thenReturn(community);
|
||||||
|
User user = Mockito.mock(User.class);
|
||||||
|
|
||||||
|
Mockito.when(communityDAO.findById(community.getId())).thenReturn(community);
|
||||||
|
|
||||||
|
List<Document> documents = prepareTwoDocuments(doclib,user);
|
||||||
|
Mockito.when(documentDAO.findByCommunity(community)).thenReturn(documents);
|
||||||
|
|
||||||
|
List<DocumentDTO> documentsDTO = documentService.getDocumentsFromCommunity(community.getId());
|
||||||
|
|
||||||
|
Assertions.assertThat(documentsDTO)
|
||||||
|
.usingElementComparatorIgnoringFields("user")
|
||||||
|
.containsExactlyInAnyOrder(DocumentMapper.toDTO(documents.get(0)), DocumentMapper.toDTO(documents.get(1)));
|
||||||
|
}
|
||||||
|
\end{minted}
|
||||||
|
\subsection{Integration Tests}%TODO Wolfimajer - moch fertig , bi
|
||||||
|
\begin{itemize}
|
||||||
|
\item testen alle Komponenten mit (Datenbank)
|
||||||
|
\item werden im Build-Cycle erst nach dem Deployen des war-Files ausgeführt (laufende Applikation)
|
||||||
|
\item In unserem Projekt kommt das Plugin \textit{failsafe} zum Einsatz
|
||||||
|
\item Datenbankscripts werden separat zu den anderen Scripts ausgeführt (Datenbank vorbereiten und auf den alten Stand zurückbringen)
|
||||||
|
\item
|
||||||
|
\begin{figure}[h]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.7\linewidth]{pics/test_structure}
|
||||||
|
\caption{}
|
||||||
|
\label{fig:teststructure}
|
||||||
|
\end{figure}
|
||||||
|
\end{itemize}
|
||||||
|
\subsection{GUI-Test}
|
||||||
|
\subsubsection{Page Object Pattern}
|
||||||
|
\begin{itemize}
|
||||||
|
\item stellt Screens der Web-App als Reihe von Objekten dar
|
||||||
|
\item tatsächlich werden nicht alle Seiten sondern wesentliche Elemente in Objekte gekapselt
|
||||||
|
\item eine HTML Seite wird so mitunter mit mehreren Objekten dargestellt (z.B. Header und Footer Page Object)
|
||||||
|
\item Das Page Objekt Design eignet sich besonders gut um Selenium Tests umzusetzen
|
||||||
|
\item Mittels der Page Objekte kann HTML Code verändert werden (Verkapselung)
|
||||||
|
\item ermöglichen die Modellierung der Benutzeroberfläche für Tests
|
||||||
|
\item reduziert Code duplication
|
||||||
|
\item verbessert Testwartbarkeit und macht Tests robuster
|
||||||
|
\end{itemize}
|
||||||
|
\subsection{Page Object Pattern lt. Zahnlücke}
|
||||||
|
\begin{itemize}
|
||||||
|
\item Trennung zwischen Testmethode und Page Code
|
||||||
|
\item Je Page eine Klasse mit Services / Operationen
|
||||||
|
\item Return einer Operation ist ein PageObject
|
||||||
|
\item Einfachere Wartbarkeit (Kapselung in PageObject)
|
||||||
|
\end{itemize}
|
||||||
|
\begin{figure}[!htp]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.8\textwidth]{pics/page-object.png}
|
||||||
|
\end{figure}
|
||||||
|
\subsection{Beispiel aus dem Projekt}
|
||||||
|
\subsubsection{Integration GUI Test mit Selenium}
|
||||||
|
\begin{minted}[linenos,breaklines=true]{java}
|
||||||
|
package at.fhj.swd.psoe.gui.pages;
|
||||||
|
|
||||||
|
import org.openqa.selenium.By;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.WebElement;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DocumentsListPage extends AbstractPage {
|
||||||
|
private List<WebElement> list;
|
||||||
|
|
||||||
|
public DocumentsListPage(WebDriver driver) {
|
||||||
|
super(driver);
|
||||||
|
}
|
||||||
|
public List<WebElement> getList() {
|
||||||
|
list = this.getDriver().findElements(By.xpath("//*[@id=\"documents:comdoctable_data\"]"));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
\end{minted}
|
||||||
|
\subsubsection{Durch Selenium getestetes Page Objekt}
|
||||||
|
\begin{minted}[linenos,breaklines=true]{java}
|
||||||
|
package at.fhj.swd.psoe.gui;
|
||||||
|
|
||||||
|
import at.fhj.swd.psoe.JdbcTestHelper;
|
||||||
|
import at.fhj.swd.psoe.gui.pages.*;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ShowDocumentsListITCase extends AbstractChromeTest {
|
||||||
|
final private String roleName = "ADMIN";
|
||||||
|
private LoginPage loginPage;
|
||||||
|
private WelcomePage welcomePage;
|
||||||
|
private DocumentsListPage documentsListPage;
|
||||||
|
private String baseUrl = "http://localhost:8080/chr-krenn-fhj-ws2018-swd16-pse";
|
||||||
|
private static final JdbcTestHelper JDBC_HELPER = new JdbcTestHelper();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
@Override
|
||||||
|
public void setUp() {
|
||||||
|
super.setUp();
|
||||||
|
JDBC_HELPER.executeSqlScript(
|
||||||
|
"src/test/resources/sql/DocumentServiceITCase-addDocument.sql");
|
||||||
|
loginPage = new LoginPage(this.driver, baseUrl, 60);
|
||||||
|
welcomePage = loginPage.login("testdocument@swd.com", "admin");
|
||||||
|
CommunitiesPage communitiesPage = welcomePage.openCommunitiesPage();
|
||||||
|
CommunityPage communityPage = communitiesPage.openCommunityPage();
|
||||||
|
documentsListPage = communityPage.openDocumentListPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTwoDocumentsListed() {
|
||||||
|
String content = documentsListPage.getList().stream().map(x -> x.getText()).collect(Collectors.joining());
|
||||||
|
Assert.assertTrue(content.contains("documentuser123"));
|
||||||
|
Assert.assertTrue(content.contains("DocumentITCase1"));
|
||||||
|
Assert.assertTrue(content.contains("DocumentITCase2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
@Override
|
||||||
|
public void tearDown() {
|
||||||
|
super.tearDown();
|
||||||
|
JDBC_HELPER.executeSqlScript(
|
||||||
|
"src/test/resources/sql/DocumentServiceITCase-deleteDocument.sql");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\end{minted}
|
||||||
\section{Toni FRAAGNAA}
|
\section{Toni FRAAGNAA}
|
||||||
Den Code durchgehen - was statt null - welche Exception - logger ok?
|
Den Code durchgehen - was statt null - welche Exception - logger ok?
|
||||||
ob ein Throw im try Block ok ist.
|
ob ein Throw im try Block ok ist.
|
||||||
|
@ -561,9 +725,12 @@ ob ein Throw im try Block ok ist.
|
||||||
// dependency Injection
|
// dependency Injection
|
||||||
|
|
||||||
// braucht man im Controller (ViewHelper) überhaupt noch Exception Handling
|
// braucht man im Controller (ViewHelper) überhaupt noch Exception Handling
|
||||||
|
|
||||||
|
//müssen wir die Folien genau beherrschen (Stubs vs. Mocks?)
|
||||||
|
|
||||||
|
//Bei welchem Goal wird was mitausgeführt? IT-Test bei mvn wildfy:run?
|
||||||
|
|
||||||
\end{minted}
|
\end{minted}
|
||||||
|
|
||||||
\section{Frageart Prüfung}
|
\section{Frageart Prüfung}
|
||||||
Welche Fehler können bei Exception-Handling vorkommen in unserem Projekt?? – wie funktioniert es grundsätzlich in unserem Code
|
Welche Fehler können bei Exception-Handling vorkommen in unserem Projekt?? – wie funktioniert es grundsätzlich in unserem Code
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue