Découverte de Mocha
Tester sur le navigateur
Tester avec un Framework
Tests fonctionnels

Le end-to-end testing consiste à tester notre application comme un utilisateur standard sur un vrai navigateur. Pour mettre en place ce type de tests il est nécessaire d'automatiser les navigateurs afin de les faire dérouler un scénario précis. Cette automatisation peut se faire gràce à l'outil Selenium qui est très efficace mais pas forcément simple d'utilisation.

Nightwatch.js va vous permettre d'écrire vos tests en utilisant une syntaxe familière et de piloter les navigateurs via Selenium depuis NodeJS.

Configuration

La configuration de nightwatch.js se fait au moyen d'un simple nightwatch.json

{
  "src_folders" : ["tests"],
  "output_folder" : "reports",
  "custom_commands_path" : "",
  "custom_assertions_path" : "",
  "page_objects_path" : "./pages",
  "globals_path" : "",

  "selenium" : {
    "start_process" : true,
    "server_path" : "bin/selenium-server-standalone-3.4.0.jar",
    "log_path" : "",
    "port" : 4444,
    "cli_args" : {
      "webdriver.chrome.driver" : "bin/chromedriver",
      "webdriver.gecko.driver" : "bin/geckodriver"
    }
  },

  "test_settings" : {
    "default" : {
      "launch_url" : "http://localhost",
      "selenium_port"  : 4444,
      "selenium_host"  : "localhost",
      "silent": true,
      "screenshots" : {
        "enabled" : true,
        "on_failure" : true,
        "on_error" : false,
        "path" : "screens"
      },
      "desiredCapabilities": {
        "browserName": "firefox",
        "marionette": true
      }
    },

    "chrome" : {
      "desiredCapabilities": {
        "browserName": "chrome"
      }
    },

    "edge" : {
      "desiredCapabilities": {
        "browserName": "MicrosoftEdge"
      }
    }
  }
}

L'ensemble des options disponibles sont documentées sur la page Getting Started. J'ai choisi ici de mettre selenium et les différents drivers dans un dossier bin à la racine de mon projet.

Les tests

Les tests s'écrivent ensuite simplement en exportant un simple objet JavaScript qui va contenir nos scénarios de test.

module.exports = {

  // On teste le résultat de ce tutoriel
  // https://www.grafikart.fr/tutoriels/symfony/champs-imbriques-888
  'Select region': function (browser) {
    let selectRegion = '//select[@id="appbundle_medecin_region"]'
    let selectDepartement = '//select[@id="appbundle_medecin_departement"]'
    let selectVille = '//select[@id="appbundle_medecin_ville"]'

    browser
      .url('http://localhost:8000/medecin/new')
      .useXpath()
      .click(selectRegion)
      .click(selectRegion + '/option[text()="Languedoc-Roussillon"]')
      .waitForElementPresent(selectDepartement + '/option[text()="Hérault"]', 1000)
      .click(selectDepartement)
      .click(selectDepartement + '/option[text()="Hérault"]')
      .waitForElementPresent(selectVille + '/option[contains(text(), "Montpellier")]', 1000)
      .click(selectVille)
      .screenshot()
      .end()
  }

}

Afin de sélectionner des éléments dans notre page on pourra utiliser des sélecteurs CSS ou Xpath. Même si au premier abord le CSS semble plus simple, Xpath propose plus d'options et permet plus de contrôle sur les éléments à récupérer.

Si vous faites plusieurs tests pour un même site et que vous souhaitez éviter de répéter les même sélecteurs encore et encore vous pouvez créer un objet pour représenter une page.

// pages/datepicker.js
module.exports = {
  url: 'https://www.grafikart.fr/demo/VueJS/datepicker/index.html',
  elements: {
    datepicker: '.datepicker',
    dateInput: '.datepicker__container input:first-child',
    okButton: {
      selector: '//button[text()="Ok"]',
      locateStrategy: 'xpath'
    },
    dateButton: {
      selector: '//span[@class="datepicker__day__text" and text()="4"]',
      locateStrategy: 'xpath'
    }
  }
}

Vous pourrez ensuite utiliser cette page dans vos tests

module.exports = {

  'Datepicker' : function (browser) {
    let page = browser.page.datepicker()
    page.navigate()
      .click('@dateInput')
      .waitForElementVisible('@datepicker', 1000)
      .click('@dateButton')
      .click('@okButton')
      .waitForElementNotPresent('@datepicker', 1000)

    page.expect.element('@dateInput').to.have.value.that.equals('04/02/2016')

    browser.end()
  }

}

Vous pouvez même aller plus loin en étendant Nightwatch afin de rajouter des commandes spécifiques suivant vos besoins.