Zapraszamy na gościnny wpis Łukasza Krause, o tym jak krok po kroku stworzyć test automatyczny w Python-ie z wykorzystaniem Selenium i Behave.
Tworząc test automatyczny w Python-ie w pierwszej kolejności należy zacząć od zainstalowania zintegrowanego środowiska programistycznego IDE. Ja skorzystałem z PyCharm w wersji Community.
Czego się dowiesz z tego artykułu:
- Jak zainstalować Pythona
- Jak zainstalować dodatkowe biblioteki do Pythona
- Podstaw korzystania z PyCharm
- Techniki tworzenia testów BDD w Pytonie (Behave)
- Podstaw automatyzacji z wykorzystaniem Selenium i Python-a
BDD to testy sterowane zachowaniami (ang. Behavior-Driven Development — dosł. programowanie sterowane zachowaniami). Twórcą tej metody jest Dan North.
W technice BDD mamy do czynienia z łatwą strukturą opierającą się na trzech krokach:
Krok 1. Given: Warunek początkowy
Krok 2. When: Akcja jaką wykonuje użytkownik
Krok 3. Then: Oczekiwany wynik
W taki sposób można tworzyć testy funkcjonalne poprzez historyjki użytkowników.
W kolejnym kroku tworzenia testu automatycznego należy zainstalować Python-a oraz bibliotekę selenium i behave.
Jeśli masz poprawnie zainstalowanego Python-a z obsługą powłoki w cmd (interpreter poleceń dla systemu Windows) powinna działać komenda pip, dzięki której można z poziomu cmd zainstalować behave.
Ważne! Podczas instalacji należy pamiętać, aby zaznaczyć opcję "Add Python to PATH".
Pip to menadżer pakietów dla Python. Dzięki niemu każdy może w łatwy i szybki sposób instalować dodatkowe biblioteki, a także uaktualniać już zainstalowane.
Dla przykładu:
pip install --upgrade selenium
Instrukcję instalacji Behave znajdziesz pod tym linkiem, a tutaj znajdziesz instrukcję do selenium.
W przypadku poprawnie zainstalowanego Pythona dodatkowe biblioteki instalujemy poprzez polecenie pip z poziomu Wiersza poleceń z uprawnieniami Administratora.
W naszym przypadku potrzebne polecenia to:
pip install behave
pip install selenium
Python + PyCharm + selenium + behave to nasz "dream team", który pozwoli nam napisać test automatyczny w BDD.
Następnie uruchamiamy PyCharm i upewniamy się (w oknie ustawień), że potrzebne biblioteki zostały zainstalowane: (File -> Settings -> Project Interpreter)
W przypadku gdyby jakieś biblioteki nie zostały zainstalowane możemy ręcznie je dodać poprzez ikonę
Okno ustawień PyCharm
W katalogu naszego projektu tworzymy katalog features.
W tym miejscu będziemy umieszczać pliki z rozszerzeniem .feature, które będą opisywały funkcje jakie chcemy przetestować. Wspólnie przetestujemy logowanie do poczty e-mail i wysłanie maila.
Naszym pierwszym przypadkiem testowym będzie więc logowanie do poczty.
W katalogu features tworzymy plik login.feature
Tworzenie nowego pliku
W przypadku gdy nie posiadamy wtyczki Gherkin do obsługi plików *.feature wybieramy utworzenie nowego pliku jako tekst.
Następnie PyCharm podpowie nam, że istnieje możliwość instalacji wtyczki do obsługi rozszerzenia *.feature dokonujemy instalacji wtyczki.
Zgodnie z zasadą BDD nazywamy naszą funkcję i opisujemy historię użytkownika a następnie dodajemy scenariusz (given - when - then) przypadku testowego.
W naszym przypadku funkcja testowana to logowanie, więc wpisujemy kod:Feature: sign in to e-mail account
Następnie opisujemy krótką historię przypadku testowego -> jako użytkownik chce się zalogować i sprawdzić swoje maile:Feature: sign in to e-mail account
As a user I want to log in
and check my e-mails
Następnie przechodzimy do napisania scenariusza.
Jako pierwszy scenariusz napisałem logowanie do poczty z poprawnymi danymi.
Kod powinien wyglądać w ten sposób:Scenario: Log in with valid data
Given user is on Poczta Onet website
When user fills in the Sign In form and submits it
Then User can see email list
Dla wyjaśnienia given -> warunkiem początkowym dla naszego testu będzie moment kiedy użytkownik znajduje się na stronie logowania. W dalszych krokach z użyciem when(kiedy) and and(i) opisujemy kroki potrzebne do uzyskania rezultatu, następnie przechodzimy do wyniku naszego testu -> then(wtedy).
Teraz czas na kodowanie w Python-ie, yeeeaahhh 😉
W pierwszej kolejności tworzymy katalog steps gdzie będą umieszczone pliki z analogicznymi nazwami i dodaniem do nazwy pliku _steps z rozszerzeniem .py
W naszym przypadku tworzymy plik login_steps.py
Następnie importujemy potrzebne biblioteki używając kodu:from behave import given, when, then
Metoda driver.get przechodzi do podanej strony poprzez url i czeka, aż strona zostanie załadowana.
Jeśli chcielibyśmy sprawdzić poprawność załadowanej strony moglibyśmy w tym miejscu utworzyć asercję.
Definicja z Wikipedii:
Asercja (ang. assertion) – codedykat (forma zdaniowa w danym języku, która zwraca prawdę lub fałsz), umieszczony w pewnym miejscu w kodzie. Asercja wskazuje, że programista zakłada, że predykat ów jest w danym miejscu prawdziwy. W przypadku gdy predykat jest fałszywy (czyli niespełnione są warunki postawione przez programistę) asercja powoduje przerwanie wykonania programu. Asercja ma szczególne zastosowanie w trakcie testowania tworzonego oprogramowania, np. dla sprawdzenia luk lub jego odporności na błędy. Zaletą stosowania asercji jest możliwość sprawdzenia, w którym fragmencie kodu źródłowego programu nastąpił błąd.
Teraz definiujemy nasz pierwszy krok -> moment kiedy użytkownik jest na stronie do logowania do poczty
Korzystamy z metody driver.get:@given ('user is on Poczta Onet website')
def step_start_page (context):
context.driver.get('http://poczta.onet.pl/')
Kod (nazwa kroku) w sekcji given, when(and), then musi być taki sam jak w scenariuszu .feature dlatego że biblioteka behave w taki sposób mapuje przypadki testowe i odpowiadające im kroki.
Teraz żeby sprawdzić nasze pierwsze linijki kodu tworzymy plik środowiskowy environment.py:from selenium import webdriver
def before_feature(context, feature):
context.driver = webdriver.Chrome()
context.driver.implicitly_wait(2)
def after_feature(context, feature):
context.driver.quit()
W naszym przypadku plik zawiera niezbędne minimum, czyli konfigurację z jakiej przeglądarki będziemy korzystać.
Należy także w katalogu głównym umieścić sterowniki przeglądarki, na której chcemy testować.
Aktualne wersje można pobrać z strony selenium
Do katalogu projektu pobrałem geckodriver.exe (przeglądarka Firefox) oraz chromedriver.exe (Google Chrome), więc teraz mamy możliwość uruchomienia testu na tych dwóch przeglądarkach.
Widok katalogu projektu
Teraz wystarczy tylko zamienić jedną linijkę kodu na :context.driver = webdriver.Firefox()
i test będzie uruchomiony w przeglądarce Firefox.
Teraz musimy poszperać trochę w kodzie strony i "dostać się" do elementów, które umożliwią nam pożądane zalogowanie do skrzynki pocztowej.
W tym celu skorzystamy z funkcji "Zbadaj" (DOM Inspector), która jest dostępna w popularnych przeglądarkach. W Google Chrome można uruchomić narzędzia dla programistów skrótem Ctrl + Shift + I
Widok opcji narzędzi dla programistów (DOM) w poszczególnych przeglądarkach (Edge, Firefox, Chrome)
Nasza strona logowania wygląda następująco:
Strona logowania do Poczty w widoku Narzędzi dla programistów (DOM)
Teraz musimy się dostać do pola nazwy użytkownika i hasła (1),(2) i wprowadzić w te pole odpowiednie dane. Dlatego w DOM musimy znaleźć odpowiedni element (3),(4).
Do elementów najczęściej dostajemy się poprzez id lub selektor css.
Zgodnie z dokumentacją w selenium możemy znajdować element po:
- find_element_by_id
- find_element_by_name
- find_element_by_xpath
- find_element_by_link_text
- find_element_by_partial_link_text
- find_element_by_tag_name
- find_element_by_class_name
- find_element_by_css_selector
Znajdowanie elementów:
- find_elements_by_name
- find_elements_by_xpath
- find_elements_by_link_text
- find_elements_by_partial_link_text
- find_elements_by_tag_name
- find_elements_by_class_name
- find_elements_by_css_selector
Najlepszym i najbardziej bezpiecznym sposobem na znalezienie elementu to wyszukanie go po ID, bo jak wiadomo powinien to być unikalny i niepowtarzalny element. W przypadku gdy pożądany element nie posiada ID można go znaleźć poprzez selektor CSS. W ostateczności zawsze pozostaje nam spróbować z wyszukiwania po xpath.
Nasz kod do znajdowanie pola loginu wygląda następująco:context.driver.find_element_by_id('f_login').send_keys('[email protected])
Na koniec pozostaje kliknąć przycisk zaloguj i w tym przypadku skorzystamy z wyszukania elementu po selektorze CSS i "powiemy" Selenium, aby kliknęła w ten element:context.driver.find_element_by_css_selector('input.loginButton').click()
Na tym etapie nasz kod będzie wyglądać tak:from behave import given, when, then
password = 'zmienna z hasłem'
@given ('user is on Poczta Onet website')
def step_start_page (context):
context.driver.get('http://poczta.onet.pl/')
@when('user fills in the Sign In form and submits it')
def step_set_login_in(context):
context.driver.find_element_by_id('f_login').send_keys('[email protected]')
context.driver.find_element_by_id('f_password').send_keys(password)
context.driver.find_element_by_css_selector('input.loginButton').click()
@then('User can see email list')
def step_valid_login(context):
context.driver.save_screenshot("screenshot-login.png")
assert context.driver.find_element_by_id('mailList-list-items')
Wiadomo, że w językach programowania wcięcia mają olbrzymie znaczenie. Dlatego prawidłowy kod wraz z wcięciami powinien wyglądać tak:
Na koniec pozostał kod rezultatu testu (then). Gdzie sprawdzamy czy użytkownik jest zalogowany i sprawdzamy asercję. W naszym przypadku wybrałem element listy maili, który świadczy o poprawnym zalogowaniu do skrzynki pocztowej.
Dodałem jeszcze na koniec, funkcje zrobienia zrzutu ekranu, aby zobaczyć na zdjęciu poprawne logowanie.@then('User can see email list')
def step_valid_login(context):
context.driver.save_screenshot("screenshot-login.png")
assert context.driver.find_element_by_id('mailList-list-items')
Teraz z poziomu wiersza cmd poleceń w katalogu projektu wystarczy wpisać "magiczne" polecenie behave i test zostanie uruchomiony.
Poniżej screencast jak to wygląda nowo utworzony test automatyczny. Test obejmuje także sprawdzenie funkcji wysyłania maili. Tak mi się ta zabawa spodobała, że nie mogłem pozostać tylko na logowaniu.
Link youtube: https://youtu.be/vQL9d_gj5GQ
Tak będzie się prezentował wynik z wykorzystaniem allure: