Kodzimy – dodajemy importy

Kontynuujemy testowanie poznanej w części pierwszej kursu strony https://demobank.jaktestowac.pl/ oraz jej podstrony.

Na początek stworzymy nowy plik z testami auto_test_2.py w folderze demo_tests (w tym samym miejscu gdzie znajduje się plik z pierwszej części kursu).

Od razu dodamy do niego nowy import modułu unittest, który oferuje wiele przydatnych metod do testowania i jest domyślnym modułem Pythona (więc nie trzeba go pobierać jak to było w przypadku Selenium).

import unittest

Następnie dodamy do niego znany nam import selenium:

import unittest
from selenium import webdriver

Zauważ, że nie musimy znowu pobierać pakietu Selenium i od razu jest on rozpoznawany. W poprzednim kursie zaimportowaliśmy ten pakiet i stał on się częścią obecnej instalacji języka Python, dzięki czemu możemy z niego teraz korzystać tak jak z wbudowanych pakietów.

Klasa oraz pierwszy test

Zapoznamy się tu z nowym pojęciem klasy w języku Python poprzez skorzystanie z instrukcji class.

TIP: Czym jest klasa? W dużym uproszczeniu – jest to zbiór metod i wartości, który służy do tworzenia różnychobiektów. Na początku w przypadku testów będziemy tworzyć klasę, która zawierać będzie w sobie wszystkie metody testowe (czyli po prostu testy). W dalszej części kursu opiszemy dokładniej zagadnienia związane z klasami i obiektami.

 

class MainTests:

Oto bardzo prosta deklaracja klasy. Używamy słowa kluczowego class i nadajemy nazwę naszej klasie. W języku Python nazwę klasy konstruujemy ze standardowych znaków alfabetu łącząc poszczególne słowa zaczynając je od dużych liter. Czyli analogicznie chcąc zrobić klasę dla prostych testów nazwiemy ją SimpleTests.
Jak zauważyłeś po nazwie klasy dajemy znak dwukropka : co oznacza, że w następnych liniach musi znaleźć się kod potrzebny aby ta klasa się uruchomiła.

My od razu zabierzemy się za tworzenie specjalnej klasy z testami czyli rozwiniemy naszą deklarację klasy o dodanie nawiasów i wypełnieniem ich kodem z użyciem wcześniej zaimportowanego modułu:

class MainTests(unittest.TestCase):

Nasza klasa teraz korzysta (profesjonalnie: dziedziczy) z gotowych rozwiązań zaimplementowanych w module unittest a dokładnie z innej klasy TestCase, dlatego po nazwie naszej klasy w nawiasach dodaliśmy kod unittest.TestCase.

Następnie dodajemy do naszej klasy kod: własną metodę, która jest właśnie naszym testem.

import unittest
from selenium import webdriver

class MainTests(unittest.TestCase):
    def test_demo_login(self):
        pass

Obowiązuje tu kilka zasad

  1. Korzystamy z instrukcji def tworząc metodę
  2. W nawiasach po nazwie metody umieszczamy parametr self jest zawsze dodawany przy metodach, więcej o nim napiszemy w kolejnych lekcjach tego kursu – niemniej musi tam się znaleźć:)
  3. Po deklaracji instrukcji umieszczamy znak dwukropka :, tak jak w przypadku klasy oznacza to, że będziemy dodawali w naszej metodzie kod 🙂
  4. Dodatkowo nazwę metody musimy zacząć od słowa test (np: test_strona_glowna) – dzięki czemu zostanie ona rozpoznana jako metoda testowa i tak też wykonana.
TIP: Tu pojawiło się słowo kluczowe pass – oznacza ono po prostu pustą linię, która nie robi niczego. Po co taka konstrukcja? Służy głównie do tworzenia “zaślepek metod” – czasem chcemy zdefiniować jedynie nazwy metod w klasie, ale nie chcemy ich jeszcze uzupełniać. Konstrukcja pass jest przydatna przy błędzie IndentationError.

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 zadeklarowanej powyżej. To samo z ciałem metody, które wklejamy z naszego poprzedniego testu – powinno ono zawierać jedno wcięcie pod nazwą metody.

Kopiujemy kod który został stworzony w pierwszym kursie serii Podstawy Testów Automatycznych w Selenium i Python cz. I – Twój pierwszy test automatyczny. Upewniamy się, że adres testowanej strony to https://demobank.jaktestowac.pl/logowanie_etap_1.html, a oczekiwany tytuł to Demobank – Bankowość Internetowa – Logowanie i efekt końcowy to:

import unittest
from selenium import webdriver

class MainTests(unittest.TestCase):
   def test_demo_login(self):
       driver = webdriver.Chrome(executable_path=r"C:\TestFiles\chromedriver.exe")
       driver.get('https://demobank.jaktestowac.pl/logowanie_etap_1.html')
       title = driver.title
       print(title)
       assert 'Demobank - Bankowość Internetowa - Logowanie' == title 
       driver.quit()
TIP: W Pythonie każda konstrukcja (klasa, metoda, pętla itp) musi mieć pod sobą przynajmniej jedną linię kodu z wcięciem gdyż w przeciwnym wypadku dostaniemy błąd IndentationError.

Uruchamianie klasy testowej

Można już uruchomić nowy test. W tym celu należy dodać nową konfigurację uruchomieniową dla klasy testowej co jest czymś odrobinę innym od konfiguracji uruchomieniowej dla pliku, z której korzystaliśmy w poprzednim kursie (różnice i szczegóły omówimy szerzej w kolejnych lekcjach tego kursu).
Jeśli użyjesz skrótu w prawym górnym rogu do uruchomienia testu lub skrótu klawiszowego SHIFT + F10 to wykorzystana zostanie ostatnia używana konfiguracja – czyli w naszym przypadku z poprzedniego kursu. Aby dodać nową konfigurację dla naszej klasy testowej przejdź do Run->Run..->Unittest MainTests a następnie z okienka, które się wyświetliło na środku ekranu wybierz interesującyą nas konfigurację zaczynającą się od Unittestest for auto_test_2…. Na screenach poniżej znajdują się poszczególne kroki:

 

 

Uwaga: Jeśli napotkałeś problemy przejdź do lekcji https://jaktestowac.pl/lesson/pt1-mk2-03-konfiguracje-uruchomieniowe-w-pycharm/ gdzie dokładnie wyjaśniamy dlaczego taka a nie inna konfiguracja uruchomieniowa została zaproponowana na powyższym screenie.

 

Teraz możesz już używać skrótu SHIFT + F10 czyli uruchomisz ostatnio używaną konfigurację testową.
Dodatkowo możesz przełączać się pomiędzy konfiguracjami uruchomieniowymi klikając strzałkę z prawej strony nazwy pliku w oknie konfiguracji w prawym górnym rogu IDE (zaznaczamy to na poniższym obrazku) aby powrócić do szybkiego uruchamiania auto_test_1.py.

Na dole obrazka oznaczyliśmy jak powinien przedstawiać się wynik puszczenia testów:

25 komentarzy

  1. Hej, po odpaleniu testów, testy się wykonują jednak dostaję ResourceWarning, jakieś wskazówki jak się go pozbyć (jestem ultra początkująca, więc może to jakiś trywialny problem) 🙂

    "C:\Users\Magda Cieślik\AppData\Local\Programs\Python\Python310\python.exe" "C:\Program Files\JetBrains\PyCharm Community Edition 2021.3.1\plugins\python-ce\helpers\pycharm\_jb_unittest_runner.py" --path C:/Projects/demo_tests/auto_test_2.py
    Testing started at 10:04 ...
    Launching unittests with arguments python -m unittest C:/Projects/demo_tests/auto_test_2.py in C:\Projects\demo_tests
    
    
    OK
    
    Process finished with exit code 0
    C:\Users\Magda Cieślik\AppData\Local\Programs\Python\Python310\lib\subprocess.py:1067: ResourceWarning: subprocess 19016 is still running
      _warn("subprocess %s is still running" % self.pid,
    ResourceWarning: Enable tracemalloc to get the object allocation traceback
    C:\Users\Magda Cieślik\AppData\Local\Programs\Python\Python310\lib\site-packages\selenium\webdriver\common\service.py:194: ResourceWarning: unclosed file 
      self.process = subprocess.Popen(
    ResourceWarning: Enable tracemalloc to get the object allocation traceback
    Demobank - Bankowość Internetowa - Logowanie
    
    
    Ran 1 test in 3.125s
    
    Avatar Magdalena Cieślik
    1. Hej 😉
      1. Jak wygląda Twój kod testów, na którym pracujesz?
      2. Czy ten błąd pojawia się zawsze?
      3. Czy w między czasie restartowałaś komputer i np. spowodowało to pojawienie się/zniknięcie problemu? 🤔

      Błąd wskazuje, że jakiś zasób (plik/serwis/webdriver, na który wskazuje subprocess z błędu) nie został poprawnie zamknięty 🙂 Myślę, że więcej szczegółów wyczytamy z Twojego kodu 😉

      Krzysiek Kijas Krzysiek Kijas
  2. Cześć!

    niestety pomimo wszystkich wskazówek związanych z dodawaniem, usuwaniem, a potem ponownym dodaniem konfiguracji ostatecznie mój kod nie działa tak jak powinien. Kod jest taki jak w tutku. Proszę o pomoc 🙂

    Efekt: (wybaczcie, nie wiem jak wkleić żeby było w konsoli)

    Testing started at 12:23 ...
    C:\TestFiles\skrypty\venv\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm Community Edition 2020.2.2\plugins\python-ce\helpers\pycharm\_jb_unittest_runner.py" --path C:/TestFiles/skrypty/auto_test_2.py
    Traceback (most recent call last):
      File "C:\Program Files\JetBrains\PyCharm Community Edition 2020.2.2\plugins\python-ce\helpers\pycharm\_jb_unittest_runner.py", line 35, in 
    Launching unittests with arguments python -m unittest C:/TestFiles/skrypty/auto_test_2.py in C:\TestFiles\skrypty
        sys.exit(main(argv=args, module=None, testRunner=unittestpy.TeamcityTestRunner, buffer=not JB_DISABLE_BUFFERING))
    
      File "C:\Users\HP\AppData\Local\Programs\Python\Python39\lib\unittest\main.py", line 100, in __init__
        self.parseArgs(argv)
      File "C:\Users\HP\AppData\Local\Programs\Python\Python39\lib\unittest\main.py", line 147, in parseArgs
        self.createTests()
      File "C:\Users\HP\AppData\Local\Programs\Python\Python39\lib\unittest\main.py", line 158, in createTests
        self.test = self.testLoader.loadTestsFromNames(self.testNames,
      File "C:\Users\HP\AppData\Local\Programs\Python\Python39\lib\unittest\loader.py", line 220, in loadTestsFromNames
        suites = [self.loadTestsFromName(name, module) for name in names]
      File "C:\Users\HP\AppData\Local\Programs\Python\Python39\lib\unittest\loader.py", line 220, in 
        suites = [self.loadTestsFromName(name, module) for name in names]
      File "C:\Users\HP\AppData\Local\Programs\Python\Python39\lib\unittest\loader.py", line 154, in loadTestsFromName
        module = __import__(module_name)
      File "C:\TestFiles\skrypty\auto_test_2.py", line 1
        import unittest
    IndentationError: unexpected indent
    
    Process finished with exit code 1
    
    Empty suite
    
    Avatar Sebastian Cur
    1. Chyba jednak nie udało mi się załadować tekstu 😀

      import unittest
      from selenium import webdriver
      
      class MainTest(unittest.TestCase):
      
          def test_1(self):
              driver = webdriver.Chrome(executable_path=r"C:\TestFiles\chromedriver.exe")
              driver.get('https://demobank.jaktestowac.pl/logowanie_etap_1.html')
              title = driver.title
              print(title)
              assert 'Celowo wpisany zły tytuł strony' == title
              driver.quit()
      
      

      Rezultat:

      E:\Programy\IT\Demo_tests\venv\Scripts\python.exe E:/Programy/IT/Demo_tests/bla.py
      
      Process finished with exit code 0
      
      Avatar Mateusz Arak
      1. Hej,
        Czy otworzyła Ci się przeglądarka Chrome?
        Czy utworzyłeś nowy plik w tej lekcji, czy re-użyłeś tego z poprzedniej?

        Podejrzewam, ze może być tutaj problem z konfiguracją. Jeśli reużyłes – to PyCharm ma złą konfiguracje uruchomieniową dla tego pliku. Jak naprawić konfigurację opisujemy w kolejnych lekcjach: https://jaktestowac.pl/lesson/pt1-mk2-03-konfiguracje-uruchomieniowe-w-pycharm/

        Daj proszę znać o wynikach 🙂
        Pozdrawiam,

        Krzysiek Kijas Krzysiek Kijas
        1. No i szafa gra!
          Dziękuję bardzo za wyjaśnienie i podpowiedź.

          Faktycznie nie otwierała się przeglądarka, mało tego przy użyciu funkcji Run nie zauważyłem, że powinienem zrobić to dla unittest a robiłem dla .py

          Ruszam dalej 🙂

          A z innej beczki..
          W jaki sposób wrzucać kod aby był czytelny – a nie taki zlany w całość?

          Pozdrawiam 🙂

          Avatar Mateusz Arak
          1. Ciesze się, że mogłem pomóc 😀

            Jeśli chodzi o kod – to może być github, albo po prostu w komentarzu – my go później przeformatujemy 🙂

            Lepsze sposoby formatowania kodu mamy na liście zadań, ale jeszcze na tym nie pracowaliśmy.

            Pozdrawiam,

            Krzysiek Kijas Krzysiek Kijas
  3. Nie rozumiem, dlaczego linia:
    from selenium import webdriver
    jest u mne cała wyszarzona – tak jakby PyCharm nie rozpoznawał pakietu Selenium. To dziwne, bo przechodząc przez poprzedni kurs (pomyślnie), zainstalowałem ten pakiet.
    Cały test przebiega w porządku, rezultat jest taki, jak podaliście na screenie na końcu tej lekcji. Dziwne, nie rozumiem…

    Avatar Michał Orczyk
      1. Hej,
        Wyszarzona linia może oznaczać, że dane moduły lub pakiety nie są używane w dalszej części pliku. W poniższym przykładzie linia from selenium import webdriver powinna być wyszarzona:

        
        import unittest
        from selenium import webdriver
        
        
        class MainTests(unittest.TestCase):
            def test_demo_login(self):
                pass
        

        Spowodowane jest to faktem, iż nie używamy modułu webdriver w naszej klasie testowej (ani ogólnie w kodzie w tym pliku).

        Ale jeśli tylko wykorzystamy moduł webdriver, to linia z importem nabierze kolorów – tak jak w poniższym przykładzie:

        import unittest
        from selenium import webdriver
        
        
        class MainTests(unittest.TestCase):
            def test_demo_login(self):
                webdriver.Chrome(executable_path=r"C:\TestFiles\chromedriver.exe")
        

        Wyszarzanie importów przez IDE daje znam znać, że dany moduł/import nie jest używany w danym pliku. Pomaga to przy poprawie czytelności i sprzątaniu nieużywanych fragmentów kodu 🙂

        Pozdrawiam,

        Krzysiek Kijas Krzysiek Kijas
  4. Hej,
    Mam pewien problem. Przy próbie odpalenia testów z konfiguracją dla Unittest pojawił się błąd
    “‘Error running ‘rerun failed tests’:
    Can’t rerun tests since test IDs can’t be resolved. Try to delete run configuration, and create new one using right click”
    jeśli dobrze rozumiem, to po usunięciu konfiguracji Unittest, muszę dodać ją ponownie tylko, że nie wiem z jaką konfiguracją?

    Avatar Anna
  5. Cześć,
    Rozpocząłem przygodę z Pythonem i mam problem w tej lekcji z odpaleniem skryptu.
    Wygląda dosłownie tak jak na screenach jednak po uruchomieniu nie zwraca błędu:
    ”Process finished with exit code 0” ale również nic się nie dzieje, przeglądarka nie uruchamia się.

    Avatar Kamil Szpunar
    1. Hej,
      Jest duża szansa, że problem leży w konfiguracji uruchomieniowej w PyCharmie – ta potrafi czasem być problematyczna, szczególnie na samym początku 😉
      Ogólnie rzecz ujmując, pliki zawierające klasy testowe potrzebują innej konfiguracji, niż pliki zawierające proste skrypty.

      Rzuć proszę okiem na odp na forum – Testy uruchamiane z klasą nie działają a bez klasy wszystko jest ok (Podstawy Automatyzacji Cz2 Lekcja 1 Kodzimy – klasa, pierwszy test i uruchomienie), gdzie Przemek wskazuje rozwiązanie problemu. Jeśli to nie pomoże to nie krępuj się – pisz śmiało i razem podrążymy ten problem!
      Powodzenia!

      Krzysiek Kijas Krzysiek Kijas
    2. Jeszcze dodam od siebie, że nowa konfiguracja czasem nie chce działać do momentu usunięcia wszystkich istniejących i dodania jej ręcznie – w lekcji którą podał Krzysiek jest to opisane krok po kroku.
      Nie poddawaj się i walcz 😀 No i oczywiście czekamy na informację o twoich postępach!

      Przemek Barański Przemek Barański
  6. Jestem osobą, która dopiero zaczyna swoją przygodę z Pythonem. Zainstalowałam Pythona 2.7. Jeśli używam kodu zamieszczonego w tej lekcji ale bez:
    “class MainTests(unittest.TestCase):
    def test_demo_login(self):”
    to wszystko działa poprawnie. Kiedy chcę wykorzystać kod z lekcji przeglądarka otwiera się ale nie dzieje się już nic więcej.
    Co może być przyczyną?
    Z góry dziękuję za podpowiedź

    Avatar Alex
  7. Fajnie by było, jakby fragment kodu podany jako przykład z def i self, tj.
    ‘def test_main_page(self):
    pass’,

    był tej samej treści co cały kod w przykładzie niżej (tam jest już wpisane:
    ‘def test_demo_login(self):
    pass’.

    Jest to trochę mylące 🙂

    Avatar Urszula Surmacewicz

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *