Accueil Nos publications Blog Le scripting dans SoapUI avec Groovy

Le scripting dans SoapUI avec Groovy

Dans cet article, je vais présenter les possibilités offertes par SoapUi, plus précisément la création et le paramétrage de test suites avec l’utilisation du langage de scripting Groovy.

SoapUi est un outil développé par Eviware, permettant entre autres d’invoquer, de monitorer et bouchonner des services Web, basés sur différentes technologies.
Il intègre un mécanisme de testing à savoir la gestion des TestSuites, composés de test cases, eux-même composés de test steps.

Le gros avantage de cette fonctionnalité est sans doute la possibilité de scripter chaque élément dans les moindres détails. (setup scripts, teardown scripts, properties…)

Nous allons voir par un exemple simple comment enchaîner tout cela.

La partie script s’effectuera avec Groovy, qui est un langage dynamique très proche du Java. (pour plus d’infos, c’est ici)

Plutôt qu’un long discours, je vais donc présenter un bon exemple, inspiré d’une de mes expériences passées.

Contexte

On dispose d’un service Web contenant 2 opérations, permettant de créer et supprimer des commandes fournisseur.

Chaque commande est composée de 1..* lignes de commandes et chaque ligne pointe sur un stock libre.
On dispose bien sûr d’une XSD qui décrit tout ça, et d’un WSDL contenant les opérations de création et suppression.

Voici les steps que l’on va mettre en place :

  1. Stock des paramètres d’entrée du test case
  2. Stock des paramètres temporaires (passage de valeurs d’un step à l’autre)
  3. Calcul en groovy du nombre de lignes de commande à créer
  4. Appel SQL pour générer le XML décrivant ces lignes
  5. Interprétation du résultat par Groovy
  6. Création des commandes
  7. Récupération des codes ainsi créés
  8. Suppression en masse des commandes

En pratique

Construction du test suite

C’est parti ! Commençons par créer le test suite. Clic droit sur le projet -> New TestSuite puis lui donner un petit nom.

Ensuite, clic droit sur le Test suite -> New TestCase et donner un nom

Voici la fenêtre de paramétrage du test case :
testCase_parametrage

Sous l’onglet TestSteps on peut voir une suite de boutons, représentant tous les types de step que l’on pourra ajouter.

On peut voir aussi 4 boutons plus bas :

  • Description,
  • Properties (un ensemble de clé-valeurs propres au cas de test, avec possibilité d’import/export depuis/vers un fichier)
  • Setup script (le script d’initialisation du test case, en groovy)
  • TearDown script (le script de finalisation du test case, en groovy également)

On n’est pas si loin d’un test avec Junit non ? 😉

Ajout des steps

On va donc s’intéresser aux steps SOAP, Groovy, JDBC et Properties.

Les steps Properties

On crée ici 2 clés, le produit de ces 2 valeurs donnera le nombre de lignes à construire.

configProps

Ensuite, on crée un autre step properties qui va contenir 3 clés, pour stocker des valeurs temporaires qui seront utilisées en read/write d’un step à l’autre. Mais on y revient juste après.

tempProps

Le 1er step Groovy

groovy_empty

Un step Groovy n’est ni plus ni moins qu’une zone de script, avec la particularité de fournir 3 variables déjà initialisées dans le contexte d’exécution :

    • log : un logger pour tracer des informations
    • context : fournit le contexte d’exécution pour obtenir diverses informations (properties, test case courant, etc)
    • testRunner : correspond à une instance du moteur exécutant la suite de tests

Le script suivant va donc calculer à partir des propriétés définies dans les steps précédents le nombre de lignes de commandes à fabriquer. Puis ce nombre sera injecté dans un step JDBC que l’on va créer par la suite.

Voici le code :


    // retrieve the properties step object
    def configPropsStep = testRunner.testCase.testSteps["configTest"];
    // read the 2 properties
    def nbOrdersToCreate = configPropsStep.getPropertyValue("nbOrdersToCreate");
    def nbLinesPerOrder = configPropsStep.getPropertyValue("nbLinesPerOrder");

    log.info "We are going to create " + nbOrdersToCreate + " orders";
    log.info "We are going to add " + nbLinesPerOrder + " lines per order";

    // compute the amount of line to build
    def numRows = Integer.parseInt(nbOrdersToCreate) * Integer.parseInt(nbLinesPerOrder);

    log.info numRows + " rows to build";

    // retrieve the database step
    def stepBase = testRunner.testCase.testSteps["stepDataBase"];
    // write its value
    stepBase.setPropertyValue("numRows", String.valueOf(numRows));
    

Si l’on exécute ce code en cliquant sur la petite flèche verte, on aura les 3 lignes de logs attendues mais on aura aussi une NullPointerException car le step JDBC n’a pas été créé.

groovy_NPE

Ce qui nous amène à l’étape suivante.

Le step JDBC

Avant tout, il faut ajouter le driver de connectivité (ojdbc5.jar par exemple pour Oracle) dans le dossier bin/ext à la racine de SOAP Ui et redémarrer ce dernier pour la bonne prise en compte.

Sans cela, on obtient un joli message d’erreur : java.sql.SQLException: No suitable driver

Pour la liste des drivers supportés, c’est ici

Voici à quoi ressemble le step :

jdbc

En haut à gauche, on peut définir des propriétés réutilisables dans la requête SQL en tant que paramètres nommés.

Un peu plus bas, on trouve la partie configuration avec le driver et la chaîne de connexion
Note : Cette chaîne est écrite ici en dur mais il est possible de paramétrer les infos (serveur, login , pwd) à un niveau plus global (par exemple dans l’item test suite)

Ensuite, le champ SQL query contiendra la requête qui sera exécutée.

Enfin, les résultats retournés par la requête sortiront au format XML dans le volet de droite, et seront interprétés en Groovy dans le script de la section suivante.

Récupération et utilisation des résultats

On va créer un nouveau step Groovy de la même manière que le précédent et y ajouter le code suivant :


// create a groovyUtils instance for XML handling
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context);

// retrieve the JDBC step
def stepBase = testRunner.testCase.testSteps["buildRows"];

// retrieve the temp properties step
def tempProps = testRunner.testCase.testSteps["tempProps"];

// get the SQL results as XML
def xmlResult = stepBase.testRequest.response.getContentAsXml();
// get a holder object to deal with XPATH
def responseHolder = groovyUtils.getXmlHolder(xmlResult);

// extract all STOCK tags
def commandLines = responseHolder.getNodeValues("//ResultSet/Row/STOCK");
log.info commandLines.getClass().getName() + " " + commandLines.size() + " lines found";

// ----------------------

// retrieve the properties step object
def configPropsStep = testRunner.testCase.testSteps["configTest"];

// read the 2 properties within it
def nbOrdersToCreate = Integer.valueOf(configPropsStep.getPropertyValue("nbOrdersToCreate"));
def nbLinesPerOrder = Integer.valueOf(configPropsStep.getPropertyValue("nbLinesPerOrder"));

// compute the amount of line to build
def numRows = nbOrdersToCreate * nbLinesPerOrder;

// retrieve the SOAP step : createOrder
def createOrderStep = testRunner.testCase.testSteps["createOrder"];

def count = 0;
StringBuilder ordersToDelete = new StringBuilder();
for(def i=1; i<=nbOrdersToCreate; i++) {
StringBuilder lines = new StringBuilder();
for(def j=1; j<=nbLinesPerOrder; j++) {
int index = i>1 ? (i-1) * nbLinesPerOrder + j-1 : i*j-1;
lines.append(OrderLines.getAt(index));
}

// transfer the Orderlines as String into the temp properties step
tempProps.setPropertyValue("orderlines", lines.toString());
tempProps.setPropertyValue("numOrder", String.valueOf(count++));

// run the SOAP step Create
testRunner.runTestStep(createOrderStep);

// retrieve the SOAP response as XML
def xmlRespCreate = createOrderStep.testRequest.response.getContentAsXml();
def createHolder = groovyUtils.getXmlHolder(xmlRespCreate);

     // assume that the createOrder operation returns an order code in the right tag
def OrderCode = createHolder.getNodeValue("//OrderCode");

     // build the string to put in the deleteOrder SOAP step
ordersToDelete.append("<OrderCode>" + OrderCode + "</OrderCode>");
}

// finally, transfert this String into the temp properties step.
tempProps.setPropertyValue("ordersToDelete", ordersToDelete.toString());
    

Résumé du script :

  1. Récupérer la réponse produite par le step JDBC
  2. Extraire toutes les balises OrderLines au format XML
  3. Les injecter dans le step properties
  4. Exécuter le step de création grâce au testRunner
  5. Récupérer sa réponse pour y extraire le code de la commande nouvellement créée
  6. Injection de tous les codes concaténés dans le step de properties qui sera lu par le dernier step SOAP de suppression de commandes

Les steps de création et suppression de commandes

La dernière étape sera maintenant de créer 2 steps de type SOAP et de changer leur contenu comme suivant :

create_SOAP

On remarque ici la syntaxe ${#step_name#key} qui permet de lire directement une valeur dans un step properties.

La 1ère valeur ${#tempProps#numOrder} représente donc le code de la commande en cours de création (code dont la valeur est incrémentée par le script Groovy précédent)

Alors que la seconde valeur ${#tempProps#orderLines} représente une chaîne XML contenant toute la structure liée aux OrderLines.

Note : Etant donné que ce step est exécuté par Groovy, il est nécessaire de le désactiver dans le flux du test case au risque d’être exécuté 2 fois.
Pour cela, faire un clic droit sur le step et choisir “Disable Step”

Pour le script de suppression, le principe est exactement le même :

On y retrouve la valeur lue dans le step properties, contenant la succession de balises XML <OrderCode>

delete_SOAP

C’est tout pour la création des steps !

On peut maintenant exécuter la suite de tests et valider que tout se passe bien dans la fenêtre de résumés des steps.

Vers l’automatisation

Tout ceci est bien pratique mais se limite au scope de SoapUi, alors qu’en est-il de l’intégration continue ?

Il est possible d’intégrer un projet SoapUi dans un cycle de tests, grâce à divers outils.

Le soft est livré avec une série d’exécutables, permettant de lancer des tests suites en ligne de commande ou depuis une plateforme d’intégration continue comme Jenkins.

Intégration avec Maven

Les utilisateurs de Maven pourront ajouter un plugin permettant de donner une configuration ainsi qu’une référence vers le fichier du projet SoapUi au format XML.

Pour plus de détails sur la configuration du plugin, c’est par ici : https://www.soapui.org/Test-Automation/maven-2x.html
Les cibles se chargeront ensuite de lancer les différents exécutables (loadRunner, testRunner, etc.)

Intégration avec JUnit

Il est également possible de l’intégrer directement avec JUnit, en utilisant l’API prévue. Par exemple :


public void testRunner() throws Exception
{
  SoapUITestCaseRunner runner = new SoapUITestCaseRunner();
  runner.setProjectFile( "src/dist/sample-soapui-project.xml" );
  runner.run();
}

Ou encore, à un niveau plus fin :


public void testTestCaseRunner() throws Exception
{
  WsdlProject project = new WsdlProject( "src/dist/sample-soapui-project.xml" );
  TestSuite testSuite = project.getTestSuiteByName( "CreateAndDeleteOrders" );
  TestCase testCase = testSuite.getTestCaseByName( "testCase1" );

  // create empty properties and run synchronously
  TestRunner runner = testCase.run( new PropertiesMap(), false );
  assertEquals( Status.FINISHED, runner.getStatus() );
}

Conclusion

Dans cet article, nous avons pu voir qu’il était plutôt simple d’accompagner le déroulement d’une suite de tests, en scriptant les moindres aspects des steps et en ajoutant une grande flexibilité.

La syntaxe de Groovy étant assez simple à assimiler, l’utiliser permet de gagner pas mal de temps pour obtenir une suite de tests rapidement, ou tout simplement un moyen d’automatiser des tâches du quotidien.

Toutefois, l’analyse des réponses en XML peut vite devenir fastidieuse si ces dernières deviennent complexes mais Groovy et XPath nous facilitent le travail.

Quelques liens utiles pour explorer un peu plus le vaste sujet du scripting :

https://www.soapui.org/apidocs/index.html

https://groovyinsoapui.wordpress.com/

https://learnsoapui.wordpress.com/2011/07/17/10-groovy-scripts-on-your-finger-tips-soapui/