Użycie Docker Selenium w pipeline

Powrót do przeszłości

W poprzedniej lekcji dowiedziałeś się jak może wyglądać przykładowy pipeline w Jenkinsie. Jest to jedna z najprostszych możliwych implementacji. Czas na jego rozbudowę.

Aktualnie pipeline wygląda następująco:

pipeline {
    agent any
    stages {
        stage('Build test code') {
            steps {
                sh 'mvn clean install -DskipTests'
            }
        }
        stage('Execute test') {
            steps {
                sh 'mvn test'
            }
        }
        stage('Generate allure report') {
            steps {
                script {
                    allure([
                            includeProperties: false,
                            jdk              : '',
                            properties       : [],
                            reportBuildPolicy: 'ALWAYS',
                            results          : [[path: 'target/allure-results']]
                    ])
                }
            }
        }
    }
}

Analizując pipeline oraz framework, który go obsługuje widzimy, że ma on pewne wady. Do których należą:

  • Testy możemy uruchomić tylko w sposób taki jak zostało to przewidziane w kodzie. Konfiguracja jest zahardkodowana,
  • Do poprawnego uruchomienia i wykonania testów potrzebujemy zewnętrznego Selenium GRIDa,
  • Framework, który go obsługuje wymaga zewnętrznego Selenium GRID lub uruchomienia go w trybie lokalny driverów. Tryb lokalnych driverów powinien służyć tylko i wyłącznie do lokalnego developmentu testów, nie zaś do uruchamiania ich w ramach ciągłej integracji.
  • Raport Allure nie zostanie wygenerowany, jeśli stage „Execute test” nie zostanie wykonany.

Te i wiele innych problemów możemy wymieniać w nieskończoność. Czas zabrać się za jeden z nich jakim jest brak Selenium GRIDa w ramach pipelinu.

 

Problem zewnętrznego Selenium GRIDa.

Dla bieżącej implementacji uruchomienie testów na Selenium GRID wymaga infrastruktury jak na obrazku poniżej:

selenium grid

Jest to klasyczne podejście w którym mamy:

  • Jenkins – Serwer CI (Continues Integration) – który jest osobną maszyną odpowiadającą za hostowanie Jenkinsa tzw. Jenkins Master,
  • Jenkins Agent – maszyna na której uruchamiany jest kod testów tzw. Jenkins Slave,
  • Selenium Hub – maszyna z zainstalowanym Selenium Hub
  • Selenium Node – kolejne maszyny z odpowiednimi przeglądarkami i Selenium GRID w trybie Node.

Takie klasyczne podejście ma szereg problemów, do których możemy zaliczyć:

  • Wiele elementów infrastruktury, które potencjalnie mogą zawieść,
  • Brak kontroli nad infrastrukturą,
  • Ograniczone zasoby,
  • Duży koszt (duża liczba maszyn).

Rozwiązaniem części z  powyższych problemów jest Docker Selenium.

Dzięki zastosowaniu dokeryzacji Selenium GRIDa przenosimy wykonanie testów, oraz infrastrukturę Selenium GRIDa z zewnętrznej maszyny, nad którą nie mamy kontroli na agenta Jenkinsowego.

Przejdźmy w takim razie do implementacji.

Docker Selenium

Zanim zaczniemy, mała dygresja. Jeśli nie wiesz czym jest Docker Selenium w ramach kursu dostępny jest artykuł wprowadzający w zagadnienie. Możesz też zapoznać się z dokumentacją twórców.

Czas na jego przykładowe zastosowanie. W naszym przykładzie użyjemy najprostszego możliwego docker-compose.yml, który będzie agregował nam Selenium Hub oraz dwa nody z przeglądarkami Chrome oraz Firefox.

I tak mamy docker-compose.yml:

version: "3"
services:
  selenium-hub:
    image: selenium/hub:3.141.59-yttrium
    container_name: selenium-hub
    ports:
      - "4444:4444"
  chrome:
    image: selenium/node-chrome:3.141.59-yttrium
    volumes:
      - /dev/shm:/dev/shm
    depends_on:
      - selenium-hub
    environment:
      - HUB_HOST=selenium-hub
      - HUB_PORT=4444
  firefox:
    image: selenium/node-firefox:3.141.59-yttrium
    volumes:
      - /dev/shm:/dev/shm
    depends_on:
      - selenium-hub
    environment:
      - HUB_HOST=selenium-hub
      - HUB_PORT=4444

Plik docker-compose.yml umieszczamy w głównym katalogu repozytorium.

docker compose

Kolejnym krokiem będzie zmiana w ramach pliku configuration.properties na następujące wartości:

is.remote.run=true
grid.url=http://localhost:4444/wd/hub

Wartość localhost bieżę się stąd, że Selenium GRID będzie się znajdować na tej samej maszynie co testy, w ramach kontenera dockerowego.

Mając gotowy docker-compose.yml możemy przejść do modyfikacji Jenkinsfile. Dzieki zastosowaniu podejścia infrastructure as a code wszystko znajduję się w repozytorium. Nie musimy modyfikować pipelinu utworzonego w ramach lekcji.

Dla przypomnienia aby uruchomić kontenery zdefiniowane w docker-compose.yml wywołujemy komendę:

docker-compose up -d

W celu ich wyłączenia kontenerów:

docker-compose down

Przechodząc do implementacji Jenkinsfile mamy:

pipeline {
    agent any
    stages {
        stage('Build test code') {
            steps {
                sh 'mvn clean install -DskipTests' // Budowanie testów
            }
        }
        stage('Run selenium grid') {
            steps {
                sh 'docker-compose up -d' // Uruchiomienie Docker Selenium
            }
        }
        stage('Execute test') {
            steps {
                sh 'mvn test' // Uruchomienie testów
                sh 'docker-compose down' // Wyłączenie Docker Selenium, wyłączenie kontenerów
            }
        }
    }
    post {
        always {
            script { // Wygenerowanie raportu Allurowego
                allure([
                        includeProperties: false,
                        jdk              : '',
                        properties       : [],
                        reportBuildPolicy: 'ALWAYS',
                        results          : [[path: 'target/allure-results']]
                ])
            }
        }
    }
}

Dodatkowo w porównaniu do poprzedniego pipelina, przenieśliśmy skrypt odpowiadający za generowanie raportu Allurowego do sekcji post. Sekcja post jest to sekcja, która wykona się zawsze po przejściu całego planu, niezależnie od wyniku.

Kurs Selenium

Uwaga: Do poprawnego uruchomienia powyższego pipelinu na maszynie agenta powinien być zainstalowany docker!

Jeśli teraz uruchomimy zmodyfikowany pipeline, zobaczymy:

[Pipeline] }
[Pipeline] // stage
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Build test code)
[Pipeline] sh
+ mvn clean install -DskipTests
[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------< pl.javastart.courses:selenium-intro >-----------------
[INFO] Building selenium-intro 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ selenium-intro ---
[INFO] Deleting D:\Program Files (x86)\Jenkins\workspace\Test\target
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ selenium-intro ---
[WARNING] Using platform encoding (Cp1250 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 3 resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ selenium-intro ---
[INFO] No sources to compile
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ selenium-intro ---
[WARNING] Using platform encoding (Cp1250 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.7.0:testCompile (default-testCompile) @ selenium-intro ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 26 source files to D:\Program Files (x86)\Jenkins\workspace\Test\target\test-classes
[INFO] 
[INFO] --- maven-surefire-plugin:2.21.0:test (default-test) @ selenium-intro ---
[INFO] Tests are skipped.
[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ selenium-intro ---
[INFO] Building jar: D:\Program Files (x86)\Jenkins\workspace\Test\target\selenium-intro-1.0-SNAPSHOT.jar
[INFO] 
[INFO] --- maven-install-plugin:2.4:install (default-install) @ selenium-intro ---
[INFO] Installing D:\Program Files (x86)\Jenkins\workspace\Test\target\selenium-intro-1.0-SNAPSHOT.jar to C:\Windows\system32\config\systemprofile\.m2\repository\pl\javastart\courses\selenium-intro\1.0-SNAPSHOT\selenium-intro-1.0-SNAPSHOT.jar
[INFO] Installing D:\Program Files (x86)\Jenkins\workspace\Test\pom.xml to C:\Windows\system32\config\systemprofile\.m2\repository\pl\javastart\courses\selenium-intro\1.0-SNAPSHOT\selenium-intro-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.722 s
[INFO] Finished at: 2020-01-12T10:11:24+01:00
[INFO] ------------------------------------------------------------------------
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Run selenium grid)
[Pipeline] sh
+ docker-compose up -d
Creating network "test_default" with the default driver
Pulling selenium-hub (selenium/hub:3.141.59-yttrium)...
3.141.59-yttrium: Pulling from selenium/hub
Digest: sha256:6f6bdd8d5ce5cd8d7be42ded88bc3dbbdf7a60ec32c908eb26dd31b37f69589a
Status: Downloaded newer image for selenium/hub:3.141.59-yttrium
Pulling chrome (selenium/node-chrome:3.141.59-yttrium)...
3.141.59-yttrium: Pulling from selenium/node-chrome
Digest: sha256:5e37ffdeae0864dd7f0df63adafcc9428766d79976a645853bc1e20d7487ff4f
Status: Downloaded newer image for selenium/node-chrome:3.141.59-yttrium
Pulling firefox (selenium/node-firefox:3.141.59-yttrium)...
3.141.59-yttrium: Pulling from selenium/node-firefox
Digest: sha256:3a92810aca49182944c72e15c68dd8561731f25e723983d8702a9234d32163d6
Status: Downloaded newer image for selenium/node-firefox:3.141.59-yttrium
Creating selenium-hub ... 

 [1A [2K
Creating selenium-hub ...  [32mdone [0m
 [1BCreating test_firefox_1 ... 

Creating test_chrome_1  ... 

 [2A [2K
Creating test_firefox_1 ...  [32mdone [0m
 [2B [1A [2K
Creating test_chrome_1  ...  [32mdone [0m
 [1B
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Execute test)
[Pipeline] sh
+ mvn test
[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------< pl.javastart.courses:selenium-intro >-----------------
[INFO] Building selenium-intro 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ selenium-intro ---
[WARNING] Using platform encoding (Cp1250 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 3 resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ selenium-intro ---
[INFO] No sources to compile
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ selenium-intro ---
[WARNING] Using platform encoding (Cp1250 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.7.0:testCompile (default-testCompile) @ selenium-intro ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-surefire-plugin:2.21.0:test (default-test) @ selenium-intro ---
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running TestSuite
[INFO ] 2020-01-12 10:12:34.795 [TestNG-tests-2] configuration.PropertiesLoader - Trying to load properties with file name: configuration.properties
[INFO ] 2020-01-12 10:12:34.795 [TestNG-tests-1] configuration.PropertiesLoader - Trying to load properties with file name: configuration.properties
[INFO ] 2020-01-12 10:12:34.803 [TestNG-tests-2] configuration.PropertiesLoader - Successfully loaded properties for file: configuration.properties
[INFO ] 2020-01-12 10:12:34.803 [TestNG-tests-1] configuration.PropertiesLoader - Successfully loaded properties for file: configuration.properties
sty 12, 2020 10:12:35 AM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
[INFO ] 2020-01-12 10:12:35.982 [TestNG-tests-2] driver.listeners.DriverEventListener - Trying to navigate to http://przyklady.javastart.pl/jpetstore/
[INFO ] 2020-01-12 10:12:36.114 [TestNG-tests-2] driver.listeners.DriverEventListener - Navigated to http://przyklady.javastart.pl/jpetstore/
[INFO ] 2020-01-12 10:12:36.209 [TestNG-tests-2] utils.testng.listeners.TestListener - Starting test: asUserLoginUsingValidLoginAndPassword
[INFO ] 2020-01-12 10:12:36.234 [TestNG-tests-2] driver.listeners.DriverEventListener - Trying to navigate to http://przyklady.javastart.pl/jpetstore/actions/Account.action?signonForm=
[INFO ] 2020-01-12 10:12:36.376 [TestNG-tests-2] driver.listeners.DriverEventListener - Navigated to http://przyklady.javastart.pl/jpetstore/actions/Account.action?signonForm=
[INFO ] 2020-01-12 10:12:36.407 [TestNG-tests-2] driver.listeners.DriverEventListener - Trying to find element with locator By.name: username
[INFO ] 2020-01-12 10:12:36.429 [TestNG-tests-2] driver.listeners.DriverEventListener - Found element with locator By.name: username
[INFO ] 2020-01-12 10:12:36.484 [TestNG-tests-2] driver.listeners.DriverEventListener - Trying to find element with locator By.name: username
[INFO ] 2020-01-12 10:12:36.500 [TestNG-tests-2] driver.listeners.DriverEventListener - Found element with locator By.name: username
[INFO ] 2020-01-12 10:12:36.514 [TestNG-tests-2] driver.listeners.DriverEventListener - Trying to type into element: input text [j2ee]
[INFO ] 2020-01-12 10:12:36.586 [TestNG-tests-2] driver.listeners.DriverEventListener - Typed into element: input text [j2ee]
[INFO ] 2020-01-12 10:12:36.588 [TestNG-tests-2] page.objects.LoginPage - Typed into User Name Field j2ee
[INFO ] 2020-01-12 10:12:36.588 [TestNG-tests-2] driver.listeners.DriverEventListener - Trying to find element with locator By.name: password
[INFO ] 2020-01-12 10:12:36.611 [TestNG-tests-2] driver.listeners.DriverEventListener - Found element with locator By.name: password
[INFO ] 2020-01-12 10:12:36.621 [TestNG-tests-2] driver.listeners.DriverEventListener - Trying to enter empty string or clear element: input
[INFO ] 2020-01-12 10:12:36.663 [TestNG-tests-2] driver.listeners.DriverEventListener - Entered empty string or cleared element: input
[INFO ] 2020-01-12 10:12:36.664 [TestNG-tests-2] driver.listeners.DriverEventListener - Trying to find element with locator By.name: password
[INFO ] 2020-01-12 10:12:36.681 [TestNG-tests-2] driver.listeners.DriverEventListener - Found element with locator By.name: password
[INFO ] 2020-01-12 10:12:36.695 [TestNG-tests-2] driver.listeners.DriverEventListener - Trying to type into element: input text [j2ee]
[INFO ] 2020-01-12 10:12:36.788 [TestNG-tests-2] driver.listeners.DriverEventListener - Typed into element: input text [j2ee]
[INFO ] 2020-01-12 10:12:36.788 [TestNG-tests-2] page.objects.LoginPage - Typed into Password Field j2ee
[INFO ] 2020-01-12 10:12:36.788 [TestNG-tests-2] driver.listeners.DriverEventListener - Trying to find element with locator By.name: signon
[INFO ] 2020-01-12 10:12:36.822 [TestNG-tests-2] driver.listeners.DriverEventListener - Found element with locator By.name: signon
[INFO ] 2020-01-12 10:12:36.838 [TestNG-tests-2] driver.listeners.DriverEventListener - Trying to click on element with tag name: input
[INFO ] 2020-01-12 10:12:37.026 [TestNG-tests-2] driver.listeners.DriverEventListener - Clicked on element
[INFO ] 2020-01-12 10:12:37.026 [TestNG-tests-2] page.objects.LoginPage - Clicked on Login Button
[INFO ] 2020-01-12 10:12:37.027 [TestNG-tests-2] page.objects.FooterPage - Checking if dog banner is displayed
[INFO ] 2020-01-12 10:12:37.027 [TestNG-tests-2] driver.listeners.DriverEventListener - Trying to find element with locator By.cssSelector: #Banner img[src*='dog']
[INFO ] 2020-01-12 10:12:37.052 [TestNG-tests-2] driver.listeners.DriverEventListener - Found element with locator By.cssSelector: #Banner img[src*='dog']
[INFO ] 2020-01-12 10:12:37.119 [TestNG-tests-2] generic.assertions.AssertWebElement - Checking if element is displayed
[INFO ] 2020-01-12 10:12:37.119 [TestNG-tests-2] driver.listeners.DriverEventListener - Trying to find element with locator By.cssSelector: #Banner img[src*='dog']
[INFO ] 2020-01-12 10:12:37.150 [TestNG-tests-2] driver.listeners.DriverEventListener - Found element with locator By.cssSelector: #Banner img[src*='dog']
[INFO ] 2020-01-12 10:12:37.172 [TestNG-tests-2] generic.assertions.AssertWebElement - WebElement was displayed!
[INFO ] 2020-01-12 10:12:37.174 [TestNG-tests-2] utils.testng.listeners.TestListener - Test asUserLoginUsingValidLoginAndPassword passed successfully
sty 12, 2020 10:12:37 AM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
[INFO ] 2020-01-12 10:12:37.410 [TestNG-tests-1] driver.listeners.DriverEventListener - Trying to navigate to http://przyklady.javastart.pl/jpetstore/
[INFO ] 2020-01-12 10:12:37.557 [TestNG-tests-1] driver.listeners.DriverEventListener - Navigated to http://przyklady.javastart.pl/jpetstore/
[INFO ] 2020-01-12 10:12:37.561 [TestNG-tests-1] utils.testng.listeners.TestListener - Starting test: asUserTryToLogInWithIncorrectLoginAndPassword
[INFO ] 2020-01-12 10:12:37.564 [TestNG-tests-1] driver.listeners.DriverEventListener - Trying to navigate to http://przyklady.javastart.pl/jpetstore/actions/Account.action?signonForm=
[INFO ] 2020-01-12 10:12:37.734 [TestNG-tests-1] driver.listeners.DriverEventListener - Navigated to http://przyklady.javastart.pl/jpetstore/actions/Account.action?signonForm=
[INFO ] 2020-01-12 10:12:37.734 [TestNG-tests-1] driver.listeners.DriverEventListener - Trying to find element with locator By.name: username
[INFO ] 2020-01-12 10:12:37.750 [TestNG-tests-1] driver.listeners.DriverEventListener - Found element with locator By.name: username
[INFO ] 2020-01-12 10:12:37.780 [TestNG-tests-1] driver.listeners.DriverEventListener - Trying to find element with locator By.name: username
[INFO ] 2020-01-12 10:12:37.793 [TestNG-tests-1] driver.listeners.DriverEventListener - Found element with locator By.name: username
[INFO ] 2020-01-12 10:12:37.802 [TestNG-tests-1] driver.listeners.DriverEventListener - Trying to type into element: input text [NotExistingLogin]
[INFO ] 2020-01-12 10:12:37.832 [TestNG-tests-1] driver.listeners.DriverEventListener - Typed into element: input text [NotExistingLogin]
[INFO ] 2020-01-12 10:12:37.832 [TestNG-tests-1] page.objects.LoginPage - Typed into User Name Field NotExistingLogin
[INFO ] 2020-01-12 10:12:37.832 [TestNG-tests-1] driver.listeners.DriverEventListener - Trying to find element with locator By.name: password
[INFO ] 2020-01-12 10:12:37.846 [TestNG-tests-1] driver.listeners.DriverEventListener - Found element with locator By.name: password
[INFO ] 2020-01-12 10:12:37.853 [TestNG-tests-1] driver.listeners.DriverEventListener - Trying to enter empty string or clear element: input
[INFO ] 2020-01-12 10:12:37.885 [TestNG-tests-1] driver.listeners.DriverEventListener - Entered empty string or cleared element: input
[INFO ] 2020-01-12 10:12:37.885 [TestNG-tests-1] driver.listeners.DriverEventListener - Trying to find element with locator By.name: password
[INFO ] 2020-01-12 10:12:37.897 [TestNG-tests-1] driver.listeners.DriverEventListener - Found element with locator By.name: password
[INFO ] 2020-01-12 10:12:37.904 [TestNG-tests-1] driver.listeners.DriverEventListener - Trying to type into element: input text [NotProperPassword]
[INFO ] 2020-01-12 10:12:37.936 [TestNG-tests-1] driver.listeners.DriverEventListener - Typed into element: input text [NotProperPassword]
[INFO ] 2020-01-12 10:12:37.936 [TestNG-tests-1] page.objects.LoginPage - Typed into Password Field NotProperPassword
[INFO ] 2020-01-12 10:12:37.936 [TestNG-tests-1] driver.listeners.DriverEventListener - Trying to find element with locator By.name: signon
[INFO ] 2020-01-12 10:12:37.949 [TestNG-tests-1] driver.listeners.DriverEventListener - Found element with locator By.name: signon
[INFO ] 2020-01-12 10:12:37.955 [TestNG-tests-1] driver.listeners.DriverEventListener - Trying to click on element with tag name: input
[INFO ] 2020-01-12 10:12:38.028 [TestNG-tests-1] driver.listeners.DriverEventListener - Clicked on element
[INFO ] 2020-01-12 10:12:38.028 [TestNG-tests-1] page.objects.LoginPage - Clicked on Login Button
[INFO ] 2020-01-12 10:12:38.028 [TestNG-tests-1] page.objects.LoginPage - Checking if warning message Invalid username or password. Signon failed. is displayed
[INFO ] 2020-01-12 10:12:38.029 [TestNG-tests-1] driver.listeners.DriverEventListener - Trying to find element with locator By.cssSelector: #Content ul[class='messages'] li
[INFO ] 2020-01-12 10:12:38.040 [TestNG-tests-1] driver.listeners.DriverEventListener - Found element with locator By.cssSelector: #Content ul[class='messages'] li
[INFO ] 2020-01-12 10:12:38.075 [TestNG-tests-1] generic.assertions.AssertWebElement - Checking if element is displayed
[INFO ] 2020-01-12 10:12:38.075 [TestNG-tests-1] driver.listeners.DriverEventListener - Trying to find element with locator By.cssSelector: #Content ul[class='messages'] li
[INFO ] 2020-01-12 10:12:38.087 [TestNG-tests-1] driver.listeners.DriverEventListener - Found element with locator By.cssSelector: #Content ul[class='messages'] li
[INFO ] 2020-01-12 10:12:38.110 [TestNG-tests-1] generic.assertions.AssertWebElement - WebElement was displayed!
[INFO ] 2020-01-12 10:12:38.110 [TestNG-tests-1] generic.assertions.AssertWebElement - Checking if WebElement has text: Invalid username or password. Signon failed.
[INFO ] 2020-01-12 10:12:38.110 [TestNG-tests-1] driver.listeners.DriverEventListener - Trying to find element with locator By.cssSelector: #Content ul[class='messages'] li
[INFO ] 2020-01-12 10:12:38.120 [TestNG-tests-1] driver.listeners.DriverEventListener - Found element with locator By.cssSelector: #Content ul[class='messages'] li
[INFO ] 2020-01-12 10:12:38.120 [TestNG-tests-1] driver.listeners.DriverEventListener - Trying to get text for WebElement
[INFO ] 2020-01-12 10:12:38.131 [TestNG-tests-1] driver.listeners.DriverEventListener - Taken text of WebElement. Text wast Invalid username or password. Signon failed.
[INFO ] 2020-01-12 10:12:38.132 [TestNG-tests-1] generic.assertions.AssertWebElement - WebElement had expected text!
[INFO ] 2020-01-12 10:12:38.132 [TestNG-tests-1] utils.testng.listeners.TestListener - Test asUserTryToLogInWithIncorrectLoginAndPassword passed successfully
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 5.339 s - in TestSuite
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  7.196 s
[INFO] Finished at: 2020-01-12T10:12:39+01:00
[INFO] ------------------------------------------------------------------------
[Pipeline] sh
+ docker-compose down
Stopping test_firefox_1 ... 

Stopping test_chrome_1  ... 

Stopping selenium-hub   ... 

 [3B [1A [2K
Stopping selenium-hub   ...  [32mdone [0m
 [1BRemoving test_firefox_1 ... 

Removing test_chrome_1  ... 

Removing selenium-hub   ... 

 [1A [2K
Removing selenium-hub   ...  [32mdone [0m
 [1B [3A [2K
Removing test_firefox_1 ...  [32mdone [0m
 [3B [2A [2K
Removing test_chrome_1  ...  [32mdone [0m
 [2BRemoving network test_default
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Declarative: Post Actions)
[Pipeline] script
[Pipeline] {
[Pipeline] allure
[Test] $ "D:\Program Files (x86)\Jenkins\tools\ru.yandex.qatools.allure.jenkins.tools.AllureCommandlineInstallation\allure\bin\allure.bat" generate "D:\Program Files (x86)\Jenkins\workspace\Test\target\allure-results" -c -o "D:\Program Files (x86)\Jenkins\workspace\Test\allure-report"
Report successfully generated to D:\Program Files (x86)\Jenkins\workspace\Test\allure-report
Allure report was successfully generated.
Creating artifact for the build.
Artifact was added to the build.
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

Podsumowanie

Dzięki zastosowaniu Docker Selenium mamy możliwość:

  • Łatwego skalowania ilością Nodów Selenium i ich konfiguracją w ramach docker-compose.yml
  • Pełną kontrolą na infrastrukturą Selenium GRID,
  • Wykonanie na jednej maszynie, co zmniejsza koszt, zwiększa stabilność, ułatwia debugowanie.

 

Potrzebujesz więcej informacji?

Artykuł powstał na bazie kursu Automatyzacja testów z wykorzystaniem Selenium.

O Autorze

Nazywam się Mateusz Ciołek i od 2011 roku zajmuję się testowaniem oprogramowania ze specjalizacją w automatyzacji testów. 

Dyskusja i komentarze

Masz pytania do tego wpisu? Może chcesz się podzieliś spostrzeżeniami? Zapraszamy dyskusji na naszej grupe na Facebooku.