Accueil/Compétences/BrowserStack
Logo BrowserStack

BrowserStack

La plateforme cloud de test cross-browser et multi-device qui permet de tester des applications web et mobiles sur plus de 3000 navigateurs, appareils et systèmes d'exploitation réels.

Pour les non-initiés

Qu'est-ce que BrowserStack ?

Imaginez que vous créez un site web ou une application mobile et que vous devez vous assurer qu'elle fonctionne parfaitement pour tous vos utilisateurs, quel que soit leur appareil ou navigateur. C'est un défi considérable car il existe des centaines de combinaisons différentes de navigateurs, d'appareils et de systèmes d'exploitation. C'est là qu'intervient BrowserStack.

BrowserStack est comme un laboratoire virtuel géant qui vous donne accès instantanément à des milliers d'appareils et navigateurs réels via le cloud. Au lieu d'avoir à acheter et maintenir des dizaines d'appareils différents, vous pouvez simplement vous connecter à BrowserStack et tester votre site ou application sur n'importe quel appareil, comme si vous l'aviez physiquement entre les mains.

Ce que BrowserStack apporte à votre projet

Compatibilité universelle

La confiance que votre site ou application fonctionne correctement pour tous vos utilisateurs, quel que soit leur appareil ou navigateur, évitant ainsi les problèmes de compatibilité qui pourraient frustrer vos clients.

Économies substantielles

Élimination du besoin d'acheter et de maintenir un laboratoire coûteux d'appareils physiques, tout en permettant à votre équipe de tester sur une gamme beaucoup plus large d'environnements.

Tests automatisés

Possibilité d'automatiser les tests sur de multiples navigateurs et appareils simultanément, accélérant considérablement le cycle de développement et permettant des livraisons plus rapides et plus fiables.

Tests locaux et en interne

Capacité à tester des applications en développement ou des sites internes qui ne sont pas accessibles publiquement, grâce à des tunnels sécurisés entre votre environnement local et BrowserStack.

En somme, BrowserStack permet aux équipes de développement de livrer des applications web et mobiles de haute qualité, compatibles avec tous les environnements utilisateurs, tout en réduisant considérablement les coûts et les délais liés aux tests. C'est un outil essentiel pour toute entreprise soucieuse de l'expérience utilisateur de ses produits digitaux.

Pour les développeurs

Fonctionnement technique

BrowserStack est une plateforme cloud de test qui permet aux développeurs de tester leurs sites web et applications sur des milliers de navigateurs, systèmes d'exploitation et appareils réels. Elle offre plusieurs produits complémentaires pour répondre à différents besoins de test.

Produits principaux

BrowserStack propose quatre produits principaux :

  • Live - Test manuel sur des navigateurs et appareils réels
  • Automate - Tests automatisés pour applications web avec Selenium et Cypress
  • App Live - Test manuel d'applications mobiles natives
  • App Automate - Tests automatisés d'applications mobiles avec Appium

Exemples pratiques d'intégration

Selenium avec BrowserStack Automate

Voici un exemple d'intégration de Selenium WebDriver avec BrowserStack pour des tests cross-browser automatisés :

Tests Selenium avec BrowserStack
// tests/e2e/crossbrowser.test.js const { Builder, By, Key, until } = require('selenium-webdriver'); const assert = require('assert'); // Configuration des navigateurs et appareils à tester const configurations = [ { os: 'Windows', osVersion: '10', browser: 'Chrome', browserVersion: 'latest', name: 'Test sur Chrome Windows 10' }, { os: 'OS X', osVersion: 'Big Sur', browser: 'Safari', browserVersion: 'latest', name: 'Test sur Safari macOS Big Sur' }, { os: 'iOS', osVersion: '15', device: 'iPhone 13 Pro', realMobile: true, name: 'Test sur iPhone 13 Pro' }, { os: 'Android', osVersion: '12.0', device: 'Samsung Galaxy S22', realMobile: true, name: 'Test sur Samsung Galaxy S22' } ]; async function runTest(capabilities) { // Ajout des identifiants BrowserStack const browserstackOptions = { 'browserstack.user': process.env.BROWSERSTACK_USERNAME, 'browserstack.key': process.env.BROWSERSTACK_ACCESS_KEY, 'browserstack.debug': true, // Active les captures d'écran et les logs visuels 'browserstack.console': 'verbose', 'browserstack.networkLogs': true, ...capabilities }; const driver = await new Builder() .usingServer('https://hub-cloud.browserstack.com/wd/hub') .withCapabilities(browserstackOptions) .build(); try { console.log(`Démarrage du test sur ${capabilities.name}`); // Test de connexion (exemple) await driver.get('https://example.com/login'); // Attendre que la page soit chargée await driver.wait(until.elementLocated(By.id('login-form')), 10000); // Remplir le formulaire de connexion await driver.findElement(By.id('email')).sendKeys('test@example.com'); await driver.findElement(By.id('password')).sendKeys('password123', Key.RETURN); // Attendre la redirection vers le tableau de bord await driver.wait(until.urlContains('dashboard'), 10000); // Vérifier que l'utilisateur est connecté const welcomeElement = await driver.findElement(By.css('.welcome-message')); const welcomeText = await welcomeElement.getText(); assert.ok(welcomeText.includes('Bienvenue'), 'Le message de bienvenue devrait être affiché'); console.log(`Test réussi sur ${capabilities.name}`); // Marquer le test comme réussi sur BrowserStack await driver.executeScript( 'browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"passed","reason": "Login successful!"}}' ); } catch (error) { console.error(`Erreur sur ${capabilities.name}:`, error); // Marquer le test comme échoué sur BrowserStack await driver.executeScript( `browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"failed","reason": "${error.message}"}}` ); throw error; } finally { await driver.quit(); } } // Exécuter les tests sur tous les navigateurs/appareils configurés describe('Tests cross-browser avec BrowserStack', function() { // Augmenter le timeout pour les tests sur appareils réels this.timeout(30 * 60 * 1000); // 30 minutes for (const config of configurations) { it(`devrait fonctionner sur ${config.name}`, async function() { await runTest(config); }); } });

BrowserStack Local

Pour tester des applications en développement ou des environnements internes, BrowserStack Local établit un tunnel sécurisé :

Configuration de BrowserStack Local
// setup/browserstack-local.js const browserstack = require('browserstack-local'); // Initialiser une instance de BrowserStack Local const bsLocal = new browserstack.Local(); // Options pour BrowserStack Local const localOptions = { key: process.env.BROWSERSTACK_ACCESS_KEY, verbose: true, force: true, // Force la connexion même si elle est déjà établie onlyAutomate: true, // Limite l'accès aux tests automatisés uniquement forceLocal: true, // Force le trafic à passer par le tunnel local localIdentifier: 'MyApp_' + Math.random().toString(36).substring(2, 8) // Identifiant unique pour le tunnel }; // Démarrer BrowserStack Local avant les tests async function startBrowserStackLocal() { return new Promise((resolve, reject) => { console.log('Démarrage de BrowserStack Local...'); bsLocal.start(localOptions, (error) => { if (error) { console.error('Erreur lors du démarrage de BrowserStack Local:', error); return reject(error); } console.log('BrowserStack Local démarré avec succès!'); resolve(); }); }); } // Arrêter BrowserStack Local après les tests async function stopBrowserStackLocal() { return new Promise((resolve, reject) => { console.log('Arrêt de BrowserStack Local...'); bsLocal.stop((error) => { if (error) { console.error('Erreur lors de l'arrêt de BrowserStack Local:', error); return reject(error); } console.log('BrowserStack Local arrêté avec succès!'); resolve(); }); }); } // Vérifier si BrowserStack Local est en cours d'exécution function isRunning() { return bsLocal.isRunning(); } module.exports = { startBrowserStackLocal, stopBrowserStackLocal, isRunning }; // Usage dans mocha.js hooks ou jest globalSetup/globalTeardown // // Dans un fichier mocha global hooks: // // const bsLocal = require('./browserstack-local'); // // before(async function() { // this.timeout(30000); // await bsLocal.startBrowserStackLocal(); // }); // // after(async function() { // this.timeout(30000); // await bsLocal.stopBrowserStackLocal(); // });

Cypress avec BrowserStack

BrowserStack prend également en charge les tests Cypress pour les applications web modernes :

Intégration de Cypress avec BrowserStack
// cypress.config.js const { defineConfig } = require('cypress'); module.exports = defineConfig({ e2e: { specPattern: 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}', screenshotsFolder: 'cypress/screenshots', supportFile: 'cypress/support/e2e.js' }, // Configuration pour BrowserStack reporter: 'mochawesome', reporterOptions: { reportDir: 'cypress/reports', overwrite: false, html: true, json: true }, // Variables d'environnement spécifiques à BrowserStack env: { browserstack: true } }); // cypress/browserstack.js const fs = require('fs'); const path = require('path'); const fetch = require('node-fetch'); const FormData = require('form-data'); // Configuration de l'intégration BrowserStack const BROWSERSTACK_USERNAME = process.env.BROWSERSTACK_USERNAME; const BROWSERSTACK_ACCESS_KEY = process.env.BROWSERSTACK_ACCESS_KEY; const BROWSERSTACK_BUILD_NAME = `Build ${new Date().toISOString()}`; // Liste des configurations de navigateurs/appareils const browserConfigs = [ { browser: 'chrome', browser_version: 'latest', os: 'Windows', os_version: '10', name: 'Windows Chrome Test' }, { browser: 'edge', browser_version: 'latest', os: 'Windows', os_version: '11', name: 'Windows Edge Test' }, { device: 'iPhone 13 Pro', os_version: '15', name: 'iOS iPhone Test' } ]; // Génération du fichier browserstack.json function generateBrowserStackConfig() { const config = { auth: { username: BROWSERSTACK_USERNAME, access_key: BROWSERSTACK_ACCESS_KEY }, browsers: browserConfigs, run_settings: { cypress_config_file: './cypress.config.js', project_name: 'My Project', build_name: BROWSERSTACK_BUILD_NAME, callback_url: process.env.CALLBACK_URL || null, parallels: 1 }, connection_settings: { local: true, local_identifier: null } }; fs.writeFileSync( path.join(__dirname, 'browserstack.json'), JSON.stringify(config, null, 2) ); console.log('Fichier browserstack.json généré avec succès.'); } // Téléchargement des rapports de test vers BrowserStack async function uploadReports() { const reportDir = path.join(__dirname, 'cypress/reports'); if (!fs.existsSync(reportDir)) { console.error('Répertoire de rapports non trouvé.'); return; } const jsonReports = fs.readdirSync(reportDir) .filter(file => file.endsWith('.json')); if (jsonReports.length === 0) { console.log('Aucun rapport JSON trouvé à télécharger.'); return; } for (const report of jsonReports) { const formData = new FormData(); formData.append('file', fs.createReadStream(path.join(reportDir, report))); formData.append('build_name', BROWSERSTACK_BUILD_NAME); try { const response = await fetch( `https://api-cloud.browserstack.com/app-automate/cypress/v1/builds/${BROWSERSTACK_BUILD_NAME}/reports`, { method: 'POST', body: formData, headers: { 'Authorization': 'Basic ' + Buffer.from(`${BROWSERSTACK_USERNAME}:${BROWSERSTACK_ACCESS_KEY}`).toString('base64') } } ); const data = await response.json(); console.log(`Rapport ${report} téléchargé: ${JSON.stringify(data)}`); } catch (error) { console.error(`Erreur lors du téléchargement du rapport ${report}:`, error); } } } // Exécuter les tests sur BrowserStack async function runOnBrowserStack() { // Générer la configuration generateBrowserStackConfig(); // Exécuter la commande de lancement BrowserStack const { execSync } = require('child_process'); try { console.log('Démarrage des tests sur BrowserStack...'); execSync('browserstack-cypress run --config-file ./browserstack.json', { stdio: 'inherit' }); console.log('Tests terminés sur BrowserStack.'); // Télécharger les rapports await uploadReports(); } catch (error) { console.error('Erreur lors de l'exécution des tests sur BrowserStack:', error); process.exit(1); } } // Exporter les fonctions pour une utilisation dans les scripts npm module.exports = { runOnBrowserStack, generateBrowserStackConfig, uploadReports }; // Pour exécuter depuis la ligne de commande: // node -e "require('./cypress/browserstack').runOnBrowserStack()"

Tests d'applications mobiles avec Appium

Pour les applications mobiles, BrowserStack s'intègre avec Appium :

Tests Appium avec BrowserStack App Automate
// tests/mobile/app.test.js const { remote } = require('webdriverio'); const assert = require('assert'); // Configuration pour les différents appareils à tester const devices = [ { name: 'iPhone 13', platformName: 'iOS', platformVersion: '15', deviceName: 'iPhone 13', app: 'bs://abcdef123456', // ID BrowserStack de l'app iOS automationName: 'XCUITest' }, { name: 'Samsung Galaxy S22', platformName: 'Android', platformVersion: '12.0', deviceName: 'Samsung Galaxy S22', app: 'bs://654321fedcba', // ID BrowserStack de l'app Android automationName: 'UIAutomator2' } ]; // Fonction pour exécuter les tests sur un appareil spécifique async function runTestOnDevice(deviceConfig) { // Configuration BrowserStack const config = { ...deviceConfig, // Ajout des identifiants BrowserStack 'browserstack.user': process.env.BROWSERSTACK_USERNAME, 'browserstack.key': process.env.BROWSERSTACK_ACCESS_KEY, // Options supplémentaires 'browserstack.debug': true, 'browserstack.networkLogs': true, 'browserstack.geoLocation': 'FR', // Configuration du test project: 'Mon Projet Mobile', build: `Build ${new Date().toISOString()}`, name: `Test sur ${deviceConfig.name}` }; // Initialiser le driver WebdriverIO sur BrowserStack const driver = await remote({ protocol: 'https', hostname: 'hub-cloud.browserstack.com', path: '/wd/hub', port: 443, capabilities: config, logLevel: 'error' }); try { console.log(`Démarrage du test sur ${deviceConfig.name}`); // Exemple de test d'une application mobile // Attendre que l'application démarre await driver.waitUntil( async () => { const element = await driver.$('~login-button'); return element.isExisting(); }, { timeout: 30000, timeoutMsg: 'L\'application n\'a pas démarré correctement' } ); // Interagir avec les éléments de l'application // Pour iOS: identifiants accessibles par l'accessibilityId // Pour Android: identifiants par resource-id ou content-desc await driver.$('~username-input').setValue('testuser@example.com'); await driver.$('~password-input').setValue('password123'); await driver.$('~login-button').click(); // Attendre que la page principale se charge await driver.waitUntil( async () => { const homeScreen = await driver.$('~home-screen'); return homeScreen.isExisting(); }, { timeout: 15000, timeoutMsg: 'La connexion a échoué ou la page principale n\'a pas été chargée' } ); // Vérifier que des éléments spécifiques sont présents const welcomeText = await driver.$('~welcome-message').getText(); assert.ok(welcomeText.includes('Bienvenue'), `Message de bienvenue incorrect: ${welcomeText}`); // Navigation dans l'application await driver.$('~menu-button').click(); await driver.$('~settings-option').click(); // Vérifier qu'on a bien accédé aux paramètres const settingsTitle = await driver.$('~settings-title').getText(); assert.strictEqual(settingsTitle, 'Paramètres', 'Titre de la page des paramètres incorrect'); // Marquer le test comme réussi sur BrowserStack await driver.executeScript( 'browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"passed","reason": "Tous les tests ont réussi!"}}' ); console.log(`Test réussi sur ${deviceConfig.name}`); } catch (error) { console.error(`Erreur sur ${deviceConfig.name}:`, error); // Marquer le test comme échoué sur BrowserStack await driver.executeScript( `browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"failed","reason": "${error.message}"}}` ); throw error; } finally { // Fermer le driver await driver.deleteSession(); } } // Exécuter les tests sur tous les appareils configurés describe('Tests d\'application mobile avec BrowserStack', function() { // Augmenter le timeout pour les tests sur appareils réels this.timeout(40 * 60 * 1000); // 40 minutes for (const device of devices) { it(`devrait fonctionner sur ${device.name}`, async function() { await runTestOnDevice(device); }); } });

Fonctionnalités principales

  • Appareils et navigateurs réels - Tests sur des appareils physiques, pas des émulateurs
  • Débogage avancé - Logs, vidéos, captures d'écran et outils de débogage
  • Tests parallèles - Exécution simultanée de tests sur plusieurs configurations
  • Intégration CI/CD - Compatible avec Jenkins, Travis CI, CircleCI, GitHub Actions, etc.
  • Screenshots rapides - Captures d'écran instantanées sur de multiples navigateurs
  • Testing responsif - Tests sur différentes tailles d'écran
  • Géolocalisation - Tests avec différentes localisations géographiques
  • Tests de performance - Mesures de vitesse et analyses avec Lighthouse

Intégration avec les outils de développement

BrowserStack s'intègre avec de nombreux outils et frameworks populaires :

  • Frameworks de test - Icône SeleniumSelenium, Icône CypressCypress, Appium, TestCafe, Playwright, etc.
  • Frameworks JavaScript - Icône JestJest, Mocha, Jasmine, etc.
  • Systèmes CI/CD - Jenkins, CircleCI, Icône GitHub ActionsGitHub Actions, GitLab CI, etc.
  • Outils de gestion de test - Icône JiraJira, TestRail, etc.
  • Frameworks d'automatisation - Protractor, WebdriverIO, NightWatch, etc.

Bonnes pratiques avec BrowserStack

  • Optimiser les tests parallèles - Utiliser le maximum de sessions parallèles autorisées par votre plan
  • Tester les scénarios critiques - Prioriser les parcours utilisateurs les plus importants
  • Utiliser des timeouts appropriés - Prévoir des délais d'attente plus longs que pour les tests locaux
  • Marquer le statut des tests - Utiliser l'API browserstack_executor pour indiquer si un test a réussi ou échoué
  • Limiter la durée des tests - Garder les tests courts et ciblés
  • Utiliser des identifiants de build - Organiser les tests avec des noms de build explicites
  • Tirer parti des capacités de débogage - Exploiter les vidéos, captures d'écran et logs

Limites et considérations

  • Coût - Service payant avec différents niveaux de tarification basés sur les fonctionnalités et le nombre de sessions parallèles
  • Temps d'initialisation - Le démarrage des sessions peut prendre plus de temps que les tests locaux
  • Disponibilité des appareils - Les appareils très demandés peuvent parfois être indisponibles
  • Temps de session limité - Les sessions ont généralement une durée maximale (entre 30 minutes et 2 heures selon les plans)
  • Restrictions réseaux - Certains réseaux d'entreprise peuvent bloquer les connexions nécessaires

BrowserStack est un outil puissant qui simplifie considérablement le test cross-browser et multi-device, permettant aux équipes de développement de se concentrer sur la création de fonctionnalités plutôt que sur la gestion d'une infrastructure de test complexe. En automatisant les tests sur de multiples plateformes, il accélère les cycles de développement tout en garantissant une expérience utilisateur cohérente sur tous les appareils.

Applications concrètes

Cas d'usage

Tests de compatibilité cross-browser

Vérification qu'un site web ou une application fonctionne correctement sur différentes versions de navigateurs (Chrome, Firefox, Safari, Edge) et systèmes d'exploitation, assurant ainsi une expérience cohérente pour tous les utilisateurs grâce à Icône SeleniumSelenium.

Test d'applications mobiles

Test d'applications iOS et Android sur des appareils réels de différentes générations, tailles d'écran et versions de système d'exploitation, sans avoir à acquérir et maintenir un large parc d'appareils physiques dans des conteneurs Icône DockerDocker.

Tests de régression automatisés

Exécution automatique de suites de tests avec Icône JestJest et Icône CypressCypress après chaque modification du code, en parallèle sur plusieurs environnements, pour détecter rapidement les problèmes de compatibilité introduits par les changements.

Test d'applications locales ou internes

Test d'applications en développement ou d'environnements protégés grâce à BrowserStack Local, qui établit un tunnel sécurisé entre l'infrastructure locale et les navigateurs/appareils de BrowserStack avec intégration à Icône GitHub ActionsGitHub Actions.

Test de design responsif

Vérification du comportement responsive d'un site web sur différentes tailles d'écran et orientations (portrait/paysage), avec possibilité de générer rapidement des captures d'écran sur multiples configurations.

Intégration CI/CD

Intégration des tests BrowserStack dans les pipelines d'intégration et déploiement continus (Jenkins, Icône GitHub ActionsGitHub Actions, etc.) pour automatiser entièrement le processus de validation cross-browser sur différentes plateformes comme Icône DockerDocker et bloquer les déploiements en cas de problème.

Intégration dans un workflow de développement

Voici comment BrowserStack s'intègre typiquement dans le flux de travail d'une équipe de développement web :

  1. Développement local - Les développeurs créent de nouvelles fonctionnalités et les testent d'abord localement sur leur navigateur principal avec Icône JestJest
  2. Test manuel rapide - Utilisation de BrowserStack Live pour vérifier visuellement le comportement sur d'autres navigateurs/appareils clés
  3. Création de tests automatisés - Développement de tests Icône SeleniumSelenium, Icône CypressCypress ou Appium pour les parcours utilisateurs critiques
  4. Intégration continue - Configuration du pipeline CI avec Icône GitHub ActionsGitHub Actions pour exécuter automatiquement les tests sur BrowserStack après chaque commit
  5. Analyse des résultats - Examen des rapports, captures d'écran et vidéos pour identifier les problèmes
  6. Débogage des problèmes - Utilisation des outils de débogage BrowserStack pour reproduire et corriger les problèmes spécifiques à certains navigateurs
  7. Validation avant déploiement - Exécution de tests de régression complets sur l'ensemble des navigateurs et appareils cibles
  8. Monitoring continu - Tests périodiques automatisés pour détecter les problèmes sur les environnements de production

Cette approche permet de détecter et corriger les problèmes de compatibilité tôt dans le cycle de développement, réduisant considérablement le risque de découvrir des problèmes en production et garantissant une expérience utilisateur cohérente sur toutes les plateformes.