Twój pierwszy Screenshot w Selenium WebDriver

Projekt testowy

Na początku zacznijmy od stworzenia nowego projektu o nazwie BasicScreenshotTests wraz z własnym venv, w którym będziemy eksperymentowali ze zrzutami ekranu. Nasz nowy projekt umieśćmy w katalogu Projects, tak aby struktura folderów wyglądała w następujący sposób:

C:
+-- Projects
|   +-- BasicScreenshotTests
|      +-- venv
|         +-- ...
|      +-- ...
|   ...
...
TIP: Generalnie aby stworzyć nowy projekt wystarczy kliknąć w górnym menu PyCharma File -> New Project… i w katalogu Projects utworzyć projekt z sugerowaną nazwą i domyślnym ustawieniem Project Interpreter.
W razie problemów tworzenie projektu za pomocą IDE PyCharm omówiliśmy w lekcji Tworzymy projekt, natomiast tworzenie środowiska wirtualnego – w sekcji Python Virtual Environment.

Klasa testowa

Następnie przygotujmy sobie:

  1. Klasę testową o nazwie BasicScreenshotTests w pliku basic_screenshot_tests.py.
  2. Następnie dodamy metody setUp oraz tearDown, w których odpowiednio przygotujemy sobie moduł webdriver. Będzie on bazował na naszym chromedriver.exe (dla przypomnienia – Drugi kod – korzystamy z modułu WebDriver).
  3. Doinstalujmy brakujący pakiet selenium (dla przypomnienia – Pierwszy kod – pojawia się Selenium).
  4. Napiszmy prosty test, który będzie odwiedzał stronę https://antoogle.testoneo.com/ oraz sparawdzał jej tytuł.

Całość mogłaby wyglądać w następujący sposób:

import unittest
from selenium import webdriver


class BasicScreenshotTests(unittest.TestCase):

   def setUp(self):
      self.base_url = 'https://antoogle.testoneo.com/'
      self.driver = webdriver.Chrome(executable_path=r"C:\TestFiles\chromedriver.exe")

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

   def test_open_antoogle(self):
      self.driver.get(self.base_url)
      self.assertEqual('The Antoogle Search Page', self.driver.title, f'Expected title differ from actual for page url: {self.base_url}')

Metoda do zrzutów ekranu

Teraz poznamy metodę odpowiedzialną za tworzenie screenshotów driver.get_screenshot(). Użyjemy ją w naszym kodzie zaraz przed linią z asercją w taki sposób:

self.driver.get_screenshot_as_file("screenshot.png")

Czyż nie wygląda banalnie? Możemy także podejrzeć jej dokumentację.
Mamy trzy sposoby:

  1. Poprzez naciśnięcie skrótu szybkiego podglądu dokumentacji Ctrl + Q. Przypominamy, że niestety twórcy PyCharama zmienili sposób działania tego podglądu (niestety na gorsze) i często trzeba uciekać się do innych sposobów aby podglądnąć pełną dokumentację
  2. Przejście bezpośrednio do biblioteki selenium gdzie istnieje implementacja tej metody poprzez przytrzymanie klawisza Ctrl i naciśnięcie lewym przyciskiem myszy na naszą metodę
  3. Udając się do oficjalnej dokumentacji dostępnej pod tym adresem

Z dwóch ostatnich sposobów możemy odnaleźć przykład użycia naszej metody – najszybszym wydaje się przejście do jej implementacji (sposób 2) – w wyniku, którego możemy zobaczyć oryginalną dokumentację do kodu tej metody:

def get_screenshot_as_file(self, filename):
   """
   Saves a screenshot of the current window to a PNG image file. Returns
      False if there is any IOError, else returns True. Use full paths in
      your filename.

   :Args:
    - filename: The full path you wish to save your screenshot to. This
      should end with a `.png` extension.

   :Usage:
       driver.get_screenshot_as_file('/Screenshots/foo.png')
   """

Widzimy, że metoda ta przyjmuje jeden argument, którym jest ścieżka z nazwą pliku, pod którym zostanie zapisany nasz zrzut ekranu. Jeśli umieścimy tam tylko nazwę pliku, to obraz zostanie zapisany w katalogu gdzie znajduje się plik z naszym testem.

Przykładowo, w naszym wypadku ścieżka C:\Pojects\BasicScreenshotTests\screenshot.png będzie równoznaczna z screenshot.png – w obu przypadkach obraz zostanie zapisany w pliku o nazwie screenshot.png w katalogu C:\Pojects\BasicScreenshotTests\ gdyż tam znajdują się nasze skrypty z testami.

Użycie metody do screenshotów

Tak wygląda nasz udoskonalony test z zastosowaniem:
self.driver.get_screenshot_as_file("screenshot.png"):

import unittest
from selenium import webdriver


class BasicScreenshotTests(unittest.TestCase):

   def setUp(self):
      self.base_url = 'https://antoogle.testoneo.com/'
      self.driver = webdriver.Chrome(executable_path=r"C:\TestFiles\chromedriver.exe")

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

   def test_open_antoogle(self):
      self.driver.get(self.base_url)
      self.driver.get_screenshot_as_file("screenshot.png")
      self.assertEqual('The Antoogle Search Page', self.driver.title, f'Expected title differ from actual for page url: {self.base_url}')

Co się stanie jeśli go uruchomimy? Poza tym, że przeglądarka otworzy się jedynie na ułamek sekundy, to w naszym katalogu projektowym pojawi się plik o nazwie screenshot.png, na którym ujrzymy testowaną stronę internetową. W PyCharmie powinieneś zobaczyć ten plik w lewym panelu Project zaraz pod plikiem z naszą klasą.

Otwieramy otrzymany plik screenshot.png bezpośrednio w PyCharmie co oznacza, że bez problemu możemy w naszym IDE podglądać pliki graficzne. Nawet znajdziemy u góry zakładki z podglądem podstawowych opcji do zmiany sposobu wyświetlania obrazka.

Podsumowanie

Takim oto sposobem mamy nasz pierwszy automatyczny zrzut ekranu 😉 Teraz możemy zacząć go ulepszać.

Umiemy już tworzyć screenshoty, ale sposób ich robienia znacznie odbiega od tego co chcieliśmy osiągnąć. Zrzut ekranu będzie robiony zawsze a my chcielibyśmy aby był tworzony jedynie w momencie kiedy nasz test zakończy się niepowodzeniem. Jak to osiągnąć?

Może tutaj zastosować wcześniej poznaną konstrukcję try… except?

14 komentarzy

  1. Witam.
    tez mi to nie działa na pycharmie: 2020.3. Nie uruchamia okno przeglądarki dostaje exit code 0 i brak pliku ze screenshotem

    Natomiast działa mi rozwiązanie:

    driver = webdriver.Chrome(executable_path=r'H:\chromedriver\chromedriver.exe')
    driver.get('https://antoogle.testoneo.com/')
    title = driver.title
    driver.save_screenshot('screenshot.png')
    

    Pozdrawiam
    Arek

    1. Hej,
      exit code 0 oznacza, że nie było błędu (co nie znaczy, że poszło tak jak chcieliśmy).

      Jak wyglądał Twój cały kod?

      Czy skrypt (który zwrócił 0) utworzyłeś jako nowy plik? – Jest szansa, że PyCharm użył złej konfiguracji uruchomieniowej. Testy wymagają konfiguracji z Test Runnerem, a bez tego próba uruchomienia kończy się wpisem exit code 0 Wiecej o tym problemie pisaliśmy w lekcji https://jaktestowac.pl/lesson/pt1-mk2-03-konfiguracje-uruchomieniowe-w-pycharm/

      Krzysiek Kijas Krzysiek Kijas
      1. Dzień dobry.
        Dziękuję za odpowiedź. Po wielu nieudanych próbach skopiowałem cały kod z Waszego przykładu (łącznie z sekcją import) i również nie zadziałało..
        w Venv istnieje Selenium, a webdriver z wklejonym w poprzednim komentarzu kodem działa poprawnie. Nie wiem gdzie szukać problemu.
        Pozdrawiam
        Arek

        Avatar Arek
        1. Hej,
          To jest duża szanse, ze to wina konfiguracji.
          Podeślij mi proszę screena z aktualnej konfiguracji uruchomieniowej (np w takiej postaci: ). Aby podejrzeć konfiguracje kliknij w górnym menu na Run a następnie Edit Configurations… (dwa słowa więcej znajdziesz w lekcji https://jaktestowac.pl/lesson/pt1-mk2-03-konfiguracje-uruchomieniowe-w-pycharm/#Standardowa_konfiguracja_uruchomieniowa_dla_pliku_autotest2 ).

          Konfiguracje możesz nam wysłać na maila kontaktowego 🙂

          Krzysiek Kijas Krzysiek Kijas
    1. Zazwyczaj przy tworzeniu projektu wskazane jest stworzenie dla niego własnego i nowego venv, chociaż jeśli np. chcesz reuzyć istniejący venv, to również możesz go wskazać 🙂 Tu należy jednakże uważać gdy więcej niż jeden projekt korzysta z danego venv – mogą pojawić się konflikty, niezgodności paczek i trudności w tworzeniu requirements.txt 😉

      PS. To nie spam a normalne pytanie 😉

      Krzysiek Kijas Krzysiek Kijas
  2. ok znalazlem przyczyne przy tworzeniu projektu zaznaczylem new environment using Virtualvenv nie wiem czy tak mialo byc ? odnosnie ‘ BasicScreenshotTests wraz z własnym venv’ a moj venv jest czysty i to chyba generowalo ten blad.

    Avatar Dawid Kowalczyk
    1. Tak, w tym przypadku tworzone jest nowe, czyste środowisko Pythona w katalogu (domyślnie) venv w projekcie. W takim przypadku wystarczy tylko doinstalować brakujące pakiety (albo przez opcje projektu i interpretra albo bezpośrednio ze skryptów). Później mając środowisko tylko z wymaganymi paczkami można w prosty sposób przenosić je w inne miejsca – natomiast informacje o pakietach – za pomocą pliku requirements.txt 😉

      Krzysiek Kijas Krzysiek Kijas
  3. zmienilem konfiguracje i dostaje
    Traceback (most recent call last):
    File “C:/Projects/BasicScreenshotTests/basic_screenshot_tests.py”, line 2, in
    from selenium import webdriver
    ModuleNotFoundError: No module named ‘selenium’

    a kod jest ten sam, czy to moze byc problem z importem selenium?

    Avatar Dawid Kowalczyk
    1. Tutaj wygląda na to, że konfiguracja nie korzysta z venv, który miał zainstalowaną paczkę selenium a np. z głównego Pythona systemowego. Sprawdź proszę w konfiguracji – tam jest opcja Python Interpreter – zobacz czy jest ustawiona na Pythona z venv czy systemowego 🙂

      Krzysiek Kijas Krzysiek Kijas
        1. Hej,
          Tak, posiadanie venv w projekcie jest dobrą praktyką – wtedy mamy w pełni niezależne środowisko Pythona, wraz z zestawem paczek w odpowiednich wersjach 😉 To jest szczególnie pomocne, gdy mamy wiele różnych projektów, z których każdy wymaga swojego zestawy bibliotek.
          Bez venv wszystko będzie działać, nawet przez długi czas, ale prędzej czy później pojawią się problemy 😀

          Krzysiek Kijas Krzysiek Kijas
  4. Witam panowie nie wiem czemu ale mi sie nie uruchamia okno przegladarki dostaje exit code 0 brak pliku ze screenshotem. Czy to moze byc spowodowane venv?

    
    import unittest
    from selenium import webdriver
    
    
    class BasicScreenshotTests(unittest.TestCase):
    
        def setUp(self) :
            self.base_url = 'https://antoogle.testoneo.com/'
            self.driver = webdriver.Chrome(executable_path=r"C:\TestFiles\chromedriver.exe")
    
        def tearDown(self) :
            self.driver.quit()
    
        def test_open_antoogle(self) :
            self.driver.get(self.base_url)
            self.driver.get_screenshot_as_file("screenshot.png")
            self.assertEqual('The Antoogle Search Page', self.driver.title,
                             f'Expected title differ from actual for page url: {self.base_url}')
    
    
    Avatar Dawid Kowalczyk
    1. Hej,
      Tu bardziej bym szukał przyczyny w sposobie uruchamiania i konfiguracji – wynik wskazuje na to, ten skrypt uruchamiany jest jak zwykły skrypt a nie klasa testowa za pomocą runnera PyCharma.

      Krzysiek Kijas Krzysiek Kijas

Dodaj komentarz

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