Testy w Django z użyciem Selenium

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()
view raw tests.py hosted with ❤ by GitHub

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.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *