Skrypt testowy: Dodanie produktu do koszyka (Page Object Pattern)

 

W tym materiale przedstawię test automatyczny, którego celem będzie przetestowanie dodawania konkretnego produktu do koszyka zakupowego a wszystko odbędzie się z wykorzystaniem wzorca Page Object Pattern.

Page Object Pattern to podstawowy wzorzec projektowy wykorzystywany do tworzenia testów automatycznych. Krótko mówiąc, ten sposób pisania testów polega na tym, że każdą ze stron internetowych przedstawiamy jako osobą klasę tzw. Page Object. W każdej z klas tworzyły metody, deklarujemy WebElementy które zawiera dana strona www, co pozwala nam utrzymać dużo większy porządek i ład w naszym kodzie a same testy stają się bardziej czytelne i zrozumie. Kolejną, dużą zaletą takiego podejścia do pisania testów jest to, że unikamy redundancji kodu. Nasze testy stają się łatwiejsze w utrzymaniu, gdyż w przypadku, gdy na jakiejś stronie zmieni się np. ścieżka do pewnego WebElementu – to zmianę przeprowadzamy tylko w danej klasie, która reprezentuje tą konkretna stronę a nie we wszystkich naszych testach, gdzie używamy zmienionego elementu.

 

Na początku przedstawię pełny kod, który będzie składał się z trzech klas: HomePage.class, ProductDetails.class oraz addBasketTest.class

Jak już wspomniałem, cały kod będzie testował jedną funkcjonalność: dodawanie konkretnego produktu do koszyka i sprawdzenie czy cała operacja przebiegła pomyślnie.

Nasz test będzie składać się z następujących kroków:

  1. Wchodzimy na stronę: http://www.sklep-graal.pl/
  2. Klikamy  z menu pozycje „Gry planszowe”
  3. Klikamy z podmenu Gier planszowych pozycje „Gry przygodowe”
  4. Z wyświetlonej listy gier klikamy w grę o tytule „The Walking Dead”
  5. Na ekranie szczegółów wybranego produktu, porównujemy tytuł grycenęilośćoraz status – z poprawnymi danymi produktu
  6. Jeśli dane gry zgadzają się z poprawnym produktem (który jest wskazany przed rozpoczęciem testów) wówczas klikamy na przycisk „Do koszyka
  7. Sprawdzamy czy po kliknięciu przycisku został wyświetlony komunikat potwierdzający poprawną operacje dodania produktu do koszyka (treść poprawnego komunikatu została podana na początku testu)

HomePage.class

 

package pages;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

        public class HomePage {

            private WebDriver driver;

            public HomePage(WebDriver driver)
            {
                this.driver = driver;
            }

            private By games = By.linkText("Gry planszowe");
            private By categoryGame = By.linkText("Przygodowe");
            private By titleGame = By.linkText("The Walking Dead");


            public void clickGames()
            {
                driver.findElement(games).click();
            }

            public void clickCategoryGame()
            {
                driver.findElement(categoryGame).click();
            }

            public void clickTitleGame()
            {
                driver.findElement(titleGame).click();
            }
        }

 

 

 

Powyższa klasa  reprezentuje główną stronę sklepu: http://www.sklep-graal.pl/

 

Listing 1.0

 

 

Listing 1.0 przedstawia reprezentowana przez klasę HomePage –  stronę www.

 

 

Dokładne omówienie klasy HomePage:

Deklarujemy prywatny obiekt driver oraz tworzymy konstruktor klasy HomePage

 

 

Następnie lokalizujemy niezbędne do przeprowadzania testu WebElementy na tej stronie. Potrzebujemy zlokalizować pozycje w Menu: „Gry planszowe” oraz podmenu „Przygodowe” a także tytuł interesującej nas gry: „The Walking Dead„. Warto zwrócić uwagę, że WebElementy mają przedrostek private co oznacza, że są prywatne, czyli będą widoczne tylko w tej klasie i w żadnej innej. My jednak będziemy chcieli korzystać z tych elementów w innych klasach wiec musimy utworzyć metody, które będą działać w oparciu o te WebElementy i będą klasami publicznymi, czyli będą widoczne również dla innych klas naszego projektu.

 

 

Tutaj tworzymy wspominane wcześniej metody publiczne, które korzystają z wcześniej  zadeklarowanych WebElementów. Metody te również wykonują określone akcje, w naszym przypadku są to operacje kliknięcia  we wskazany element na stronie. Warto pamiętać, żeby tworzyć „samo opisujące” się nazwy metod, gdyż to znacznie ułatwi nam późniejsze zrozumienie kodu.

 

 

Kolejna omawiana klasa to ProductDetails – czyli ekran szczegółów wybranego produktu.

 

package pages;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;


        public class ProductDetails {
            private WebDriver driver;

            public ProductDetails(WebDriver driver) {
                this.driver = driver;
            }

            private  By status = By.xpath(".//*[@id='box_productfull']/div[3]/table/tbody/tr[1]/td[2]/dl/dd[1]");

            private By heading = By.xpath(".//*[@id='box_productfull']/div[2]/h1");

            private By price = By.xpath(".//*[@id='box_productfull']/div[3]/table/tbody/tr[2]/td/div[1]/em");

            private By buttonBasket = By.cssSelector("button[type='submit'][class='addtobasket']");

            private By quantity = By.cssSelector("input[name='quantity']");

            private By statement = By.cssSelector("div.container p");


            public String getStatus()
            {
                String strStatus = driver.findElement(status).getText();
                return strStatus;
            }

            public String getHeading()
            {
                String strHeading = driver.findElement(heading).getText();
                return strHeading;
            }

            public String getPrice()
            {
                String strPrice= driver.findElement(price).getText();
                return strPrice;
            }


            public String getQuantity()
            {
                String strQuantity = driver.findElement(quantity).getAttribute("Value");
                return strQuantity;
            }

            public String getStatement()
            {
                String strStatement = driver.findElement(statement).getText();
                return strStatement;
            }

            public void clickButtonBasket()
            {
                driver.findElement(buttonBasket).click();
            }
            
        }

 

 

Listing 1.1

 

 

Listing 1.1 przedstawia stronę ze szczegółami wybranego produktu.

 

Deklarujemy prywatny obiekt driver oraz tworzymy konstruktor klasy ProductDetails

 

Analogicznie do wcześniej opisanej klasy HomePage: lokalizujemy niezbędne do przeprowadzania testu WebElementy na tej stronie. Tym razem potrzebujemy zlokalizować takie elementy jak:  status produktu (czy dostępny),  nagłówek (nazwa gry), cenęilość (sztuk produktu), przycisk „Do koszyka”. oraz komunikat (który potwierdza poprawne wykonanie operacji dodawani do koszyka)

 

 

Poniżej tworzymy publiczne metody, które korzystając z wcześniej zlokalizowanych WebElementów, będą wykonywać na nich rożne akcje. Wcześniej już poznaliśmy akcje realizująca klikanie w dany element. Teraz widzimy jeszcze metodę pobierająca i zwracając wartość ze wskazanego elementu – np. getStatus(). Dzięki metodom getStatus()getHeading(), getPrice()getQuantity() pobieramy i zwracamy wartość ze wskazanych WebElementów – robimy to po to, aby później porównać te dane z poprawnymi danymi produktu –  w przypadku zgodności kliknąć w przycisk dodający produkt do koszyka (przypominam test polega na dodaniu KONKRETNEGO, wskazanego produktu do koszyka)

Metoda getStatement() – pobiera i zwraca wartość komunikatu jaki pojawia się po kliknięciu przycisku „Do koszyka”.

 

 

Klasa addBasketTest to miejsce naszego testu , który będziemy wykonywać w oparciu o  wcześniej utworzone klasy HomePage oraz ProductDetails.

package testPackage;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import pages.HomePage;
import pages.ProductDetails;

import java.util.concurrent.TimeUnit;


        public class addBasketTest {

            WebDriver driver;
            HomePage hp;
            ProductDetails pd;

            //Dane właściwego produktu
            private  String rightHeading ="The Walking Dead";
            String rightPrice = "154,90 zł";
            String rightQuantity = "1";
            String rightStatus = "dostępna";
            String rightStatement ="Produkt dodany do koszyka.";


            @BeforeTest

            public void uruchom()
            {
                System.setProperty("webdriver.chrome.driver", "C:\\Users\\Tomasz\\Documents\\seleniumChromeDriver\\chromedriver.exe");
                driver = new ChromeDriver();
                driver.get("http://www.sklep-graal.pl");
                driver.manage().window().maximize();
                driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
            }


            @AfterTest

            public void shoutDown()
            {
                driver.quit();
            }


            @Test(priority = 0)
            public void addToBasketTest()
            {
                hp = new HomePage(driver);
                pd = new ProductDetails(driver);

                hp.clickgames();
                hp.clickCategoryGame();
                hp.clickTitleGame();

                Assert.assertEquals(pd.getStatus(),rightStatus);
                Assert.assertEquals(pd.getPrice(),rightPrice);
                Assert.assertEquals(pd.getHeading(),rightHeading);
                Assert.assertEquals(pd.getQuantity(), rightQuantity);

                pd.clickButtonBasket();

                Assert.assertEquals(pd.getStatement(),rightStatement);

            }

        }

 

 

Deklarujemy obiekt driver oraz obiekty utworzonej wcześniej klasy HomePage oraz ProductDetails.

 

W tym miejscu podajemy poprawne dane produktu jaki zamierzamy dodać do koszyka.

 

Następnie za pomocą adnotacji @BeforeTest (udostępnionej za pomocą frameworka TestNG) tworzymy kod, który będzie wykonywał się przed wszystkim  testami. Tworzymy metodę uruchom()w której ustawiamy property dla ChromeDrivera, inicjalizujemy driver przeglądarki Chrome, odpalamy stronę www.sklep-graal.pl oraz wykonujemy akcję maksymalizacji okna przeglądarki a także ustawiamy implicitlyWait na 10 sekund.

 

 

Kolejny fragment kodu to adnotacja @AfterTest – jak sama nazwa wskazuje, tutaj umieszczamy kod który będzie wykonywany po wszystkich testach. Zwykle w tym miejscu np. usuwamy jakieś artefakty, które zostały utworzone na potrzeby testów, bądź usuwamy pliki cookies czy jak w naszym przypadku – po prostu zamykamy okno przeglądarki.

 

 

W końcu docieramy do kodu głównego testu. Jak widzimy jest on poprzedzony adnotacją @Testoraz instrukcją priority. Priorytet = 0 oznacza, ze test ma odbyć się jako pierwszy. Mogliśmy sobie pominąć tą prioretyzację, ponieważ jak widać wykonujemy tylko jeden test wiec nie ma potrzeby jawnie wskazywać, który z testów powinien być odpalony jako pierwszy. Niemniej jednak, kiedy mamy do wykonania kilka testów ta linijka jest bardzo pomocna i jawnie porządkuje kolejność wykonywania testów.

 

 

Następnie  tworzymy  obiekty dwóch klas które stworzymy wcześniej: HomePage oraz ProductDetails  i przekazujemy obiekt driver jako parametr konstruktora.

 

 

Kolejne trzy linie kodu to wywołania metod klasy HomePage. Odpowiadają one za klikanie we wskazane elementy na stronie – w naszym przypadku pozycje w menu oraz tytuł gry.

 

 

Dalsze instrukcje to tzw. Asercje – czyli funkcje sprawdzające/porównujące poszczególne warunki. Asercje wykorzystywane poniżej dostarcza framework TestNG. W naszym przypadku asercje porównują status, cenę, nagłówek oraz ilość (wszystkie te dane pobieramy, napisanymi metodami ze strony ProductDetails)  z danymi poprawnymi, które mamy podane na początku klasy w której aktualnie się znajdujemy.  Jeśli asercja Assert.assertEquals() okaże się prawdą, czyli podane dwie wartości się zgadzają (są takie same) wówczas kompilator przechodzi do kolejnej linii. Jeśli zaś asercja jest nieprawdziwa (podane wartości nie są takie same) wówczas kompilator przerywa działanie całego programu oraz zgłasza błąd – co skutkuje niepowodzeniem testu.

 

 

Za pomocą metody clickButtonBasket() wywołanej na obiekcie pd klasy ProductDetails, klikamy w przycisk „Do koszyka„, który kończy proces dodawania pozycji do koszyka.

 

 

Ostatnią instrukcją kodu jest kolejna asercja, sprawdzająca tym razem czy komunikat jaki pojawia się po kliknięciu w przycisk „Do koszyka” – to komunikat informujący o pomyślności operacji. Jeśli komunikat zgadza się z komunikatem przewidywanym/poprawnym – wówczas kończy nasz test z wynikiem POZYTYWNYM.

 

 

Listing 1.2

 

 

Listing 1.2 Przedstawia poprawny komunikat jaki pojawia się po pomyślnej operacji dodania produktu do koszyka.

 

Na koniec jeszcze widok konsoli z poprawnie wykonanym testem.

 

7 myśli na “Skrypt testowy: Dodanie produktu do koszyka (Page Object Pattern)”

  1. Piękne dzięki, ciężko w necie podejrzeć za darmo pełne skrypty realizujące konkretne funkcjonalność, wiec tym bardziej dziękuję:)

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *