Mozilla's getting a new look. What do you think? https://mzl.la/brandsurvey

Partie 5 : Introduction à un exécuteur de tests

Jusqu'ici tout va bien, mais nous avons toujours traité un seul test. Quand on teste une réelle application web il peut y avoir des centaines de cas de tests, et nous ne voulons certainement pas exécuter chacun d'eux manuellement. Dans un tel scénario, nous devons utiliser un exécuteur de tests pour trouver et exécuter les tests à pour nous. C'est le sujet de cet article.

Exécuteurs de tests

Un exécuteur de tests fournit la bonne base pour un framework de test réel. Il est conçu pour exécuter des tests, des étiquettes de tests avec des attributs (annotations), fournir du reporting et bien d'autres fonctionnalités encore. Il existe de nombreux exécuteurs de tests Python disponibles, mais dans notre cas, nous allons utiliser le unittest de Python puisqu'il est simple, efficace et inclus dans le package Python (comme cela nous n'avons pas besoin d'installer quoi que ce soit).

En général on sépare les tests en 3 sections standard : setUp(), tests, et tearDown(), typique pour une configuration d'exécuteur de tests.
 
Les méthodes setUp() et tearDown() sont exécutées automatiquement pour chaque test et contiennent respectivement :

  • Les étapes de configuration qu'il faut réaliser avant d'exécuter le test, comme déverrouiller l'écran et tuer les applications ouvertes.
  • Les étapes de refroidissement qu'il faut exécuter après le test, comme fermer la session Marionette.

La partie test de la configuration est le code que vous voulez exécuter pour le test en cours. Regardons maintenant comment nous pouvons appliquer cela au test que nous avons construit dans les parties 2 à 4.

Exécuter test_add_contact.py avec unittest

Pour utiliser unittest nous devons tout d'abord importer unittest : ajoutez la ligne suivante en dessous de vos autres lignes d'import :

import unittest

Ensuite, nous devons créer un exécuteur de tests. Pour faire cela, nous allons faire hériter la classe TestContacts de la classe unittest.Testcase ; mettez à jour votre ligne class comme suit :

class TestContacts(unittest.TestCase):

Nous devons également supprimer ceci :

    def __init__(self):
        self.test_add_contacts()

L'initialisation du test sera gérée à la place par unittest, ainsi nous ne devons pas le gérer nous-mêmes. A la fin du code, remplacez ce qui suit :

if __name__ == '__main__':
    TestContacts()

par :

if __name__ == '__main__':
    unittest.main()

Ensuite, nous devons créer une méthode setUp(self): dans notre classe TestContacts et insérer les étapes suivantes :

  1. Instancier Marionette et démarrer une session Marionette
  2. Déverrouiller l'écran
  3. Tuer les applications ouvertes
  4. Charger l'application Contacts

La méthode devrait ressembler au code ci-dessous. Vous devrez supprimer les lignes identiques qui sont déjà dans test_add_contacts.

    def setUp(self):
         # Create the client for this session. Assuming you're using the default port on a Marionette instance running locally
        self.marionette = Marionette()
        self.marionette.start_session()

        # Unlock the screen
        self.unlock_screen()

        # kill all open apps
        self.kill_all()

        # Switch context to the homescreen iframe
        time.sleep(2)
        home_frame = self.marionette.find_element('css selector', 'div.homescreen iframe')
        self.marionette.switch_to_frame(home_frame)

Maintenant passons à la méthode tearDown(self). A l'intérieur de celle-ci nous devons ajouter le code pour fermer la session Marionette. La méthode devrait ressembler à ceci :

    def tearDown(self):
        # Close the Marionette session now that the test is finished
        self.marionette.delete_session()

Encore une fois, n'oubliez pas de supprimer les lignes identiques dans test_add_contacts.

Manitenant essayez d'exécuter le test exactement comme vous l'avez fait précédemment. Vous allez voir que vous obtenez un rapport de succès et d'échecs. Ceci est un des avantages d'utiliser un exécuteur de tests comme unittest ou py.test.

Note : Si vous êtes bloqués, il existe de nombreux guides d'utilisation de unittest sur Internet. Nous recommandons http://selenium-python.readthedocs.org/en/latest/getting-started.html et http://assertselenium.com/2013/10/07/getting-started-with-python-webdriver/. Ils sont pour Python et WebDriver mais sont tout de même appropriés.

Code de référence

Pour référence, notre code final à cette étape ressemble à celui-ci :

import time
from marionette import Marionette
from marionette_driver import Wait
import unittest


class TestContacts(unittest.TestCase):

    def unlock_screen(self):
        self.marionette.execute_script('window.wrappedJSObject.lockScreen.unlock();')

    def kill_all(self):
        self.marionette.switch_to_frame()
        self.marionette.execute_async_script("""
             // Kills all running apps, except the homescreen.
             function killAll() {
               let manager = window.wrappedJSObject.AppWindowManager;

               let apps = manager.getApps();
               for (let id in apps) {
                 let origin = apps[id].origin;
                 if (origin.indexOf('verticalhome') == -1) {
                   manager.kill(origin);
                 }
               }
             };
             killAll();
             // return true so execute_async_script knows the script is complete
             marionetteScriptFinished(true);
            """)

    def setUp(self):
         # Create the client for this session. Assuming you're using the default port on a Marionette instance running locally
        self.marionette = Marionette()
        self.marionette.start_session()

        # Unlock the screen
        self.unlock_screen()

        # kill all open apps
        self.kill_all()

        # Switch context to the homescreen iframe and tap on the contacts icon
        time.sleep(2)
        home_frame = self.marionette.find_element('css selector', 'div.homescreen iframe')
        self.marionette.switch_to_frame(home_frame)


    def test_add_contacts(self):
        contacts_icon = self.marionette.find_element('xpath', "//div[@class='icon']//span[contains(text(),'Contacts')]")
        contacts_icon.tap()

        # Switch context back to the base frame
        self.marionette.switch_to_frame()
        Wait(self.marionette).until(lambda m: m.find_element('css selector', "iframe[data-url*='contacts']").is_displayed())

        # Switch context to the contacts app
        contacts_frame = self.marionette.find_element('css selector', "iframe[data-url*='contacts']")
        self.marionette.switch_to_frame(contacts_frame)

        # Tap [+] to add a new Contact
        self.marionette.find_element('id', 'add-contact-button').tap()
        Wait(self.marionette).until(lambda m: m.find_element('id', 'save-button').location['y']== 0)

        # Type name into the fields
        self.marionette.find_element('id', 'givenName').send_keys('John')
        self.marionette.find_element('id', 'familyName').send_keys('Doe')

        # Tap done
        self.marionette.find_element('id', 'save-button').tap()
        Wait(self.marionette).until(lambda m: not m.find_element('id', 'save-button').is_displayed())

    def tearDown(self):
        # Close the Marionette session now that the test is finished
        self.marionette.delete_session()

if __name__ == '__main__':
    unittest.main()

Étiquettes et contributeurs liés au document

 Contributeurs à cette page : jwhitlock, SphinxKnight, noahchampoux, Goofy, J.DMB
 Dernière mise à jour par : jwhitlock,