Upload
phungdang
View
214
Download
0
Embed Size (px)
Citation preview
ARQUILLIAN IN DERPRAXIS
/ Stefan Hildebrandt @hildebrandttk
0
FOLIEN ALS HTML-PRÄSENTATION
http://bit.ly/1FzQAkg
JAVA 2 EEjUnitClient-zugriff
Proxies im ContainerInitialContextFactory
NameNotFoundExceptionNamingException
RemoteException
J2EE MIT SPRINGwar-Deployment
Projektspezifische "Frameworks"Deployment mit MocksDatenbanksetupTestdaten
spring-test
HISTORIE VON ARQUILLIANEntstand bei der Implementierung des JSR 299Weiterentwicklung durch JBoss
Fokus: Test ihrer Server und FrameworksEuer Projektfokus?
FEATURESSteuerung des Container–LebenszyklusErstellung von ArtefaktenInstallieren von ArtefaktenBereitstellung von Komponenten in den TestPlug-in-Konzept für Erweiterungen
public class PetTypeControllerTest {
@Testpublic void testSwitchSortOrder_ascending_to_descending() { PetTypeController petTypeController = new PetTypeController(SortOrder.ascending);
petTypeController.switchSortOrder();
assertEquals(SortOrder.descending, petTypeController.getPetTypeSortOrder());}
@Testpublic void testSwitchSortOrder_descending_to_ascending() { PetTypeController petTypeController = new PetTypeController(SortOrder.descending);
petTypeController.switchSortOrder();
assertEquals(SortOrder.ascending, petTypeController.getPetTypeSortOrder());}}
JPATDD / BDD
Entwicklung von komplexen MappingsSchrittweise Erstellung von QueriesAls Input- -> Output-TestsSehr gute Absicherung für Refactorings
@RunWith(Arquillian.class)@PersistenceTest@UsingDataSet("OwnerDaoImplTest.yml")@Cleanup(strategy = CleanupStrategy.USED_TABLES_ONLY)public class OwnerDaoImplTest {
//Need this instance for arquillian-dbunit loading @PersistenceContext(unitName = "javaee7petclinic") private EntityManager entityManager;
@Inject private OwnerDao ownerDao;
types: - id: 1 name: Katze - id: 2 name: Hundowners: - id: 1 first_name: Stefan last_name: Hildebrandt address: Hauptstr. city: Oldenburg telephone: 0441-666 - id: 2 first_name: Horst last_name: Müller address: Hauptstr. city: Oldenburg telephone: 0441-765pets: - id: 11 name: Speedy birth_date: 2015-01-01 type_id: 1 owner_id: 1 - id: 21 name: Bruno birth_date: 2014-03-04 type_id: 2 owner_id: 2visits: - id: 110 visit_date: 2015-01-11 description: Untersuchungen
@Testpublic void testFindOwnersWithVisitWithinGivenTimeFrame_DayForLastVisit() { final List<Owner> owners = ownerDao.findOwnersWithVisitWithinGivenTimeFrame( SIMPLE_DATE_FORMAT.parse("2015-03-11"), new Date()); assertThat(owners, CoreMatchers .<Owner>hasItem(hasProperty("firstName", is(equalTo("Stefan"))))); assertThat(owners, not(CoreMatchers .<Owner>hasItem(hasProperty("firstName", is(equalTo("Horst"))))));}
@Testpublic void testFindOwnersWithVisitWithinGivenTimeFrame_OnlyOneVisitOnOneDayInPast() { final List<Owner> owners = ownerDao.findOwnersWithVisitWithinGivenTimeFrame( SIMPLE_DATE_FORMAT.parse("2015-03-10"), SIMPLE_DATE_FORMAT.parse("2015-03-10")); assertThat(owners, not(CoreMatchers .<Owner>hasItem(hasProperty("firstName",is(equalTo("Stefan")))))); assertThat(owners, CoreMatchers .<Owner>hasItem(hasProperty("firstName", is(equalTo("Horst")))));}
@Testpublic void testFindOwnersWithVisitWithinGivenTimeFrame_AllVisitsUntilSomeDateInPast() { final List<Owner> owners = ownerDao .findOwnersWithVisitWithinGivenTimeFrame( SIMPLE_DATE_FORMAT.parse("1990-03-10"), SIMPLE_DATE_FORMAT.parse("2015-03-10")); assertThat(owners, CoreMatchers .<Owner>hasItem(hasProperty("firstName", is(equalTo("Stefan"))))); assertThat(owners, CoreMatchers .<Owner>hasItem(hasProperty("firstName", is(equalTo("Horst")))));}
SERVICESZusammenspiel mehrerer Elemente eines ServicesMit/ohne DatenbankMocks oder Simulatoren
Angepasstes Deployment@Alternative
@RunWith(Arquillian.class)public class VetWebserviceTest { private static final String BASE = "../../../../"; private static final String POM_PATH = BASE + "pom.xml";
@Deployment(testable = false) public static WebArchive createDaoDeployment() { File[] deps = Maven.resolver().loadPomFromFile(POM_PATH) .importRuntimeDependencies().resolve().withTransitivity().asFile(); WebArchive war; = ShrinkWrap.create(WebArchive.class, "remote-service-deployment.war") .addClasses(VetWebservice.class, JaxRsActivator.class, Vets.class) .addClasses(VetDao.class, Vet.class, Specialty.class) .addClasses(VetDaoMock.class) .addAsLibraries(deps); return war }
@Test@RunAsClientpublic void testFeed() throws IOException { CloseableHttpClient httpClient = HttpClients.createDefault(); final String uri = baseURL + "rest/vets/feed"; HttpGet httpGet = new HttpGet(uri); CloseableHttpResponse response = httpClient.execute(httpGet); assertEquals(200, response.getStatusLine().getStatusCode()); final String datePattern = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm'.*'").format(new Date()) final HttpEntity entity = response.getEntity(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); entity.writeTo(outputStream); assertThat(outputStream.toString(), RegexMatcher.matchesRegex( "..."));}
SYSTEMDB mit Echtdaten (obfuscated) in VM / ContainerSimulatoren für NachbarsystemeTestschnittstellen:
Service-EbeneRemoteLocal
UI
SYSTEMINTEGRATIONMIT NACHBARSYSTEMEN
Komplett definierter und exklusiver StandKein Setup über reguläre UI/ServicesSehr robuste und verlässliche TestsRelativ schnellIdealerweise Ausführung im CI vor Integration
z.B. mit oder (mit )Simulatoren für nicht verfügbare Systeme (SAP, ...)
vagrant docker compose
AKZEPTANZTESTSExterne, fachliche Sicht auf TestsVerlinkung zu AnforderungenLangfristige Absicherung von AnforderungenKlassische Probleme:
LangsamSeltene AusführungWeit weg vom CodeKaum Feedback für Entwicklung
CUKESPACECucumber-Runner für ArquillianAkzeptanztests von Unit- bis SystemintegrationsebeneSetup wie bei Systemintegrationstests
Wesentlich RobusterLokale Ausführung im CI -> Schnelles FeedbackRegelmäßige Ausführung im CI -> Schnelles FeedbackEigener Vortrag
NICHT-FUNKTIONALETESTS
Mit JMeter...Über Messpunkte bei der TestausführungIndirekt: Laufzeit einer größeren Suite
ZUSAMMENFASSUNG EINSATZBEREICHETests immer auf kleinstmöglicher EbeneErst bei konkreten Problemen Tests in höherer EbeneWenige vollumfängliche IntegrationstestsDurch die integrierte Kombination wertvoll
SERVER@DeploymentArchiv wird erweitertTests laufen im ContainerÜbertragung der Ergebnisse an den TestVoller Zugriff auf Ressourcen/Komponenten
REMOTEVerwendung einer bestehenden laufenden Instanz➚ Am schnellsten➚ Ergebnis realitätsnah➘ Manuelles Setup➘ Manuelles Starten/Stoppen➘ Hängenbleiben von Deployments
MANAGEDVerwendung einer bestehenden InstallationStart/Stop durch Arquillian➚ Ergebnis realitätsnah➚ Automatisches Starten/Stoppen➘ Etwas längere Laufzeiten➘ Manuelles Setup➘ Hängenbleiben von Deployments
EMBEDDEDVerwendung eines embedded-Containers in der Test-JVM➚ Kein Hängenbleiben von Deployments➚ Automatisches Startup➚ Automatisches Setup➘ Etwas längere Laufzeiten➘ Ergebnis ggf. nicht vollständig realitätsnah➘ Konflikte von Bibliotheken (z.B. guava)
ARQUILLIAN SUITE EXTENSIONIdee: Ein Deployment je Test-Classpath
Auswirkungen auf ProjektlayoutAlternativ: Mehrere Deployments
Benannte DeploymentsZuordnung über Namen
Eigene Events für HooksNicht im Fokus anderer der Kernentwicklung und andererExtensions
Kompatibilitätsprobleme mit anderen Extensions
TOMEEBenannte DeploymentsGeänderte Deployment-EventsAb Tomee 1.7.2
DEPENDENCY HANDLINGmaven-/gradle-Importer
Analyse komplexer Projekte dauertAlternativ: directory-Importer
Befüllung mittels maven/gradle
DATENBANK SETUP (INTEGRATION+)Once-Per-SuiteDedizierte Daten je TestMögliche Verfahren
DB UnitSpezialwerkzeuge für DatenbankenFertige Container oder VMs
UI-TESTSDefinierter Systemzustand
DatenbankSonstige Daten/Zustände
Langsamere Systeme mockenInspections in den MocksBedienung des UIs vereinfachen
INTERNES MULTITHREADINGParallele Ausführung der Tests in eine Suite in einer VMNotwendig:
Synchronisatisiertes Suite-DeploymentDisjunkte TestdatenThreadsave Mocks-/Simulatoren
Nicht mit Arquillian kombinierbarjunittoolbox-ParallelSuite
EXTERNES MULTITHREADINGParallele Testausführung mit maven/gradle
mehrere JVMsNotwendig:
Mehrere Container, DBs und UmsystemeArquillian Cube Extension
/DRONE GRAPHENEUnterstützung für SeleniumtestsBereitstellung von Webdriver-InstanzImplementierung des Page-Objekt-PatternsErweiterung des Page-Objekt-Patterns um KomponentenEigener Vortrag
WARPUntersuchung von Servlet-Requests im TestMocking von Servlet-Responses im Test
TRANSACTIONTransaktionssteuerung in Tests
PERSISTENCEAusführung von SQL-Skripten für das SchemaDBUnit-Integration
Befüllung einer DBAssert auf DB-Ebene
DOKUMENTATIONQuellcode der TestsQuellcode der Tests von Open Source Projekten
Offizielle GuidesArquillian Showcase
ZUSAMMENFASSUNG➚ Ideal für Java EE-Unit-Tests➚ Auf allen Teststufen verwendbar➚ Viel Flexibilität➘ Viel Komplexität➘ Suite nicht im Fokus
ALTERNATIVENcdi-unitApache DeltaSpike CdiCtrlspring-testspring-boot
FOLIEN
http://bit.ly/1FzQAkg
STEFAN HILDEBRANDT - CONSULTING.HILDEBRANDT.TKBeratung, Coaching und ProjektunterstützungJava EEBuildsysteme gradle und maven/ant-MigrationTestautomatisierungCoach in agilen ProjektenDevOps