Un guide pour REST-assuré

Un guide de REST-assuré

1. introduction

REST-assuré a été conçu pour simplifier les tests et la validation des API REST et est fortement influencé par les techniques de test utilisées dans les langages dynamiques tels que Ruby et Groovy.

La bibliothèque prend en charge HTTP, en commençant bien sûr par les verbes et les opérations HTTP standard, mais va bien au-delà de ces bases.

Dans ce guide, nous allons àexplore REST-assured et nous allons utiliser Hamcrest pour faire des assertions. Si vous n'êtes pas déjà familiarisé avec Hamcrest, vous devez d'abord réviser le didacticiel:Testing with Hamcrest.

En outre, pour en savoir plus sur les cas d'utilisation plus avancés de REST-assuré, consultez nos autres articles:

Passons maintenant à un exemple simple.

2. Exemple de test simple

Avant de commencer, assurons-nous que nos tests comportent les importations statiques suivantes:

io.restassured.RestAssured.*
io.restassured.matcher.RestAssuredMatchers.*
org.hamcrest.Matchers.*

Nous en aurons besoin pour simplifier les tests et accéder facilement aux principales API.

Maintenant, commençons par l'exemple simple - un système de paris de base exposant certaines données pour les jeux:

{
    "id": "390",
    "data": {
        "leagueId": 35,
        "homeTeam": "Norway",
        "visitingTeam": "England",
    },
    "odds": [{
        "price": "1.30",
        "name": "1"
    },
    {
        "price": "5.25",
        "name": "X"
    }]
}

Supposons qu’il s’agisse de la réponse JSON provenant de l’API déployée localement -http://localhost:8080/events?id=390.:

Utilisons maintenant REST-assuré pour vérifier certaines fonctionnalités intéressantes du JSON de réponse:

@Test
public void givenUrl_whenSuccessOnGetsResponseAndJsonHasRequiredKV_thenCorrect() {
   get("/events?id=390").then().statusCode(200).assertThat()
      .body("data.leagueId", equalTo(35));
}

Donc, ce que nous avons fait ici, c'est - nous avons vérifié qu'un appel au point final/events?id=390 répond avec un corps contenant unJSON String dont leleagueId de l'objetdata est 35.

Jetons un œil à un exemple plus intéressant. Supposons que vous souhaitiez vérifier que le tableauodds contient des enregistrements avec des prix1.30 et5.25:

@Test
public void givenUrl_whenJsonResponseHasArrayWithGivenValuesUnderKey_thenCorrect() {
   get("/events?id=390").then().assertThat()
      .body("odds.price", hasItems("1.30", "5.25"));
}

3. Configuration assurée par REST

Si votre outil de dépendance préféré est Maven, nous ajoutons la dépendance suivante dans le fichierpom.xml:


    io.rest-assured
    rest-assured
    3.0.0
    test

Pour obtenir la dernière version, suivezthis link. L'assurance REST tire parti de la puissance des correspondants Hamcrest pour exécuter ses assertions, nous devons donc également inclure cette dépendance:


    org.hamcrest
    hamcrest-all
    1.3

La dernière version sera toujours disponible àthis link.

4. Validation de racine JSON anonyme

Considérons un tableau qui comprend des primitives plutôt que des objets:

[1, 2, 3]

Cela s'appelle une racine JSON anonyme, ce qui signifie qu'elle n'a pas de paire clé-valeur, mais qu'il s'agit toujours de données JSON valides.

Nous pouvons exécuter la validation dans un tel scénario en utilisant le symbole`$` ou une chaîne vide («») comme chemin. Supposons que nous exposions le service ci-dessus viahttp://localhost:8080/json, puis nous pouvons le valider comme ceci avec REST assuré:

when().get("/json").then().body("$", hasItems(1, 2, 3));

ou comme ceci:

when().get("/json").then().body("", hasItems(1, 2, 3));

5. Flotteurs et doubles

Lorsque nous commençons à utiliser REST-assuré pour tester nos services REST, nous devons comprendre que les nombres à virgule flottante dans les réponses JSON sont mappés au type primitiffloat.

L'utilisation du typefloat n'est pas interchangeable avecdouble comme c'est le cas pour de nombreux scénarios en java.

Voici un exemple de cette réponse:

{
    "odd": {
        "price": "1.30",
        "ck": 12.2,
        "name": "1"
    }
}

Supposons que nous exécutons le test suivant sur la valeur deck:

get("/odd").then().assertThat().body("odd.ck", equalTo(12.2));

Ce test échouera même si la valeur que nous testons est égale à la valeur de la réponse. C'est parce que nous comparons à undouble plutôt qu'à unfloat.

Pour que cela fonctionne, nous devons spécifier explicitement l'opérande de la méthode de correspondanceequalTo comme unfloat, comme ceci:

get("/odd").then().assertThat().body("odd.ck", equalTo(12.2f));

6. Spécification de la méthode de demande

En règle générale, nous exécuterons une requête en appelant une méthode telle queget(), correspondant à la méthode de requête que nous voulons utiliser.

De plus,we can also specify the HTTP verb using the request() method:

@Test
public void whenRequestGet_thenOK(){
    when().request("GET", "/users/eugenp").then().statusCode(200);
}

L'exemple ci-dessus équivaut à utiliser directementget().

De même, nous pouvons envoyer des requêtesHEAD,CONNECT etOPTIONS:

@Test
public void whenRequestHead_thenOK() {
    when().request("HEAD", "/users/eugenp").then().statusCode(200);
}

La requêtePOST suit également une syntaxe similaire et nous pouvons spécifierthe body by en utilisant les méthodeswith() andbody().

Par conséquent, pour créer un nouveauOdd  en envoyant une requêtePOST :

@Test
public void whenRequestedPost_thenCreated() {
    with().body(new Odd(5.25f, 1, 13.1f, "X"))
      .when()
      .request("POST", "/odds/new")
      .then()
      .statusCode(201);
}

Le sobjectOdd envoyé en tant quebody will sera automatiquement converti en JSON. Nous pouvons également passer tous lesString que nous voulons envoyer comme nosPOSTbody.

7. Configuration des valeurs par défaut

Nous pouvons configurer beaucoup de valeurs par défaut pour les tests:

@Before
public void setup() {
    RestAssured.baseURI = "https://api.github.com";
    RestAssured.port = 443;
}

Ici, nous définissons un URI et un port de base pour nos requêtes. En plus de ceux-ci, nous pouvons également configurer le chemin de base, la racine et l’authentification.

Remarque: nous pouvons également rétablir les valeurs par défaut standard de REST-assuré en utilisant:

RestAssured.reset();

8. Mesurer le temps de réponse

Voyons comment nous pouvonsmeasure the response time using the time() and timeIn() methods of the Response object:

@Test
public void whenMeasureResponseTime_thenOK() {
    Response response = RestAssured.get("/users/eugenp");
    long timeInMS = response.time();
    long timeInS = response.timeIn(TimeUnit.SECONDS);

    assertEquals(timeInS, timeInMS/1000);
}

Notez que:

  • time() est utilisé pour obtenir le temps de réponse en millisecondes

  • timeIn() est utilisé pour obtenir le temps de réponse dans l'unité de temps spécifiée

8.1. Valider le temps de réponse

On peut également valider le temps de réponse - en millisecondes - à l'aide de simpleslongMatcher:

@Test
public void whenValidateResponseTime_thenSuccess() {
    when().get("/users/eugenp").then().time(lessThan(5000L));
}

Si nous voulons valider le temps de réponse dans une unité de temps différente, nous utiliserons le matchertime() avec un second paramètreTimeUnit:

@Test
public void whenValidateResponseTimeInSeconds_thenSuccess(){
    when().get("/users/eugenp").then().time(lessThan(5L),TimeUnit.SECONDS);
}

9. Vérification de la réponse XML

Non seulement il peut valider une réponse JSON, mais il peut également valider XML.

Supposons que nous fassions une demande àhttp://localhost:8080/employees et que nous obtenions la réponse suivante:


    
        Jane
        Daisy
        f
    

Nous pouvons vérifier que lefirst-name estJane comme ceci:

@Test
public void givenUrl_whenXmlResponseValueTestsEqual_thenCorrect() {
    post("/employees").then().assertThat()
      .body("employees.employee.first-name", equalTo("Jane"));
}

Nous pouvons également vérifier que toutes les valeurs correspondent à nos valeurs attendues en enchaînant des adaptateurs de corps comme suit:

@Test
public void givenUrl_whenMultipleXmlValuesTestEqual_thenCorrect() {
    post("/employees").then().assertThat()
      .body("employees.employee.first-name", equalTo("Jane"))
        .body("employees.employee.last-name", equalTo("Daisy"))
          .body("employees.employee.sex", equalTo("f"));
}

Ou en utilisant la version abrégée avec des arguments variables:

@Test
public void givenUrl_whenMultipleXmlValuesTestEqualInShortHand_thenCorrect() {
    post("/employees")
      .then().assertThat().body("employees.employee.first-name",
        equalTo("Jane"),"employees.employee.last-name",
          equalTo("Daisy"), "employees.employee.sex",
            equalTo("f"));
}

10. XPath pour XML

We can also verify our responses using XPath. Considérez l'exemple ci-dessous qui exécute un matcher sur lesfirst-name:

@Test
public void givenUrl_whenValidatesXmlUsingXpath_thenCorrect() {
    post("/employees").then().assertThat().
      body(hasXPath("/employees/employee/first-name", containsString("Ja")));
}

XPath accepte également une autre manière d'exécuter le matcherequalTo:

@Test
public void givenUrl_whenValidatesXmlUsingXpath2_thenCorrect() {
    post("/employees").then().assertThat()
      .body(hasXPath("/employees/employee/first-name[text()='Jane']"));
}

11. Détails du test de journalisation

11.1. Détails de la demande de journal

Tout d'abord, voyons commentlog entire request details using*log().all()*:

@Test
public void whenLogRequest_thenOK() {
    given().log().all()
      .when().get("/users/eugenp")
      .then().statusCode(200);
}

Cela enregistrera quelque chose comme ceci:

Request method:  GET
Request URI:    https://api.github.com:443/users/eugenp
Proxy:          
Request params: 
Query params:   
Form params:    
Path params:    
Multiparts:     
Headers:        Accept=*/*
Cookies:        
Body:           

Pour ne consigner que des parties spécifiques de la requête, nous avons la méthodelog() en combinaison avecparams(), body(), headers(), cookies(), method(), path() par exemplelog.().params().

Notez que les autres bibliothèques ou filtres utilisés peuvent modifier ce qui est réellement envoyé au serveur, cela ne doit donc être utilisé que pour consigner la spécification de la demande initiale.

11.2. Détails de la réponse du journal

De même, nous pouvons enregistrer les détails de la réponse.

Dans l'exemple suivant, nous enregistrons uniquement le corps de la réponse:

@Test
public void whenLogResponse_thenOK() {
    when().get("/repos/eugenp/tutorials")
      .then().log().body().statusCode(200);
}

Exemple de sortie:

{
    "id": 9754983,
    "name": "tutorials",
    "full_name": "eugenp/tutorials",
    "private": false,
    "html_url": "https://github.com/eugenp/tutorials",
    "description": "The \"REST With Spring\" Course: ",
    "fork": false,
    "size": 72371,
    "license": {
        "key": "mit",
        "name": "MIT License",
        "spdx_id": "MIT",
        "url": "https://api.github.com/licenses/mit"
    },
...
}

11.3. Réponse du journal en cas de problème

Nous avons également la possibilité de consigner la réponse uniquement en cas d'erreur ou si le code d'état correspond à une valeur donnée:

@Test
public void whenLogResponseIfErrorOccurred_thenSuccess() {

    when().get("/users/eugenp")
      .then().log().ifError();
    when().get("/users/eugenp")
      .then().log().ifStatusCodeIsEqualTo(500);
    when().get("/users/eugenp")
      .then().log().ifStatusCodeMatches(greaterThan(200));
}

11.4. Enregistrer si la validation a échoué

Nous pouvons également enregistrer la requête et la réponse uniquement si notre validation a échoué:

@Test
public void whenLogOnlyIfValidationFailed_thenSuccess() {
    when().get("/users/eugenp")
      .then().log().ifValidationFails().statusCode(200);

    given().log().ifValidationFails()
      .when().get("/users/eugenp")
      .then().statusCode(200);
}

Dans cet exemple, nous voulons valider que le code d'état est 200. Seulement si cela échoue, la demande et la réponse seront enregistrées.

12. Conclusion

Dans ce tutoriel, nous avonsexplored the REST-assured framework et avons examiné ses fonctionnalités les plus importantes que nous pouvons utiliser pour tester nos services RESTful et valider leurs réponses.

L'implémentation complète de tous ces exemples et extraits de code peut être trouvée dans lesGitHub projectassurés par REST.