Powrót do: Podstawy Testów Automatycznych w Selenium i Python cz. 5 – Profesjonalna konfiguracja projektu
Wydzielenie zduplikowanego kodu a dziedziczenie
Przećwiczmy sobie praktycznie na prostym przykładzie techniki, które zastosujemy w kodzie naszych testów.
Kod do ćwiczeń
Wyobraźmy sobie prosty kod, który powstał po wielu latach żmudnej pracy nad modelem komunikacji urządzeń:
class Device(): def __init__(self, dev_name): self.name = dev_name def turn_on(self): print(f"Device {self.name} turned on") def turn_off(self): print(f"Device {self.name} turned off") class MobilePhone(Device): def game_mode(self): print(f"Device {self.name} set to game mode") def exchange_data(self): print(f"Device {self.name} exchanging data") def ring(self): print(f"Device {self.name} ringing") def update(self): print(f"Device {self.name} is being updated") class SmartWatch(Device): def update(self): print(f"Device {self.name} is being updated") def measure_heart_rate(self): print(f"Device {self.name} measuring_heart_rate") def ring(self): print(f"Device {self.name} ringing") def exchange_data(self): print(f"Device {self.name} exchanging data") print(f"Device {self.name} checking connection with mobile phone")
Kod wydaje się nie być skomplikowany. Użyjmy go. Stwórz nowy plik w scratches (Otwieranie widoku Scratches i tworzenie pliku Scratches) i wpisz powyższy kod.
Następnie, poniżej kodu klas, dodajmy proste użycie urządzeń:
# initialising and using devices x_phone = MobilePhone("xPhone") x_watch = SmartWatch("xWatch") x_phone.turn_on() x_phone.game_mode() x_phone.exchange_data() x_phone.ring() x_phone.update() x_phone.turn_off() x_watch.turn_on() x_watch.update() x_watch.measure_heart_rate() x_watch.ring() x_watch.exchange_data() x_watch.turn_off()
Wynik jaki otrzymamy na konsolę to:
Device xPhone turned on Device xPhone set to game mode Device xPhone exchanging data Device xPhone ringing Device xPhone is being updated Device xPhone turned off Device xWatch turned on Device xWatch is being updated Device xWatch measuring_heart_rate Device xWatch ringing Device xWatch exchanging data Device xWatch checking connection with mobile phone Device xWatch turned off
Czyli kod działa, nie mniej my chcemy go trochę usprawnić. Popatrz na metodę ring()
. Jest ona identyczna w obu klasach MobilePhone
i SmartWatch
. Zrefaktorujmy więc tę duplikację!
Wyciąganie wspólnej metody do klasy bazowej
Wydzielimy metodę do klasy bazowej czyli użyjemy mechanizmu dziedziczenia. Po takim zabiegu wszystkie dziedziczące klasy będą mogły korzystać z metody zaimplementowanej w klasie bazowej 🙂
Ale jak wyciągnąć tę metodę? Jeśli są one identyczne w różnych klasach to wystarczy, że po prostu wytniemy je z obu klas i wkleimy w klasę bazową. Na celownik wzięliśmy metodę ring()
i:
- Wycinamy ją z obu klas
- Wklejamy ją do klasy bazowej
- Uruchamiamy kod i sprawdzamy czy otrzymaliśmy wynik taki sam jak poprzednio – oznacza to, że nasz refaktor się powiódł 😀
Tak będzie wyglądał kod klas po refaktorze:
class Device(): def __init__(self, dev_name): self.name = dev_name def turn_on(self): print(f"Device {self.name} turned on") def turn_off(self): print(f"Device {self.name} turned off") def ring(self): print(f"Device {self.name} ringing") class MobilePhone(Device): def game_mode(self): print(f"Device {self.name} set to game mode") def exchange_data(self): print(f"Device {self.name} exchanging data") def update(self): print(f"Device {self.name} is being updated") class SmartWatch(Device): def update(self): print(f"Device {self.name} is being updated") def measure_heart_rate(self): print(f"Device {self.name} measuring_heart_rate") def exchange_data(self): print(f"Device {self.name} exchanging data") print(f"Device {self.name} checking connection with mobile phone")
Jest nieźle, pozbyliśmy się zduplikowanego kodu i wszystko działa jak poprzednio. Dzięki dziedziczeniu możemy bez problemu dalej wywoływać metodę ring()
na obiektach klasy MobilePhone
czy SmartWatch
.
Zmiana wymagań
Teraz dodamy pewne utrudnienie:
Niestety okazało się, że klasa Device
pod żadnym pozorem nie może być zmieniana, gdyż jest to zewnętrzna biblioteka i podlega utrzymaniu i modyfikacji przez inne firmy. Oznacza to, że nie możemy sobie tam tak wklejać metod…
Załóżmy też, że wcześniejsze działania czyli wyciągnięcie metody ring()
zrobiliśmy wcześniej jako właściciele klasy Device
. Niestety teraz sytuacja się zmieniła i już nie możemy tak działać.
Co zrobić?
Cześć
Małe literówki do poprawy jest Deivce powinno być Device 🙂 Linie 5, 13, 17, `19 ,25 ,26
Pozdrawiam
Mateusz
Hej,
Faktycznie 😀 Jedna literówka, a później CTRL+C/V… 😀
Poprawione – dzięki za wyłapanie i zgłoszenie 🙂