Eerder ben ik in de bijdrage Ketentesten en SOA (deel 1) ingegaan op de aspecten die komen kijken bij ketentesten in een SOA-omgeving. In dit artikel ga ik in op één van de problemen tijdens een ketentest: de grote hoeveelheid van externe afhankelijkheden en hoe deze te elimineren.
In een keten kan er onderscheid gemaakt worden tussen onderdelen van een keten (voor het gemak in dit artikel services genoemd) die de keten vormen en onderdelen van een keten waarvan de keten alleen maar afhankelijk is, maar die geen wezenlijk onderdeel uitmaken van de te testen keten.
Ketenservices
De eerste categorie bevat services die onder de regie vallen van het ketentestproject en ook zelf getest gaan worden. De tweede categorie bevat services die niet onder de regie vallen van het testteam en die dus ook geen direct onderdeel van de keten vormen, maar waar de keten wel van afhankelijk is. Denk hierbij aan ingekochte third-party services of een door middel van services ontsloten mainframe. Een tester heeft geen of weinig invloed op het gedrag van deze services, maar zij maken wel onderdeel uit van de end-to-end test. Een aantal voorbeelden van de invloed die dergelijke services op de totale test hebben zijn:
– Is er überhaupt een testvariant van de service beschikbaar, of gebeurt het testen van het systeem met de productieversie?
– Moet er voor elke aanroep van de service betaald worden of is er een gratis variant beschikbaar (denk aan de kosten van een performance test)?
– Is de testservice voldoende betrouwbaar, denk aan garanties voor beschikbaarheid, voorspelbaarheid van de responsetijd en voorspelbaarheid van de data (krijg ik bij een gelijke vraag altijd hetzelfde antwoord terug?)?
– Heeft de tester invloed op de testdata, is het bijvoorbeeld mogelijk om via een interface zelf testgevallen te configureren, liefst automatisch, desnoods handmatig?
– Is het mogelijk om bepaalde excepties en foutsituaties op afroep te genereren, dit om de reactie van de aanroepende systemen op uitzonderingen te kunnen testen? Voorbeeld: bij een bepaalde input reageert de third-party service altijd heel langzaam of met een bepaalde foutmelding.
– Heb ik de juiste versie beschikbaar voor bijvoorbeeld reproduceren van een productie-issue?
Applicatievirtualisatie
De oplossing voor de invloed die dergelijke services hebben op een test is applicatievirtualisatie. Met behulp van op de markt beschikbare virtualisatietooling is het mogelijk om de externe afhankelijkheden in een keten te elimineren door op communicatie-protocolniveau de applicatielogica van deze afhankelijkheden te simuleren door middel van virtuele services. Dus in plaats van de echte services, worden tijdens het testen de virtuele services aangeroepen.
Door het exacte gedrag van de echte services op te nemen en op afroep weer af te spelen is het daarmee mogelijk om heel nauwkeurig het gedrag van deze services te simuleren. Van elke aanroep worden de request (inputparameters) en de response (de outputparameters) vastgelegd. De virtualisatietooling functioneert tijdens deze fase als een proxyservice tussen de aanroepende partij en de aangeroepen service in. Tijdens het testen daarna worden het verstuurde inputbericht vergeleken met de verzameling opgenomen inputberichten en bij een match (te definiëren van heel los tot en met zeer strict) wordt het bijbehorende outputbericht als antwoord verstuurd.
De request-/response-berichten die op deze manier worden opgenomen lijken heel statisch en zouden dus altijd exact hetzelfde antwoord geven, ook als dat niet gewenst is. Om dit te voorkomen zijn er allerlei voorzieningen aangebracht in de virtualisatietooling om te kunnen werken met onverwachte vragen (onbekende request-berichten) en dynamische response-berichten. Zo is bijvoorbeeld instelbaar op welke elementen in een request moet worden gelet bij de selectie van een response: altijd het hele bericht, een bepaald deel van het bericht of alleen de naam van de aangeroepen methode. Door nu in het response-bericht te werken met faciliteiten, zoals het automatisch kopiëren van waardes uit het request-bericht naar het response-bericht, het kunnen genereren van default waardes, random gegenereerde waardes, automatisch unieke tellers of met waarden die bepaald zijn door middel van een database-query of webservice aanroep, is het mogelijk om dynamische response-berichten samen te stellen die een reëel beeld geven van het werkelijke systeem.
Speciale aandacht gaat hierbij uit naar parameters die een datum en of tijd bevatten. Veel systemen zijn gevoelig voor datumvelden. Een voorbeeld is een reserveringssysteem waarbij voor vluchten de datum altijd in de toekomst moeten liggen.
De virtualisatietooling moet dus kunnen omgaan met datum- en tijdvelden, ze moet deze velden automatisch herkennen en snappen dat een datum in een request en een datum in een respons altijd relatief moeten worden geïnterpreteerd ten opzichte van de systeemdatum. De datum- en tijdvelden in de opgenomen request- en response-berichten moeten dus nooit letterlijk gebruikt worden, maar bijvoorbeeld als basis voor het berekenen van een relatieve datum.
Een voorbeeld: op 1 april wordt er met een serviceaanroep gecontroleerd of op 10 april nog ruimte is voor één passagier op een vlucht naar Londen. De service geeft een lijstje van alle beschikbare vluchten op en rond die datum (dus op de datum 9, 10 of 11 april). Als deze datums worden opgenomen en ruim een maand later op 10 mei worden gebruikt in een regressietest, kunnen de originele input- en outputdatums uiteraard niet gebruikt worden, in plaats daarvan moet worden gewerkt met een datum die relatief is ten opzichte van de systeemdatum, in dit geval plus tien dagen en zo kunnen de beschikbare vluchten in de regressietest van 10 mei worden voorzien van de datums 19, 20 en 21 mei.
Een ander aspect is de volgorde van aanroepen van verschillende services. Bijvoorbeeld bij een bankapplicatie wordt eerst het saldo opgevraagd, daarna wordt er een bedrag openomen en daarna wordt weer het saldo opgevraagd. Om een reëel beeld van de werkelijkheid te geven moet de virtuele service, die de backoffice-applicatie van de bank simuleert, kunnen omgaan met deze volgorde. Dus als bij de eerste aanroep het saldo duizend euro is, moet na een opname van vijfhonderd euro bij de tweede aanroep van de saldoservice vijfhonderd euro worden teruggegeven. Wat voorkomen moet worden is dat de virtuele service om dit mogelijk te maken de logica van de te simuleren applicatie moet bevatten. Het betreft hier alleen de volgorde van de berichten, dus de tweede aanroep van de saldoservice moet een ander resultaat geven omdat er daarvoor een aanroep heeft plaatsgevonden van de geldopnameservice.
Conclusie
Door middel van applicatievirtualisatie wordt tijdens een test gewerkt in een omgeving waarbij de te testen keten is teruggebracht tot exact die systemen die getest moeten worden, zonder last te hebben van afhankelijkheden die de test vertragen of zelfs onmogelijk maken. Applicatievirtualisatie maakt dit mogelijk zonder dat hiervoor programmeurs de te simuleren applicatie geheel of gedeeltelijk hoeven na te bouwen in bijvoorbeeld een stub.
Het derde en laatste deel van deze serie gaat over de virtualisatie van services die zelf deel uitmaken van de te testen keten. Hierin wordt uitgelegd hoe ook hier applicatievirtualisatie kan helpen de doorlooptijd van een ketentest aanmerkelijk te versnellen.