Implementieren des Seitenobjektmusters in Python + pytest

Als ich anfing, Testautomatisierung zu studieren, konnte ich nicht verstehen: "Was ist Page Object und wie wird es in Python + pytest implementiert?". Als ich das Internet studierte, fand ich eine Implementierung in anderen Sprachen und Frameworks: Lehrartikel, die für mich unverständlich waren. Deshalb habe ich beschlossen, diese Analyse zu schreiben. Die Idee ist, die Implementierung in Python + pytest zu zeigen und in einer zugänglichen Sprache zu erklären.


Was ist ein Seitenobjekt?


Dies ist ein beliebtes Muster, das de facto der Standard in der Automatisierung von Webprodukttests ist. Die Grundidee besteht darin, die Testlogik von der Implementierung zu trennen.


Jede Projektwebseite kann als Klassenobjekt beschrieben werden. Die Benutzerinteraktion wird in Klassenmethoden beschrieben, und in den Tests verbleibt nur die Geschäftslogik. Dieser Ansatz hilft, Probleme mit Tests beim Ändern des Layouts einer Webanwendung zu vermeiden. Sie müssen nur die Klasse korrigieren, die die Seite beschreibt.


Seitenobjekt definiert die Teile:


  • Basisseite \ Basisklasse - Implementiert die erforderlichen Methoden für die Arbeit mit Webdriver.
  • Seitenobjekt \ Seitenklasse - Implementiert Methoden zum Arbeiten mit Elementen auf Webseiten.
  • Tests - Implementiert die Tests, die in der Geschäftslogik des Testfalls beschrieben sind.

Schema des Seitenobjektmusters.
Bild
Um das Thema klar zu erklären, implementieren wir einen automatisierten Test.


Der theoretische Teil der Implementierung


Schritte :


  1. Der Benutzer öffnet einen Browser.
  2. Der Benutzer gibt https://ya.ru/ in die Adressleiste ein.
  3. Der Benutzer gibt das Wort "Hallo" in die Suchleiste ein.
  4. Der Benutzer klickt auf die Schaltfläche „Suchen“.

Erwartetes Ergebnis :
Der Benutzer wird zur Suche weitergeleitet. Suchergebnisse enthalten Unterelemente (Videos, Bilder usw.).


Überprüfen Sie : Auf der Suchseite gibt es eine Navigationsleiste und Elemente von "Bild" und "Video".


Der praktische Teil der Implementierung


Um den Artikel zu verstehen, müssen Sie die Grundkonstruktionen von Python, OOP, kennen und die Prinzipien und Funktionen von Selen verstehen.


Wir werden die Bibliotheken verwenden: Selen und Pytest. Sie können sie über den Pip-Paketmanager installieren.


pip install selenium pip install pytest 

Vergessen Sie auch nicht, den Treiber für den Browser herunterzuladen. Dieser Artikel verwendet Chrome Webdriver. Sie können es hier herunterladen. Um damit zu arbeiten, legen Sie die Datei im Stammverzeichnis des Projekts ab.


Fixture erstellen


Zuerst müssen Sie die Initialisierung für WebDriver implementieren. Wir werden es in Spielpaarungen beschreiben. Fixtures in Pytest sind Funktionen, die ihre eigene Periodizität der Ausführung haben.
Dies ist ein alternativer Ersatz für die Methoden SetUp und TearDown in unittest. Mithilfe von Vorrichtungen können Sie den Anfangszustand des Systems zum Testen vorbereiten.


In pytest gibt es einen reservierten Namen für die Fixture-Datei - conftest.py .


Wir erstellen die Datei conftest.py und implementieren die Funktion mit dem Namen - Browser.


Wir markieren es mit dem Dekorator @ pytest.fixture und übergeben den Parameter scope mit dem Wert session. Dies bedeutet, dass diese Fixture-Funktion nur einmal pro Testsitzung ausgeführt wird.


 import pytest from selenium import webdriver @pytest.fixture(scope="session") def browser(): driver = webdriver.Chrome(executable_path="./chromedriver") yield driver driver.quit() 

Als nächstes beschreiben wir den Teil, der vor den Tests ausgeführt wird. Es initialisiert den Web-Treiber mit einer Angabe, wo sich der Chrom-Treiber befindet. Als nächstes verwenden wir das Ertragskonstrukt, das die Funktion in Teile unterteilt - vor und nach den Tests.


Im Teil "Nach Tests" rufen wir die Beendigungsfunktion auf, die die Sitzung beendet und die Webdriver-Instanz beendet.


Basisseite


Erstellen Sie die Datei BaseApp.py. In der BasePage-Klasse definieren wir die grundlegenden Methoden für die Arbeit mit WebDriver.


 from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class BasePage: def __init__(self, driver): self.driver = driver self.base_url = "https://ya.ru/" def find_element(self, locator,time=10): return WebDriverWait(self.driver,time).until(EC.presence_of_element_located(locator), message=f"Can't find element by locator {locator}") def find_elements(self, locator,time=10): return WebDriverWait(self.driver,time).until(EC.presence_of_all_elements_located(locator), message=f"Can't find elements by locator {locator}") def go_to_site(self): return self.driver.get(self.base_url) 

Erstellen Sie in der BasePage-Klasse einen Konstruktor, der einen Treiber akzeptiert - eine Instanz von Webdriver. Geben Sie base_url an, mit der die Seite geöffnet wird.


Als nächstes erstellen wir die Methoden find_element (sucht nach einem Element und gibt es zurück) und find_elements (sucht nach der Menge und gibt sie als Liste zurück).


Dies ist ein Wrapper über WebdriverWait, der für explizite Erwartungen in Selen verantwortlich ist.


In der Funktion bestimmen wir die Zeit, die standardmäßig 10 Sekunden beträgt. Dies ist die Zeit, um nach dem Artikel zu suchen. Go_to_site-Methode - Ruft die get-Funktion von WebDriver auf. Mit dieser Methode können Sie zur angegebenen Seite wechseln. Wir übergeben base_url daran.


Seitenobjekt


Unsere Webseitenklasse ist in der Datei YandexPages.py implementiert.


 from BaseApp import BasePage from selenium.webdriver.common.by import By class YandexSeacrhLocators: LOCATOR_YANDEX_SEARCH_FIELD = (By.ID, "text") LOCATOR_YANDEX_SEARCH_BUTTON = (By.CLASS_NAME, "search2__button") LOCATOR_YANDEX_NAVIGATION_BAR = (By.CSS_SELECTOR, ".service__name") class SearchHelper(BasePage): def enter_word(self, word): search_field = self.find_element(YandexSeacrhLocators.LOCATOR_YANDEX_SEARCH_FIELD) search_field.click() search_field.send_keys(word) return search_field def click_on_the_search_button(self): return self.find_element(YandexSeacrhLocators.LOCATOR_YANDEX_SEARCH_BUTTON,time=2).click() def check_navigation_bar(self): all_list = self.find_elements(YandexSeacrhLocators.LOCATOR_YANDEX_NAVIGATION_BAR,time=2) nav_bar_menu = [x.text for x in all_list if len(x.text) > 0] return nav_bar_menu 

Wir erstellen die Klasse YandexSeacrhLocators. Es wird nur zum Speichern von Locators verwendet.
In der Klasse beschreiben wir die Locators:


LOCATOR_YANDEX_SEARCH_FIELD - Suchzeichenfolgen-Locator
LOCATOR_YANDEX_SEARCH_BUTTON - Locator der Schaltfläche "Suchen"
LOCATOR_YANDEX_NAVIGATION_BAR - Navigationsleisten-Locator (Bilder, Videos usw.)


Erstellen Sie eine Klasse SearchHelper, die von BasePage geerbt wird.


Wir implementieren Hilfsmethoden für die Arbeit mit der Suche:
enter_word - sucht nach einem Element der Suchzeichenfolge, klickt und gibt das gewünschte Wort in die Suche ein;
click_on_the_search_button - Sucht nach einem Element der Suchschaltfläche und klickt darauf.
check_navigation_bar - Sucht nach Navigationselementen und ruft das Textattribut ab. Erstellt eine Liste und filtert nach Bedingungen. Wenn die Zeichenfolgenlänge größer als Null ist, wird das Element zur Liste hinzugefügt. Definieren Sie beispielsweise die Standardzeit neu, indem Sie sie auf 2 Sekunden einstellen.


Tests


 from YandexPages import SearchHelper def test_yandex_search(browser): yandex_main_page = SearchHelper(browser) yandex_main_page.go_to_site() yandex_main_page.enter_word("Hello") yandex_main_page.click_on_the_search_button() elements = yandex_main_page.check_navigation_bar() assert "" and "" in elements 

Wir erstellen die Testfunktion test_yandex_seacrh, die das Browser-Fixture akzeptiert. Als nächstes erstellt die erste Zeile das Seitenobjekt - yandex_main_page. Vom Objekt aus nennen wir Interaktionsmethoden mit Seitenelementen. Die Funktion beschreibt die Logik der Benutzeraktionen auf oberster Ebene.


Übertragen wir alles, was wir implementiert haben, in das Schema, ähnlich dem Seitenobjektschema. Benennen Sie die Blöcke unter dem Namen der Dateien aus dem Artikel um.


Bild


Wie Sie sehen, konnten wir das Muster in die Praxis umsetzen.


Ich werde einen Link zum fertigen Repository hinterlassen. Danke fürs Lesen!

Source: https://habr.com/ru/post/de472156/


All Articles