Tworząc nawet najprostszą aplikację, bardzo szybko dochodzimy do momentu, w którym „przeklikanie” głównych ścieżek w aplikacji zaczyna być bardzo czasochłonne i nużące. Wprowadzenie nowych funkcji zaczyna być irytujące. Jest to szczególnie uciążliwe w interpretowanych językach, gdzie informację o ewentualnych błędach dostajemy dopiero po wejściu na stronę lub wykonaniu jakiejś akcji.
Kolejnym problemem jest gdy mamy do przejścia jakiś dłuższy scenariusz, aby sprawdzić jakąś funkcjonalność. Po kilku przejściach i rosnącym zdenerwowaniu, gdy funkcjonalność wciąż nie chce działać, sprawia, że pomijamy część elementów, które mogą mieć wpływ na działanie (lub niedziałanie). Takie scenariusze możemy mnożyć dowolnie. Dlatego warto zastanowić się nad zautomatyzowaniem takich powtarzalnych czynności. Do tego świetnie nadaje się biblioteka Selenium, która bardzo ułatwia testowanie z użyciem prawdziwej przeglądarki.
Instalacja
W Pythonie/Django instalacja jest bardzo prosta, wystarczy zainstalować pakiet, używając do tego celu pip:
pip install selenium
I to już nam pozwoli na korzystanie z dobrodziejstw biblioteki.
Aplikacja
Do celów demonstracyjnych posłuży pusta aplikacja z panelem administratora.
Użyta aplikacja dostępna jest na GitHubie pod adresem: https://github.com/mloza/django_selenium
Projekt zawiera również bazę sql lite, więc aplikacja jest gotowa do uruchomienia.
Pierwszy test
Zacznijmy od czegoś prostego: poprawne logowanie do panelu administracyjnego. Tworzymy testowego użytkownika, sprawdzamy, czy możemy się zalogować do panelu, a następnie usuwamy użytkownika. Otwieramy plik SeleniumTests/tests.py:
from django.contrib.auth.models import User | |
from django.contrib.staticfiles.testing import StaticLiveServerTestCase | |
from selenium.webdriver.firefox.webdriver import WebDriver | |
from selenium.webdriver.support.wait import WebDriverWait | |
class AuthenticationTests(StaticLiveServerTestCase): | |
def __init__(self, methodName='runTest'): | |
super().__init__(methodName='runTest') | |
#dane konta testowego | |
self.username = "test" | |
self.email = "test@test.com" | |
self.test_pass = "test_pass" | |
@classmethod | |
def setUpClass(cls): | |
#otwieramy przeglÄ darkÄ | |
super(AuthenticationTests, cls).setUpClass() | |
cls.selenium = WebDriver() | |
@classmethod | |
def tearDownClass(cls): | |
#zamykamy przeglÄ darkÄ | |
cls.selenium.quit() | |
super(AuthenticationTests, cls).tearDownClass() | |
def runTest(self): | |
#tworzenie użytkownika | |
user = User.objects.create_superuser(self.username, self.email, self.test_pass) | |
user.save() | |
#próba zalogowania | |
self.selenium.get("%s/admin" % self.live_server_url) | |
self.selenium.find_element_by_id("id_username").send_keys(self.username) | |
self.selenium.find_element_by_id("id_password").send_keys(self.test_pass) | |
self.selenium.find_element_by_css_selector("input[type='submit']").click() | |
#czekamy aż zaÅaduje siÄ strona panelu | |
WebDriverWait(self.selenium, 2).until(lambda driver: driver.find_element_by_css_selector("#content h1")) | |
#sprawdzamy czy jesteÅmy na stronie panelu | |
self.assertEqual("Site administration", self.selenium.find_element_by_css_selector("#content h1").text) | |
#sprzÄ tamy | |
user.delete() |
W konstruktorze inicjalizuję nazwę uzytkownika, hasło i e-mail. Następnie mamy metodę def setUpClass(cls), która wywoływana jest raz, przed uruchomieniem wszystkich testów. W niej jest inicjalizowane Selenium. Kolejną metodą jest def tearDownClass(cls), która jest wywoływana po zakończeniu wszystkich testów i ma za zadanie posprzątać po teście. W tym przypadku zamyka przeglądarkę.
Ostatnią metodą jest metoda zawierająca test. W pierwszych 3 linijkach tworzymy użytkownika w bazie danych, którego będziemy używać do sprawdzania logowania. Następnie otwieramy stronę panelu administracyjnego. Program przejdzie dalej gdy strona się załaduje. Wtedy wyszukujemy elementy, których będziemy używać. Jest kilka sposobów na wyszukanie elementu, możemy to zrobić, używając id, klasy css, selektora css lub xpatha. Metoda send_keys symuluje wciskanie klawiszy, natomiast metoda click – kliknięcie w element. Te linijki są odpowiedzialne za wypełnienie formularza logowania i wysłania go. Następnie musimy poczekać, aż kolejna strona się załaduje. Robimy to, tworząc WebDriverWait, któremu mówimy, że czekamy 2 sekundy, aż będzie spełniony warunek. W warunku definiujemy, że zostanie odnaleziony element przez selektor css #content h1. Test uruchamiam lokalnie, więc 2 sekundy są wystarczające, dla innych przypadków trzeba odpowiednio dostosować czas. Gdy mamy już załadowaną stronę sprawdzamy, czy w nagłówku znajduje się napis Site administration.
Ostatnim krokiem jest usunięcie użytkownika z bazy danych. Co prawda baza do testów jest kopiowana i nie byłoby problemu pozostawienie usera w bazie, jednak może to interferować z innymi przypadkami testowymi i najlepiej po sobie posprzątać.
Podsumowanie
Użycie Selenium pozwala nam w łatwy sposób automatyzować powtarzalne czynności. Najczęściej używane jest do automatyzacji testów GUI, ale nic nie stoi na przeszkodzie, aby użyć go do automatyzacji innych powtarzalnych czynności.