1. Metody testowania skryptów
Witaj na naszym wykładzie poświęconym ulubionemu procesowi wszystkich programistów — debugowaniu i testowaniu! Jeśli już opanowałeś tworzenie niesamowitego bota z Selenium, czas dowiedzieć się, jak zmienić go z narwanego robota w posłusznego wykonawcę, który nie tylko działa, ale robi to stabilnie. W końcu nie chcesz, aby twój bot w najważniejszym momencie nagle postanowił „odpocząć”.
Zacznijmy od omówienia różnych metod testowania twoich skryptów. Testowanie — to jak obowiązkowa wizyta u lekarza: nikt nie chce, ale bez tego ani rusz. Nawet najbardziej genialny skrypt wymaga sprawdzenia swojej odporności i niezawodności. Dobra wiadomość jest taka, że Python ma mnóstwo narzędzi, które ci w tym pomogą.
Unit testy
Wszystko zaczyna się od unit testów. Są one jak małe szwajcarskie zegarki sprawdzające każdą przekładnię
twojego mechanizmu. W Pythonie biblioteka unittest
jest standardem de facto do pisania unit testów.
Główna idea polega na testowaniu pojedynczych „unitów” lub części twojego kodu w izolacji.
import unittest
from my_selenium_script import my_function
class TestMyFunction(unittest.TestCase):
def test_success_case(self):
result = my_function("oczekiwane wejście")
self.assertEqual(result, "oczekiwany wynik")
unittest.main()
Ten prosty przykład ilustruje, jak można sprawdzać poszczególne funkcje swojego kodu. Oczywiście w praktyce będziesz sprawdzać nie tylko sukces, ale także różne przypadki brzegowe i nieprawidłowe dane wejściowe.
Testy integracyjne
Kiedy już masz podstawy do zaufania każdemu z „unitów”, czas sprawdzić ich interakcję między sobą. Testy integracyjne, jak idealna randka, pokazują, jak poszczególne komponenty działają razem. Możesz używać tych samych bibliotek, ale podejść do testowania z innej strony.
class TestIntegration(unittest.TestCase):
def test_full_workflow(self):
# Wyobraź sobie, że każdy krok to wywołanie funkcji twojego algorytmu
open_page()
fill_form()
submit_form()
self.assertTrue(check_results())
Testy integracyjne mogą być bardziej złożone i zajmować więcej czasu, ale dają pewność, że cały system działa jako całość.
2. Debugowanie i naprawianie błędów
Teraz, gdy omówiliśmy testowanie, zanurzmy się w bardziej intrygującą część — debugowanie. Debugowanie to, kiedy twój bot postanawia zaszaleć i zacząć improwizować, a ty próbujesz przywrócić go do planu.
Narzędzia debugowania
Świetnym narzędziem do debugowania w Pythonie jest pdb
. Pozwala zatrzymać wykonanie skryptu i
przeanalizować jego stan krok po kroku. Spójrzmy na przykład:
import pdb
def some_function(value):
pdb.set_trace() # Tutaj wykonanie się zatrzyma
result = value + 1
return result
some_function(3)
Po uruchomieniu tego kodu wejdziesz w interaktywną środowisko, gdzie możesz przechodzić kod linia po linii, sprawdzać wartości zmiennych, modyfikować je i nawet kontynuować wykonanie programu krok po kroku. To mocno ułatwia życie, kiedy twój skrypt wydaje się robić coś dziwnego.
Wizualizacja stanu strony
Do wizualnego debugowania przydaje się zapisywanie zrzutów ekranu strony na każdym etapie wykonywania skryptu. To pomoże zobaczyć, jakie elementy są widoczne na ekranie i jak wygląda strona w momencie błędu.
driver.save_screenshot("page_state.png")
Strategie wyszukiwania i naprawiania błędów
Niestety, żaden debugger nie pokaże ci, gdzie w kodzie popełniono fundamentalny błąd w logice. Tutaj z pomocą przychodzą strategie:
- Logowanie: Dodawanie logów wszędzie. Jak powiedział ktoś mądry, „jeśli nie wiesz, co się
dzieje z kodem, to znaczy, że masz za mało logów”. Korzystanie z biblioteki
logging
pomaga nie zaśmiecać kodu funkcjamiprint()
i daje większą kontrolę. - Odczytywanie kodu na głos: Czasami problemy łatwiej rozwiązać, jeśli sformułujesz, co robi kod. Brzmi zabawnie, ale to działa!
- Podział na moduły: Wyraźnie podziel części kodu na moduły lub funkcje. To pozwoli łatwiej określić, gdzie dokładnie wystąpił problem.
3. Analiza twoich skryptów Selenium
Aby stworzyć niezawodny skrypt, ważne jest, aby przetestować jego działanie w różnych scenariuszach. Oto kilka przykładów takich scenariuszy:
Brak elementów na stronie
Podczas debugowania ważne jest, aby upewnić się, że wszystkie potrzebne elementy są obecne na stronie i
dostępne do interakcji.
Użyj metody find_elements()
i sprawdź długość zwróconej listy, aby uniknąć błędów typu
NoSuchElementException
.
elements = driver.find_elements_by_class_name("class_name")
if len(elements) == 0:
logging.warning("Elementy nie znalezione")
else:
logging.info("Elementy znalezione pomyślnie")
Nieprzewidziane stany strony
Na przykład strony z różnymi formami ładowania lub różnymi elementami, które pojawiają się w zależności od warunków. Skrypt powinien być przygotowany do obsługi takich sytuacji.
try:
special_offer = driver.find_element(By.ID, "special_offer")
logging.info("Znaleziono ofertę specjalną i wykonujemy działania")
except NoSuchElementException:
logging.info("Nie znaleziono oferty specjalnej, kontynuujemy dalej")
Różne elementy na stronie
Podczas testowania warto uwzględnić fakt, że na tej samej stronie elementy mogą się zmieniać (np. różne banery, bloki reklamowe itd.). Testuj skrypt z uwzględnieniem różnych stanów strony.
Testowanie w różnych przeglądarkach
Różne przeglądarki mogą różnie interpretować strony, dlatego w celu zapewnienia stabilności dobrze jest testować skrypt na kilku przeglądarkach (np. Chrome, Firefox, Edge). Selenium pozwala uruchamiać testy na różnych przeglądarkach za pomocą różnych driverów.
from selenium import webdriver
# Uruchomienie w Chrome
driver = webdriver.Chrome()
# Uruchomienie w Firefox
driver = webdriver.Firefox()
# Uruchomienie w Edge
driver = webdriver.Edge()
4. Automatyzacja testowania skryptu
Pisanie testów za pomocą unittest
Użyj biblioteki unittest
, aby automatycznie uruchamiać testy dla różnych części twojego skryptu.
To pozwoli ci regularnie sprawdzać działanie każdego elementu.
import unittest
from selenium import webdriver
class SeleniumTest(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome()
self.driver.get("https://example.com")
def test_element_presence(self):
driver = self.driver
element = driver.find_element_by_id("submit_button")
self.assertIsNotNone(element, "Element nie znaleziony na stronie")
def tearDown(self):
self.driver.quit()
unittest.main()
Tworzenie zestawu testów z parametrami
Stwórz zestawy testów do sprawdzania różnych kombinacji elementów i scenariuszy. Na przykład można testować strony z różnymi parametrami, takimi jak różne formy danych w formularzu.
Sprawdzanie stabilności i wydajności
- Sprawdzaj stabilność skryptu na dużych ilościach danych: Upewnij się, że skrypt potrafi obsłużyć duże ilości danych i działać przez długi czas.
- Uruchamiaj regularne testowanie: Regularnie uruchamiaj testy, aby monitorować stabilność skryptu, zwłaszcza jeśli strona, z którą pracujesz, często się zmienia.
- Ocena wydajności: Unikaj długich oczekiwań i wolnych elementów. Użyj timerów do oceny czasu wykonywania każdego kroku i optymalizuj je w razie potrzeby.
GO TO FULL VERSION