Category Archives: automotion

Testy automatyczne Selenium cz3 – zestawy testów.

AKTUALIZACJA

Najnowszą wersję tego wpisu w formie profesjonalnego (i na obecną chwilę darmowego) kursu znajdziesz na moim autorskim portalu https://jaktestowac.pl/kursy/.
Pozdrawiam Przemek

Wstęp

Wzorując sie na podstawowym teście stworzonym w poprzednim poście http://przemek.yum.pl/testy-automatyczne-selenium-cz2-pierwsze-kroki-w-pythonie/ można napisać kolejne.  Jednak pierwsza asercja, która zakończy się niepowodzenie niestety przerwie cały test i kolejne nie będą już wykonywane – mozna to zuważyć choćby po niezamkniętym oknie przeglądarki.

UWAGA:
Poprzednia wersja tego wpisu był pisana w Python3 obecnie jest w wersji Python2 ze względu na biblioteki do testowania które w przyszłości chciałem opisać. Nie podmieniałem screenów bo są to dość kosmetyczne zmiany. Proszę o wzorowanie się na samym tekście kodu z pisanych przykładów bo te na screenach są w Python3 . Zmiany dotyczą rozwiązania z obsługą kodowania znaków: w Python3 nie jest potrzebna pierwsza linia odnośnie kodowania jak i znaczek u przed apostrofem w stringach (ergo – zastosowano domyślnie rozpoznawanie kodowania znaków specjalnych). Pamiętaj więc o literce u przed każdym łańcuchem zawierającym polskie znaki.Dodatkowo uaktualniłem obecny tytuł strony olx 🙂

Wymagania

Do zbudowania fajnie wyglądającego przypadku testowego należy opanować trochę wiedzy z programowania obiektowego – jednak generalnie zostanie tu wszystko opisane. J Zbudujemy klasę testową która bedzie posiadać metody (warto zapamiętać, że motoda to funkcja znajdująca się w klasie) będące osobnymi przypadkami testowymi.

Jak czegoś nie rozumiesz to na razie się tym nie przejmuj – leć z tutkiem dalej i potem przejdź go drugi raz i wtedy zobaczysz co się rozjaśniło czego trzeba się poduczyć.

Piszemy automat

Na początek tworzę nowy plik z testami   olx_main_tests. Dodaję  linie  umożliwijąca kodowanie polskich znaków oraz importy:

# -*- coding: utf-8 -*-
import unittest
from selenium import webdriver

jak widać będe korzystał z biblioteki unittest, która oferuje wiele przydatnych metod do testowania.

Kodzimy – klasa, pierwszy test i uruchomienie

Deklaruję nazwę klasy korzystając ze słowa kluczowego class:

class OlxMainTests(unittest.TestCase):

korzysta ona z gotowych rozwiązań (dziedziczy) zaimplementowanych w bibliotece unittest
Następnie dodaję metodę która jest właśnie naszym testem korzystając ze słowa kluczowego def (self jest  zawsze dodawane przy metodach):
Dodatkowo nazwę metody zaczynam od słowa test – dzięki czemu zostanie ona rozpoznana jako metoda testowa

def test_main_page(self):

Warto zaznaczyć, że w pythonie o przynależności danego wiersza do danej funkcji decyduje wielkość wcięcia. Dla przykładu powyższa deklaracja metody powinna posiadać jeden tabulator gdyż należy do klasy zdeklarowanej powyżej. To samo z ciałem metody, które  wklejamy z naszego poprzedniego testu – powinno ono zawierać jedno wcięcie pod nazwą metody – czyli efekt końcowy to:

class OlxMainTests(unittest.TestCase):
    def test_main_page(self):
        driver = webdriver.Firefox()
        driver.get('http://olx.pl')
        title = driver.title
        print(title)
        assert title == u'Ogłoszenia - Sprzedam, kupię na OLX.pl'
        driver.close()

Można już uruchomić nowy test (nie zapomnij o nowej konfiguracji uruchumieniowej dla tego testu Run->Run..->Unittest OLxMainTest – gdyż w przeciwnym razie uruchomisz stary test)

Po uruchomieniu widać, że test został rozpoznany i powinien zakończyć się sukcesem
2015-05-03_100032

 

Dodanie kolejnego testu i uruchomienie grupy testów

Dodajemy następny test według posiadanego szablonu – sprawdzimy czy podstrona

'http://olx.pl/oferty/'

zawiera ten sam tytuł co główna. Po za zamianą adresu www należy utworzyć nową nazwę metody:

def test_oferty_page(self):
    driver = webdriver.Firefox()
    driver.get('http://olx.pl/oferty/')
    title = driver.title
    print(title)
    assert title == u'Ogłoszenia - Sprzedam, kupię na OLX.pl'
    driver.close()

Możemy nowy test uruchomić za pomocą nowej konfiguracji uruchomieniowej – jednak czas aby wykonac wszystkie testy razem – klik prawym klawiszem myszki na plik olx_main_tests.py i wybieram Run
Widać, że przeglądarka uruchomiła się dwukrotnie oraz wszystkie testy powinny przejść:
2015-05-03_102503Dodatkowo można rozwinąć drzewko wykonanych testów:
2015-05-03_103114

Następny test i … mamy bug – rozpoznawanie problemu i naprawa testu

Dodam kolejny test – stronę: http://olx.pl/zasady/

ale tym razem ma on nie przechodzić – oto wynik:
2015-05-03_111440Test niestety nie przeszedł. Jak można się zorientować po logu w konsoli – na tej podstronie znajduje się inny tytuł.

Czyżbyśmy znaleźli BUGA!

Ciężko stwierdzić – trzeba by było podpytać twórców aplikacji webowej OLX. Na obecna chwilę zakładam, że taki tytuł ma się wyświetlać więc naprawiam test – i powinno wszystko działać.

(HINT: Jeśli od twórców OLX otrzymałbym odp, że to jest błąd na stronie – wtedy nic nie poprawiam i pozostawiam mój test, który będzie tak długo nie przechodzł jak długo nie zostanie poprawiony błąd)

Refaktoryzacja – przeczyszczamy kod

Jak widać pojawia się sporo powtórzonego kodu – dodatkowo test który nie przeszedł pozostawił otwarta przeglądarkę – co by było gdyby tych testów było 1000?

Uniwersalny kod dla każdego testu w jednym miejscu

Na poczatek dodamy metodę, która wykona się przed każdym testem (umieszczam ją przed wszystkimi metodami):

def setUp(self):
    self.EXPECTED_MAIN_TITLE = u'Ogłoszenia - Sprzedam, kupię na OLX.pl'

Metoda  setUp jest już zaimplementowana w bibliotece unittest link – jedynie rozszerzam jej działanie – dzięki czemu korzystam z tego, że unittest zna tę metodię i uruchamia się ona automatycznie przed każdym testem jednocześnie dodając moje warunki.

W metodzie umieściłem zmienną która przechowuje łańcuch znakowy (nazywamy string). Wielkie litery są użyte aby zaznaczyć, że jest to wartość której nie należy modyfikować poza tą metodą. Użycie self pozwala na dostanie się do tej zmiennej przez inne motody (ponieważ one wszystkie posiadają obiekt self) – czyli w innych metodach gdzie powtarza się wyciągnięty string można wprowadzić zmianę

assert title == self.EXPECTED_MAIN_TITLE

Pamiętaj aby uruchamiać testy po takich zmianach aby sprawdzić czy wszystko działa poprawnie.

Zarządzanie przeglądarką

Natepnie zajmuję zajmuję się zarządzaniem przeglądarką.
Dodaję do metody setUp inicjalizaję drivera

self.driver = webdriver.Firefox()

A w metodach zmieniam linię  z inicjalizacją drivera:

driver = self.driver

Lokalna zmienna w metodzie driver otrzymuje referencję do obiektu self.driver. Można to potraktować jak przypisanie do obiektu wygodnego aliasu  dzięki czemu nie trzeba za kazdym razem używać pełnej nazwy z self. Oczywiście można by było nie dodawac tego aliasu i tylko zmienić driver  na self.driver (gdyż driver jest inicjalizowany w metodzie wywołującej się przed kazdym testem setUp) czyli:

def test_oferty_page(self):
    self.driver.get('http://olx.pl/oferty/')
    title = self.driver.title
    print(title)
    assert title == self.EXPECTED_MAIN_TITLE
    self.driver.close()

Będę się posługiwał formą z aliasem gdyz jest czytelniejsza:

def test_oferty_page(self):
    driver = self.driver
    driver.get('http://olx.pl/oferty/')
    title = driver.title
    print(title)
    assert title == self.EXPECTED_MAIN_TITLE
    driver.close()

W podobny sposób do metody wywoływanej przed kazdym testem setUp pozbywam się wywołania zamykania przeglądarki – dodając na końcu klasy metodę tearDown

def tearDown(self):
    self.driver.close()

Dzięki czemu mozna usunąć ze wszystkich metod wiersz z driver.close()

Testy w jednym oknie przeglądarki

Kolejną sprawę którą można zmienić to uruchamiająca się z każdym testem przegladarka – symulując zachowanie uzytkownika warto (w tym przypadku) zrobić testy na jednej instancji przeglądarki.

Dodatkowo zbadam czas wykonywania się wszystkich testów na osbnych instancjach przeglądarki – przyda się do tego opcja w oknie uruchamiania2015-05-03_124550

klikam trybik i zaznaczam Show Statistic w zależności czy klikniemy na Test Result czy pojedynczy test wyświetli nam się czas wykonania całej grupy bądź poszczególnego testu.

Biblioteka unittest posiada metodę, która uruchomi się tylko raz przed testami dzięki temu można ją wykorzystac do uruchomienia przeglądarki. Przenoszę więć inicjalizajcę Firefoxa do nowej metody

@classmethod
def setUpClass(self):
    self.driver = webdriver.Firefox()

Zauważmy, że zamykamy przeglądarkę po każdym teście – czyli drugi test zakończy się błędem gdyz przeglądarka nie będzie uruchomiona. Czas skorzystać z metody która wykona się po wszystkich testach tearDownClass – dopiero wtedy nastapi zamknięcie przeglądarki

# def tearDown(self):
#     self.driver.close()

@classmethod
def tearDownClass(self):
    self.driver.close()

Metoda tearDown nie jest nam na razie potrzebna . Gdy wytniem z niej wiersz z zamknieciem drivera zgłaszała by błąd. Można ją zakomentować jak w przykładzie powyżej lub  tymczasowo zaślepić słowem pass albo usunąć:

def tearDown(self):
    pass

Teraz testy uruchamiają się na jednej instancji przeglądarki co wygląda jak prawdziwa akcja użytkownika.
Warto porównać czas wykonania dla testów w jednej i wielu instancjach przeglądarki:

Osobne przeglądarki: olx_main_tests.OlxMainTests 20.32 s
Jedna przeglądarka: olx_main_tests.OlxMainTests 6.748 s

Podsumowując:

Umiemy teraz napisać wiele testów sprawdzających tytuł strony
Testy mogą uruchomić się na jednej instancji przeglądarki
W testach są assercje co oznacza, że test automatycznie zakończy się niepowodzeniem gdy sprawdzany warunek okaże się błędny

Na koniec jeszcze wklejam cały kod z dzisiejszego posta

# -*- coding: utf-8 -*-
import unittest
from selenium import webdriver

class OlxMainTests(unittest.TestCase):
    @classmethod
    def setUpClass(self):
        self.driver = webdriver.Firefox()

    def setUp(self):
        self.EXPECTED_MAIN_TITLE = u'Ogłoszenia - Sprzedam, kupię na OLX.pl'

    def test_main_page(self):
        driver = self.driver
        driver.get('http://olx.pl')
        title = driver.title
        print(title)
        assert title == self.EXPECTED_MAIN_TITLE

    def test_oferty_page(self):
        driver = self.driver
        driver.get('http://olx.pl/oferty/')
        title = driver.title
        print(title)
        assert title == self.EXPECTED_MAIN_TITLE

    def test_zasady_page(self):
        driver = self.driver
        driver.get('http://olx.pl/zasady/')
        title = driver.title
        print(title)
        assert title == 'Regulamin OLX.pl'

    def tearDown(self):
        pass

    @classmethod
    def tearDownClass(self):
        self.driver.close()

Testy automatyczne Selenium cz2 – pierwsze kroki w pythonie.

AKTUALIZACJA

Najnowszą wersję tego wpisu w formie profesjonalnego (i na obecną chwilę darmowego) kursu znajdziesz na moim autorskim portalu https://jaktestowac.pl/course/pt1-mk1-podstawy-testow-automatycznych-w-selenium-i-python/.
Pozdrawiam Przemek

 

 

W tym poście opiszę jak rozpocząć przygodę z automatyzacją, która wiąże się z programowaniem. Od podstaw napiszę co trzeba zrobić aby stworzyć w pełni działający test automatyczny.

Przygotowanie środowiska

Testową aplikacja będzie olx.pl a wszystkie działania odbywaja się na maszynie z systemem Windows 7 z zainstalowaną przeglądarką Firefox
Zacznę od zainstalowania pythona na maszynie w wersji 2 linkDo pisania testów użyję IDE pycharm w darmowej wersji Community – jest to w pełni dojrzałe IDE i oferuje mnóstwo ciekawych funkcji link
UWAGA: Dokonaj update Fireoxa do najnowszej wersji

Utworzenie projektu

W PyCharmie tworzę nowy projekt – nazwę go olx_tests
Dodaję nowy plik (prawy klawisz myszki na folderze olx_test w widoku Projects) main_page_tests
2015-05-02_192101
Ustawiam pokazywanie numeru lini przy wierszach http://stackoverflow.com/a/8908562

UWAGA: Jeśli już wcześniej posiadałeś zainstalowanego pythona np. w wersji 3 to zainstaluj wesję 2 i ustaw ją dla naszego projektu:
przejdź w pycharmie File->Settings->Project:olx_tests (kliknij trójkąt z lewej)->Project Interpreter. Z listy wybierz odpowiedni interpreter lub klikając w trybik wskarz miejsce instalacji pliku python.exe ze ścieżki która domyślnie wygląda tak  C:\Python27\python.exe

Importowanie bibliotek

Biblioteki to takie gotowy kawałki kodu, dzięki którym nie trzeba wszystkiego pisać na nowo a wystarczy skorzystac z istnięjących roziwązań. Tutaj będę korzystał z biblioteki WebDriver o której funkcje opisane są tutaj

Czas jej użyć:

from selenium import webdriver

czyli z bilioteki selenium importujemy klasę webdriver.
Podkreślone na czerwono obie nazwy sugerują, że nasze IDE nie posiada zaimportowanych takich bibliotek.
PyCharm oferuje automatyczne importy więc klikam na nazwę selenium i wciskam kombinację klawiszy odpowiedzialną za podpowiedzi akcji naprawczych ALT + ENTER (powinna pojawić się także czerwona żarówka która można kliknąć i uzyskamy ten sam efekt).
Wybieram pierwszą opcję – install package selenium.
Podkreślenie powinno zniknąć co oznacza powodznie akcji.

UWAGA: Jeśli już wcześniej miałeś zainstalowaną bibliotekę selenium mozliwe, że potrzebny będzie Ci update: przejdź w pycharmie File->Settings->Project:olx_tests (kliknij trójkąt z lewej)->Project Interpreter. Odnajdź bibliotekę (Package) selenium a następnie upewnij się czy wartości w Version i Latest są identyczne. Jeśli nie to kliknij linie z selenium i naciśnij niebieską strzałkę skierowaną w górę z prawej strony. Następnie OK i juz masz zaktualizowaną bibliotekę.

Pierwszy kod

Czas skorzystać z webdriver: wpisuję więc kolejną linię
(warto zrobić jedeno linijkową przerwę pomiędzy deklaracjami importów a właściwym kodem – są to zalecenia formatowania języka python)

driver = webdriver.Firefox()

przypisuję tu do zmiennej driver obiekt który zawiera w sobie instancję przegladarki Firefox.

Uruchamianie kodu

Czas sprawdzić napisany kod – z górnego menu wybieram Run->Run..->main_page_test
Na dole pojawi się okno z informacjami na temat uruchomionego pliku i powinna zostać automatycznie uruchomiona instancja przeglądarki Firefox.
Zamykam okno Firefoxa co kończy test.

Sterowanie przeglądarką

Zmienna dirver jest jej reprezentacją więc można wywołać na niej różne funkcje – na przykład przejście do danego adresu:

driver.get('http://olx.pl')

Ostatnia konfiguracja uruchumieniowa została zapamiętana więc test można uruchomić  z kombinacji SHIFT + F10 lub kliknąć zieloną strarzałkę w prawym górnym rogu.

Tym razem przeglądarka powinna wyświetlić testowaną stronę.
W następnym kroku pobieram tytuł strony i zapisuję go do zmiennej title.
Kolejny wiersz to wypisanie zawartości zmiennej na konsole.

title = driver.title
print(title)

Po uruchomeinu testu uzyskałem taki rezultat
2015-05-02_215302UWAGA: text tytułu może ulec w każdej chwili zmianie więc zrwróć uwagę na wynik w konsoli i uaktualnij o nową wartość poniżej zaprezentowane przykłady.

Warunek pozytywnego zakończenia testu

Teraz dodam asercję czyli funkcję która porównuje dwie zmienne i w zależnie od rezultatu kończy się sukcesem bądź niepowodzeniem:

assert title == u'Ogłoszenia - Sprzedam, kupię na OLX.pl (dawniej Tablica.pl)'

UWAGA:  W łańcuchu znakowym znajdują się polskie znaki dlatego w powyższym kodzie umieściłem przed apostrofem znak u. Kolejnym krokiem jest dodanie kodu na samej górze pliku:

# -*- coding: utf-8 -*-

Wracamy do kodu z aserciją. Zauważmy, że zastosowałem tutaj  == ponieważ pojedynczy znak = słóży do przypisywania wartości do zmiennej,  w tym przypadku potrzebujemy porównania wartości.
(czyli x=5 oznacza, że x zwraca 5 a x==5 sprawdza czy x zawiera 5 i zwraca True albo False)
Uruchamiam ponownie test i nic się nie zmienia – ponieważ test pozytywnie się skończył.
Zróbmy jednak eksperyment:
Kopiuję linę  nr 5, komentuję ją za pomocą znaku # (dzięki czemu nie będzie wykonywana) a w kopii zmieniam adres na ebay.com czyli:

#driver.get('http://olx.pl')
driver.get('http://ebay.com')

Uruchamiam test i na konsoli otrzymuję:

Traceback (most recent call last):
 File "C:/tut/olx_tests/main_page_tests.py", line 9, in <module>
 assert title == u'Ogłoszenia - Sprzedam, kupię na OLX.pl (dawniej Tablica.pl)'
AssertionError
Electronics, Cars, Fashion, Collectibles, Coupons and More | eBay

Process finished with exit code 1

Widać, że tytuły który oczekiwaliśmy nie zgadza się z otrzymanym. Oraz mamy exit code 1 co oznacza, że pojawiły się problemy.

Wracam do poprawnej wersji driver.get (czyli odkomentowuję linię 5 i usuwam linię 6)
Aby ułatwić sobie sprawę dodaję automatyczne zamykanie przeglądarki – czyli wpisuję na końcu linię:

driver.close()

Podsumowanie i cały kod

I tym samym mam bardzo podstawowy test sprawdzający czy pod danym adresem znajduje się strona o określonym tytule.

Cały kodzik:

# -*- coding: utf-8 -*-
from selenium import webdriver

driver = webdriver.Firefox()
driver.get('http://olx.pl')
title = driver.title 
print(title)
assert title == u'Ogłoszenia - Sprzedam, kupię na OLX.pl (dawniej Tablica.pl)'
driver.close()

W nastepnym poście opiszę w jaki sposób grupować wiele testów, wyciągać z nich powtarzające się informację oraz jak to wszystko uruchomić w PyCharm http://przemek.yum.pl/testu-automatyczne-selenium-cz3-zestawy-testow/

Testy automatyczne Selenium cz1 – Selenium IDE

AKTUALIZACJA

Najnowszą wersję tego wpisu w formie profesjonalnego (i na obecną chwilę darmowego) kursu znajdziesz na moim autorskim portalu https://jaktestowac.pl/course/pt1-mk1-podstawy-testow-automatycznych-w-selenium-i-python/. Z samego Selenium IDE zrezygnowałem gdyż jest zbyt trudne do używania i w podobnym czasie zrobisz takie testy w profesjonalnym zestawie narzędzi (za darmo 🙂 )
Pozdrawiam Przemek

——————————————————————————————————————

Postanowiłem zrobić mały kursik, w którym od podstaw przedstawię proces tworzenia testów automatycznych. Skupię się w nim na testach GUI (warstwy prezentacji) aplikacji webowych czyli takich które mają za zadanie wiernie odwzorować zachowanie użytkownika na danej stronie.

Część 1 –  coś prostego i niezwykle szybkiego Selenium IDE
Do zastosowania w raczej prostych aplikacjach z niewielką ilościa podstron, w końcowej fazie rozwoju aplikacji – gdy zmiany na GUI nie są zbyt poważne a potrzeba zapewnienia o poprawnie działających komponentach.

  1. Zainstaluj przeglądarkę Firefox (albo uaktualnij do najnowszej wersji) – będę korzystał  i polecam wersję angielskojęzyczną
  2. Zainstaluj plugin Selenium:
    ja zrobiłem to manualnie:
    – pobrałem z oficjalnej strony Selenium http://release.seleniumhq.org/selenium-ide/2.9.0/selenium-ide-2.9.0.xpi
    – w FF w sekcji Menu/Add-ons (lub przez linka about:addons) klknąłem ikonkę trybika
    – skorzystałem z opcji

    Install Add-on From File...

    – zaakceptowałem i restart
    – w menu addons/Extensions powinny być widoczne zainstalowane rozszerzenia

  3. Zainstalowana wtyczka selenium objawia się ikonką  obok ikony menu FF
  4. Otwieram http://www.lolcats.com i klikam ikonkę wtyczki selenium co powoduje otwarcie nowego okna przeglądarki z programem selenium ide:
    2015-03-28_145952
  5. Nagrywam test (otwarcie wtyczki ustawia ją w stan automatycznego nagrywania):
    Przechodzę do strony testowej i odświeżam ją (F5), następnie do Galllery i klikam na baner LOLCATS.COM
    Wracam do wtyczki i zakańczam nagrywanie czerwonym przyciskiem record
  6. Mamy pierwszy test – powinien wyglądac tak:
    2015-03-28_151030Teraz odpalam test kozystając z zielonej ikonki ze strzałką i trzema prostokątami.
    Testy są ustawione na maksymalną szybkość i ze względu na jakiś tajemniczy bug potrafią się wysypać na ostatnim kroku:
    2015-03-28_151602Zmiejszenie prędkości powinno coś poprawić jednak wtyczka potrafi czasem się zawiesić i trzeba się z tym liczyć. Dobry wynik:
    2015-03-28_151701
  7. Taki test można zachować i odtwarzać ponownie.
    Można się pokusić o małą edycję:
    Kopiuję i wklejam krok z link=Gallery
    Klikam na zduplikowany krok
    Zmieniam w oknie Target z Gallery na Submit
    Uruchamiam test i widzę dodaną podstronę.
    Można również dograć kolejne kroki

W Selenium IDE oferuje o wiele więcej:
– grupowanie i zachowywanie przypadków testowych
– task scheduler pozwoli  na zaprogramowanie cykli wykonywania testów
– testy mozna wyeksportować do jednego z wielu wspieranych języków programowania
– testy można edytowac poprzez sekcję Source, zmieniać sposób w jaki elementy są odnajdywane na stronie
– jest wiele pluginów które rozszerzają funkcje  IDE można je znaleźć tu:
http://www.seleniumhq.org/download/#side_plugins

Wyeksportowanie skryptu do pythona (webdriver) dało prawie działające testy:
Trzeba było zaimportować bibliotekę selenium oraz zmienić usunąć końcowy slash z adresu – generalnie po tym zabiegu zaczeły działać.

Plugin Selenium IDE może wystarczyć do prostych testów jednak nie są one zbyt elastyczne , jak i stabilność wtyczki pozostawia wiele do życzenia. Aby uniknąć tych kłopotów warto skorzystać z bardziej zaawansowanej metody testów z użyciem Web Drivera – http://przemek.yum.pl/testy-automatyczne-selenium-cz2-pierwsze-kroki-w-pythonie/.