Mittwoch, 9. Dezember 2015

Übung Spock und Groovy

Übung Spock und Groovy 

Schritt 0: Installieren Sie das Eclipse Groovy Plugin

Beziehen Sie über den Eclipse Maketplace die Groovy IDE.

Update Site 4.4 (Luna):
http://dist.springsource.org/release/GRECLIPSE/e4.4/

Schritt 1: Demo Projekt herunterladen 

Laden Sie das Demo Projekt von hier herunter und entpacken Sie die ZIP Datei.

Schritt 2: Projekt importieren 

Erzeugen Sie über Gradle die Eclipse Projekt Konfiguration.
gradlew eclipse

Importieren Sie das Projekt in Eclipse

Schritt 3: Spock Tests schreiben

Schreiben Sie für das Interface Basar (Komponente) eine Reihe an Tests mittels Spock.
Hilfe zu Spock finden Sie unter:  http://spockframework.github.io/spock/docs/1.0/index.html

Schritt 4:  Data Driven Test

Schreiben Sie einen Data Driven Test mit dem Spock Werkzeug für die Basar Komponente.

Systemtest und Akzeptanztest

Folien und Übungen
Lernziele (Fragen zur Vorlesung)
  • Was wird beim Systemtest getestet?
  • Wie werden beim BDD die Testfälle beschrieben?
  • Wer führt den Systemtest durch?
  • Was sind Äquivalenzklassen?
  • Was versteht man unter Grenzwertanalyse? Welche Werte würde Sie ausprobieren, falls Sie ganzzahlige Werte in einem Intervall 23 <= x < 102 testen wollen?
  • Welche Zustände und Zustandsübergänge testet man beim zustandsbasierten Testen?
  • Wann hört man beim zustandsbasierten Testen auf zu testen?
Literatur
  • Der Systemtest. Anforderungsbasiertes Testen von Software-Systemen, Harry M. Sneed, Manfred Baumgartner, Richard Seidl - 2008
  • Andreas Spillner - Basiswissen Softwaretest - 2005

Integrationsstrategien und Integrationstestmuster

In der letzen Vorlesung haben wir die folgenden verschiedene Integrationsstrategien und Integrationstestmuster kennengelernt. Diese sind hier im vorliegenden Blog Eintrag nochmals knapp dargestellt.

Integrationsstrategien
Big-Bang Integration
Es werden alle Komponenten auf einmal in Betrieb genommen. Es findet eigentlich keinen wirklich Integration statt. Diese Integrationsstrategie gilt es um jeden Preis zu vermeiden!!!

Bottom-Up Integration
Es werden schrittweise von unten in der Architektur die Komponente integriert. Beispielweise wird im ersten Schritt die Datenzugriffslogik und die Datenbank integriert und getestet. Im nächsten Schritt wird dann die Komponente mit der Geschäftslogik dazu genommen, dies bedeutet es wird nun das Zusammenspiel Geschäftlogik, Datenzugriffsschicht und Datenbank integriert und anschließend getestet.

Top-Down Integration
Hier wird in der umgekehrten Reihenfolge wie bei der Bottom-Up Integration, schrittweise die Komponente von oben nach unten in der Architektur integriert und geprüft. Bei einer Anwendung mit einer GUI könnte im ersten Integrationsschritt die GUI und die Geschäftlogik integriert werden. Bei einer Bottom-Up Integration muss immer die letzte Komponente die nicht mehr mit integriert wird simuliert werden (außer im letzten Integrationsschritt wenn alle Komponenten integriert werden im Systemtest) dazu können Beispielweise Mock Objekte genutzt werden.

Back-Bone Integration
Bei dieser Strategie gibt es zur Integration der einzelnen Komponenten eine fertige Komponente das Backbone über die man die einzelnen Komponenten integriert (über diese erfolgt i.d.R. die Kommunikation der Komponenten z.B. über einen sogenannten Bus). Ein Beispiel aus der Java Welt ist der Einsatz eines ESB (Enterprise Service Bus) z.B. OpenESB mit einer solchen Lösung kann eine Back-Bone Integration umgesetzt werden. Auch ein Applikationsframework wie z.B. OSGi kann zur Umsetzung einer Back-Bone Integration genutzt werden.

Continuous Integration
Bei jeder Codestandänderung wird automatisch integriert und die Komponenten und Integrationstests werden durchgeführt. Einen Schritt weiter geht das Pattern Continuous Delivery wo die gesamte Anwendung bei einer Codestandänderung unter bestimmten Umständen sogar komplett an den Kunden ausgeliefert wird (siehe auch Literatur Verweise unten).

Bottom-Up Integrationstest Patterns
Praktisch betrachtet haben wir in der Vorlesung die Integrationsstrategie Bottom-Up. Dabei haben wir zwei Patterns zum Implementierten von Integrationstests für die Bottom-Up Integrationsstrategie kennengelernt. Diese sind mit dem Quelltext aus der Vorlesung im Folgenden noch mal knapp dargestellt.

Layer Test 

Bei diesem Integrationstest  Muster wird für jeden Layer (dazu muss die Anwendung nach einem Schichten Modell z.B. 3-Tier Architekturmodell aufgebaut worden sein) ein Integrationstest geschrieben. Zur Implementierung dieses vier Phasen Tests (Setup, Execute, Verify, Tear-Down) wird nur die Funktionalität des höchsten Layer genutzt.

Vorteil
Der Test hat keine Abhängigkeit zu den Technologien der untern Schichten. Daher kann der Test wiederverwendet werden wenn sich die Technologien dieser untern Schichten ändern. Beispielsweise der Test wird für das Layer der Geschäftlogik geschrieben, die Anwendung wird von einer SQL Datenbank auf eine Non-SQL Datenbank umgestellt, der Test kann ohne Änderung immer noch genutzt werden.

Nachteil
Der Test prüft nicht wirklich die Integration der Komponenten, es wird nicht sichergestellt dass die Eingaben auf dem höchsten Layer tatsächlich auch in die Komponenten gelangen und in die niedrigen Layer wo sie evtl. hin sollen.

Beispiel
Das Sequenz Diagramm unten zeigt einen beispielhaften Ablauf eines Layer Tests wie wir ihn in der Vorlesung umgesetzt haben.

Es wird im Test die Integration Datenbank und Datenzugriffsschicht einer Geschäftsanwendung geprüft. Hier der Quelltext für den Test aus der Vorlesung:

import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import basar.domain.Seller;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/spring/dao.xml"})
public class SellerDaoIntegrationTest {
@Autowired
SellerDao sellerDao;
@Before
public void setup(){
sellerDao.clear();
}
@Test
public void testCreateSeller() throws Exception {
Seller seller = new Seller();
seller.setBasarNumber(100L);
seller.setName("Tester");
sellerDao.insertSeller(seller);
Seller actualSeller = sellerDao.getSeller(100L);
assertEquals(seller, actualSeller);
}
}


Back Door Manipulation Test


Bei diesem Integrationstest  Muster wird über eine Hintertür z.B. eine Test eigene Datenbank-Verbindung die Infrastruktur-Komponenten in einen definierten Zustand gebracht. Und nach der Testausführung wird über diesen Weg ebenfalls der Zustand der Infrastruktur-Komponenten geprüft.

Vorteil
Der Test stellt sicher dass tatsächlich die Komponenten wie spezifiziert integriert sind.

Nachteil
Bei einer Änderung der Infrastruktur Komponenten muss auch der Test angepasst oder sogar neu geschrieben werden.

Beispiel
Das Sequenz Diagramm unten zeigt einen beispielhaften Ablauf eines Back Door Manipulation Tests wie wir ihn in der Vorlesung umgesetzt haben.


Es wird im Test die Integration Datenbank und Datenzugriffsschicht einer Geschäftsanwendung geprüft. Hier der Quelltext für den Beispiel Test aus der Vorlesung:

import static org.junit.Assert.*;
import java.io.InputStream;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.XmlDataSet;
import org.dbunit.operation.DatabaseOperation;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.test.jdbc.SimpleJdbcTestUtils;
import basar.domain.Seller;
@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(defaultRollback=false)
@ContextConfiguration(locations = { "/spring/dao.xml" })
public class SellerDaoTest {
@Autowired
private SellerDao sellerDao;
protected SimpleJdbcTemplate simpleJdbcTemplate;
private DataSource dataSource;
@Before
public void setUp() throws Exception {
DatabaseOperation.CLEAN_INSERT.execute(getConnection(), getDataSet());
}
@Test
public void testInsertSeller() throws Exception {
Seller seller = new Seller();
seller.setBasarNumber(new Long(130));
seller.setName("Baranowski");
sellerDao.insertSeller(seller);
int countRowsInSellerTable = SimpleJdbcTestUtils.countRowsInTable(
simpleJdbcTemplate, "seller");
assertEquals(3, countRowsInSellerTable);
List<Map<String, Object>> result = simpleJdbcTemplate
.queryForList("select * from seller where basarnumber=130");
assertEquals("Baranowski", result.get(0).get("NAME"));
}
@Autowired
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
}
protected IDatabaseConnection getConnection() throws Exception {
Connection connection = DataSourceUtils.getConnection(dataSource);
return new DatabaseConnection(connection);
}
public IDataSet getDataSet() throws Exception {
String name = "/" + getClass().getName().replace('.', '/')
+ "DataSet.xml";
InputStream resourceAsStream = getClass().getResourceAsStream(name);
return new XmlDataSet(resourceAsStream);
}
}


Literatur und Links