```html

Lorsque nous pensons à Selenium WebDriver, nous l'associons généralement à l'automatisation des navigateurs et aux tests d'interface utilisateur. Cependant, Selenium peut également être un outil puissant pour les tests d'API lorsqu'il est utilisé correctement. Ce tutoriel vous guidera à travers le processus d'utilisation des capacités de Selenium WebDriver pour effectuer des tests d'API, en vous fournissant des exemples pratiques et les meilleures pratiques.
Les tests d'API (Application Programming Interface) impliquent de tester directement les API de l'application, en vérifiant leur fonctionnalité, leur fiabilité, leurs performances et leur sécurité. Bien qu'il existe des outils dédiés aux tests d'API comme Postman, REST Assured ou SoapUI, Selenium WebDriver peut être un ajout précieux à votre boîte à outils de tests d'API, en particulier lorsque vous souhaitez combiner les tests d'interface utilisateur et d'API dans le même framework.
Prérequis
Avant de vous lancer dans les tests d'API avec Selenium WebDriver, assurez-vous d'avoir :
- Des connaissances de base de Selenium WebDriver
- Un langage de programmation de votre choix (Java, Python, C#, JavaScript)
- Selenium WebDriver configuré dans votre environnement de développement
- Une compréhension des API REST/SOAP
- Des connaissances de base des méthodes HTTP (GET, POST, PUT, DELETE)
Comprendre l'architecture
L'architecture de Selenium WebDriver le rend adapté aux tests d'API grâce à sa capacité à :
- Envoyer des requêtes HTTP directement à l'aide de bibliothèques intégrées ou externes
- Gérer les réponses et vérifier les données
- S'intégrer aux frameworks de test existants
- Gérer les données et les environnements de test
Configuration de votre environnement
Configurons un environnement de base pour les tests d'API avec Selenium WebDriver :
Exemple Java
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class SeleniumApiTesting {
private WebDriver driver;
public void setUp() {
System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless"); // Mode sans interface pour les tests d'API
driver = new ChromeDriver(options);
}
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
}
Exemple Python
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import requests
import json
def setup_driver():
chrome_options = Options()
chrome_options.add_argument("--headless") # Mode sans interface pour les tests d'API
driver = webdriver.Chrome(options=chrome_options)
return driver
def teardown_driver(driver):
if driver is not None:
driver.quit()
Approches de test d'API avec Selenium WebDriver
1. Utilisation des bibliothèques HTTP natives
L'approche la plus simple consiste à utiliser les bibliothèques HTTP natives de votre langage de programmation avec Selenium WebDriver.
Exemple Java - Requête GET
public String performGetRequest(String endpoint) throws IOException {
URL url = new URL(endpoint);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
System.out.println("GET Response Code: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
} else {
return "GET request failed with response code: " + responseCode;
}
}
Exemple Python - Requête POST
def perform_post_request(endpoint, payload):
headers = {'Content-Type': 'application/json'}
response = requests.post(endpoint, data=json.dumps(payload), headers=headers)
print(f"POST Response Code: {response.status_code}")
if response.status_code == 200:
return response.json()
else:
return f"POST request failed with response code: {response.status_code}"
2. Utilisation de JavaScriptExecutor pour les appels AJAX
Une autre approche consiste à utiliser JavaScriptExecutor de Selenium pour effectuer des appels AJAX directement à partir du navigateur.
Exemple Java
import org.openqa.selenium.JavascriptExecutor;
public String performApiCallWithJsExecutor(String endpoint, String method, String payload) {
String script = String.format(
"var xhr = new XMLHttpRequest();" +
"xhr.open('%s', '%s', false);" +
"xhr.setRequestHeader('Content-Type', 'application/json');" +
"xhr.send('%s');" +
"return xhr.responseText;",
method, endpoint, payload
);
return (String) ((JavascriptExecutor) driver).executeScript(script);
}
Exemple Python
def perform_api_call_with_js_executor(driver, endpoint, method, payload):
script = f"""
var xhr = new XMLHttpRequest();
xhr.open('{method}', '{endpoint}', false);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send('{payload}');
return xhr.responseText;
"""
return driver.execute_script(script)
3. Interception et modification des appels d'API
Selenium WebDriver peut être utilisé pour intercepter et modifier les appels d'API effectués par l'application, en particulier lorsqu'il est combiné avec des outils proxy comme BrowserMob Proxy.
Exemple Java avec BrowserMob Proxy
import net.lightbody.bmp.BrowserMobProxy;
import net.lightbody.bmp.BrowserMobProxyServer;
import net.lightbody.bmp.client.ClientUtil;
import org.openqa.selenium.Proxy;
public void setupProxyForApiInterception() {
// Démarrer le proxy
BrowserMobProxy proxy = new BrowserMobProxyServer();
proxy.start(0);
// Obtenir l'objet proxy Selenium
Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy);
// Configurer Chrome pour utiliser le proxy
ChromeOptions options = new ChromeOptions();
options.setCapability("proxy", seleniumProxy);
// Créer l'instance WebDriver
driver = new ChromeDriver(options);
// Ajouter un filtre de requête pour intercepter les appels d'API
proxy.addRequestFilter((request, contents, messageInfo) -> {
if (request.getUri().contains("/api/")) {
System.out.println("Intercepted API call: " + request.getUri());
// Modifier les en-têtes, les paramètres ou le corps de la requête si nécessaire
}
return null;
});
// Ajouter un filtre de réponse pour inspecter et modifier les réponses d'API
proxy.addResponseFilter((response, contents, messageInfo) -> {
if (messageInfo.getOriginalRequest().getUri().contains("/api/")) {
String responseBody = contents.getTextContents();
System.out.println("API Response: " + responseBody);
// Modifier la réponse si nécessaire
}
});
}
Construction d'un framework de test d'API complet
Créons un framework de test d'API plus structuré à l'aide de Selenium WebDriver :
Exemple Java
import org.json.JSONObject;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.io.IOException;
public class ApiTestFramework {
private WebDriver driver;
private final String BASE_URL = "<https://api.example.com>";
@BeforeClass
public void setUp() {
System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless");
driver = new ChromeDriver(options);
}
@Test
public void testGetUserEndpoint() throws IOException {
String endpoint = BASE_URL + "/api/users/1";
String response = performGetRequest(endpoint);
JSONObject jsonResponse = new JSONObject(response);
Assert.assertEquals(jsonResponse.getString("name"), "John Doe");
Assert.assertEquals(jsonResponse.getInt("id"), 1);
Assert.assertTrue(jsonResponse.has("email"));
}
@Test
public void testCreateUserEndpoint() throws IOException {
String endpoint = BASE_URL + "/api/users";
JSONObject payload = new JSONObject();
payload.put("name", "Jane Smith");
payload.put("email", "jane.smith@example.com");
String response = performPostRequest(endpoint, payload.toString());
JSONObject jsonResponse = new JSONObject(response);
Assert.assertTrue(jsonResponse.has("id"));
Assert.assertEquals(jsonResponse.getString("name"), "Jane Smith");
}
private String performGetRequest(String endpoint) throws IOException {
// Implémentation de l'exemple précédent
}
private String performPostRequest(String endpoint, String payload) throws IOException {
URL url = new URL(endpoint);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
// Écrire la charge utile à la connexion
try (java.io.OutputStream os = connection.getOutputStream()) {
byte[] input = payload.getBytes("utf-8");
os.write(input, 0, input.length);
}
int responseCode = connection.getResponseCode();
System.out.println("POST Response Code: " + responseCode);
try (BufferedReader br = new BufferedReader(
new InputStreamReader(connection.getInputStream(), "utf-8"))) {
StringBuilder response = new StringBuilder();
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
return response.toString();
}
}
@AfterClass
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
}
Exemple Python
import unittest
import json
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import requests
class ApiTestFramework(unittest.TestCase):
BASE_URL = "<https://api.example.com>"
def setUp(self):
chrome_options = Options()
chrome_options.add_argument("--headless")
self.driver = webdriver.Chrome(options=chrome_options)
def test_get_user_endpoint(self):
endpoint = self.BASE_URL + "/api/users/1"
response = self.perform_get_request(endpoint)
self.assertEqual(response['name'], "John Doe")
self.assertEqual(response['id'], 1)
self.assertIn('email', response)
def test_create_user_endpoint(self):
endpoint = self.BASE_URL + "/api/users"
payload = {
"name": "Jane Smith",
"email": "jane.smith@example.com"
}
response = self.perform_post_request(endpoint, payload)
self.assertIn('id', response)
self.assertEqual(response['name'], "Jane Smith")
def perform_get_request(self, endpoint):
response = requests.get(endpoint)
return response.json() if response.status_code == 200 else None
def perform_post_request(self, endpoint, payload):
headers = {'Content-Type': 'application/json'}
response = requests.post(endpoint, data=json.dumps(payload), headers=headers)
return response.json() if response.status_code in [200, 201] else None
def tearDown(self):
if self.driver:
self.driver.quit()
if __name__ == '__main__':
unittest.main()
Combiner les tests d'interface utilisateur et d'API
L'un des plus grands avantages de l'utilisation de Selenium WebDriver pour les tests d'API est la possibilité de combiner les tests d'interface utilisateur et d'API dans le même framework :
@Test
public void testLoginAndVerifyUserDataAPI() throws IOException {
// Partie interface utilisateur : connexion via l'interface utilisateur
driver.get("<https://example.com/login>");
driver.findElement(By.id("username")).sendKeys("testuser");
driver.findElement(By.id("password")).sendKeys("password");
driver.findElement(By.id("loginButton")).click();
// Attendre la fin de la connexion
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.urlContains("/dashboard"));
// Extraire le jeton d'authentification des cookies ou du stockage local
String authToken = (String) ((JavascriptExecutor) driver)
.executeScript("return localStorage.getItem('authToken');");
// Partie API : utiliser le jeton pour effectuer un appel d'API authentifié
String endpoint = BASE_URL + "/api/user/profile";
URL url = new URL(endpoint);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Authorization", "Bearer " + authToken);
// Traiter et vérifier la réponse de l'API
int responseCode = connection.getResponseCode();
Assert.assertEquals(responseCode, 200);
// Lire et analyser la réponse
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String response = in.lines().collect(Collectors.joining());
in.close();
JSONObject jsonResponse = new JSONObject(response);
// Vérifier que les données de l'API correspondent à ce qui est affiché dans l'interface utilisateur
String uiUsername = driver.findElement(By.id("profileUsername")).getText();
Assert.assertEquals(jsonResponse.getString("username"), uiUsername);
}
Meilleures pratiques pour les tests d'API avec Selenium WebDriver
- Utiliser le mode sans interface : lors de l'exécution de tests d'API purs, exécutez Selenium en mode sans interface pour économiser des ressources.
- Séparer les tests d'API et d'interface utilisateur : bien que vous puissiez les combiner, gardez les tests d'API et d'interface utilisateur logiquement séparés.
- Tirer parti des bibliothèques d'assertions : utilisez des bibliothèques d'assertions complètes pour valider les réponses d'API.
- Mettre en œuvre la gestion des erreurs : ajoutez une gestion des erreurs appropriée pour les échecs d'API.
- Journaliser les requêtes et les réponses d'API : à des fins de débogage, journalisez toutes les interactions d'API.
- Paramétrer les tests : utilisez des fournisseurs de données ou des tests paramétrés pour tester divers scénarios.
- Mettre en œuvre la gestion de l'authentification : créez des méthodes réutilisables pour gérer l'authentification.
- Tenir compte des performances : sachez que Selenium peut ajouter des frais généraux par rapport aux outils de test d'API dédiés.
Limites de l'utilisation de Selenium WebDriver pour les tests d'API
- Frais généraux de performance : Selenium est principalement conçu pour l'automatisation des navigateurs, il ajoute donc des frais généraux pour les tests d'API purs.
- Fonctionnalités spécifiques aux API limitées : les outils de test d'API dédiés offrent des fonctionnalités plus spécifiques pour les tests d'API.
- Dépendance du navigateur : même en mode sans interface, Selenium nécessite un navigateur, ce qui peut être inutile pour les tests d'API.
- Complexité : la configuration de Selenium pour les tests d'API peut être plus complexe que l'utilisation d'outils de test d'API dédiés.
Quand utiliser Selenium WebDriver pour les tests d'API
Selenium WebDriver est le plus adapté aux tests d'API dans les scénarios suivants :
- Lorsque vous disposez déjà d'un framework de test d'interface utilisateur basé sur Selenium et que vous souhaitez l'étendre.
- Lorsque vous devez tester des scénarios impliquant des interactions d'interface utilisateur et d'API.
- Lorsque vous devez tester des API dans le contexte d'un navigateur (comme tester les appels d'API JavaScript).
- Lorsque vous souhaitez intercepter et modifier les appels d'API effectués par l'application.
Conclusion
Selenium WebDriver peut être un outil polyvalent pour les tests d'API, en particulier lorsqu'il est intégré aux frameworks de test d'interface utilisateur existants. Bien qu'il ne puisse pas remplacer les outils de test d'API dédiés pour les besoins complexes de test d'API, il offre un moyen flexible de combiner les tests d'interface utilisateur et d'API dans un seul framework.
En tirant parti des approches et des exemples fournis dans ce tutoriel, vous pouvez utiliser efficacement Selenium WebDriver pour vos exigences de test d'API. N'oubliez pas de prendre en compte les compromis et de choisir le bon outil pour vos besoins de test spécifiques.
Que vous testiez des API REST, des services SOAP ou des points de terminaison GraphQL, Selenium WebDriver peut vous aider à créer des tests complets qui valident à la fois l'interface utilisateur de votre application et sa fonctionnalité d'API sous-jacente.
Pour des besoins de test d'API plus avancés, vous souhaiterez peut-être envisager de combiner Selenium WebDriver avec des bibliothèques ou des frameworks de test d'API dédiés comme REST Assured (pour Java) ou Requests (pour Python) afin d'obtenir le meilleur des deux mondes.
Bons tests !
```