selenium phantomjs tutorial
Σε αυτό το άρθρο, ο αυτοματισμός σεληνίου με PhantomJS εξηγείται με παραδείγματα κώδικα:
Το PhantomJS είναι ένα πρόγραμμα περιήγησης χωρίς κεφαλή που χρησιμοποιείται κυρίως για λιγότερο αυτοματισμό GUI.
Η απόδοση και η εκτέλεση που πραγματοποιείται σε αυτό το πρόγραμμα περιήγησης είναι ταχύτερη και χρησιμοποιείται γενικά σε σενάρια όπου δεν απαιτείται χειροκίνητη παρακολούθηση και σε εφαρμογές που είναι πλήρως αυτοματοποιημένες.
Το PhantomJS συνιστάται ιδιαίτερα σε περίπτωση εκτέλεσης σεναρίου μιας νύχτας, όπου δεν απαιτείται ανθρώπινη παρακολούθηση καθώς η εκτέλεση είναι γρήγορη. Παρέχει επίσης επιλογές για ένα αυτόματο στιγμιότυπο οθόνης για μη αυτόματη παρακολούθηση της διαδικασίας εκτέλεσης σεναρίου.
Τι θα μάθετε:
- Χρησιμοποίηση PhantomJS στον αυτοματισμό ιστοσελίδας
- PhantomJS και σελήνιο για αυτοματοποίηση ιστού (βασικό)
- PhantomJS και σελήνιο για αυτοματοποίηση ιστού (για προχωρημένους)
- Στιγμιότυπο οθόνης και αναφορά μετά την εκτέλεση
- Σύσταση για χρήση του PhantomJS ως δοκιμαστικού προγράμματος περιήγησης
- Συνιστώμενη ανάγνωση
Χρησιμοποίηση PhantomJS στον αυτοματισμό ιστοσελίδας
Σε αυτό το άρθρο, θα χρησιμοποιήσουμε το εργαλείο αυτοματισμού Selenium για να εκτελέσουμε λειτουργικό αυτοματισμό στο πρόγραμμα περιήγησης PhantomJS.
Το PhantomJS ουσιαστικά δημιουργεί ένα πρόγραμμα περιήγησης που δεν διαθέτει διεπαφή GUI, αλλά διαθέτει όλα τα πρότυπα ενός προγράμματος περιήγησης με διεπαφή GUI όπως (Firefox, IE κ.λπ.), τυπική δέσμη ενεργειών DOM, κλήσεις Ajax κ.λπ.
Στόχος της χρήσης του PhantomJS με σελήνιο
Είναι πολύ σημαντικό να κατανοήσουμε τον στόχο της χρήσης του PhantomJS με το Σελήνιο.
Όλοι γνωρίζουμε ότι το Selenium είναι ένα λειτουργικό εργαλείο αυτοματισμού που χρησιμοποιείται για την αυτοματοποίηση διαφόρων λειτουργιών εφαρμογών Ιστού.
Τώρα, ο στόχος του PhantomJS είναι ελαφρώς διαφορετικός καθώς είναι ένα πρόγραμμα περιήγησης λιγότερο GUI και η κύρια χρήση του είναι η αυτοματοποίηση των δοκιμαστικών περιπτώσεων με πτώσεις στην κατηγορία δοκιμών καπνού / δοκιμών επικύρωσης και όχι πλήρους αυτοματισμού παλινδρομικής δοκιμής.
Εάν αυτοματοποιήσουμε τη χρήση Selenium και PhantomJS, πρέπει να προσέξουμε την επιλογή των δοκιμαστικών περιπτώσεων. Ένα άλλο σημαντικό μέρος είναι η παρακολούθηση της κατάστασης εκτέλεσης των δοκιμαστικών περιπτώσεων, καθώς δεν μπορούμε να δούμε φυσικά την εκτέλεση.
PhantomJS και σελήνιο για αυτοματοποίηση ιστού (βασικό)
Όπως όλα τα άλλα προγράμματα περιήγησης με διεπαφή GUI (Firefox, IE, Chrome κ.λπ.), για το PhantomJS, το Selenium διαθέτει ένα τυπικό API για την υποστήριξη του αυτοματισμού.
Ας παρουσιάσουμε το ίδιο με έναν απλό κώδικα:
import java.io.File; import java.io.IOException; import java.util.concurrent.TimeUnit; import org.apache.commons.io.FileUtils; import org.openqa.selenium.By; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import org.openqa.selenium.phantomjs.PhantomJSDriver; import org.openqa.selenium.phantomjs.PhantomJSDriverService; import org.openqa.selenium.remote.DesiredCapabilities; public class PhantomJSTest { public void phantomJS() throws InterruptedException, IOException { DesiredCapabilities caps = new DesiredCapabilities(); caps.setJavascriptEnabled(true); caps.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY, 'D:\chromedriver\phantomjs-2.1.1-windows\bin\phantomjs.exe'); caps.setCapability('takesScreenshot', true); PhantomJSDriver driver = new PhantomJSDriver(caps); String baseUrl = 'http://www.google.com'; driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); driver.get(baseUrl + '/'); File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); FileUtils.copyFile(scrFile, new File('d:\PhantomJSSample\screenshotAfterLaunchingGoogle.jpeg'),true); driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); driver.navigate().to('https://selenium.dev//');//Launch URL File scrFile1 = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); FileUtils.copyFile(scrFile1, new File('d:\PhantomJSSample\screenshotAfterLaunchingURL.jpeg'),true); driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); driver.findElement(By.linkText('Download')).click();//Click on the Link driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); File scrFile2 = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); FileUtils.copyFile(scrFile2, new File('d:\PhantomJSSample\screenshotAfterClickingDownload.jpeg'),true); Thread.sleep(2000); int header_size =driver.findElements(By.xpath('(//div(@id='mainContent')//h3(1))')).size();//Get the total count of h3 headers in the page for(int i=1; i?=header_size; i++) { String suggestion_name_xp = '('+'//div(@id='mainContent')//h3(1)'+')'+'('+i+')'; String header =driver.findElement(By.xpath(suggestion_name_xp)).getText(); System.out.println(header); //Print the name of headers } Thread.sleep(2000); } public static void main(String() args) throws InterruptedException, IOException { PhantomJSTest pj =new PhantomJSTest(); pj.phantomJS(); } }
Κυκλοφορεί το παραπάνω απόσπασμα κώδικα Επίσημος ιστότοπος Selenium στο πρόγραμμα περιήγησης PhantomJS και εκτελεί λειτουργία κλικ στην καρτέλα λήψης. Στη συνέχεια, υπολογίζει τον αριθμό των κεφαλίδων με ετικέτα h3 του κύριου περιεχομένου στη σελίδα λήψης και το εκτυπώνει.
sql ερωτήσεις και απαντήσεις στις εξετάσεις pdf
Μετά την εκτέλεση κάθε λειτουργίας, χρειάζεται ένα στιγμιότυπο οθόνης για χειροκίνητη παρακολούθηση.
πώς να εκτελέσετε το αρχείο java jar
Τώρα θα ενσωματώσουμε την ίδια λειτουργική δοκιμή σε ένα πλαίσιο με παρακολούθηση καταγραφής και το στιγμιότυπο οθόνης. Ας προσθέσουμε επίσης την αυτόματη αλληλογραφία μαζί με την ολοκλήρωση αναφορών έκτασης για να της δώσουμε ένα πλήρες αυτοματισμό, ώστε να μπορούμε να παρακολουθούμε το αποτέλεσμα εκτέλεσης αργότερα.
PhantomJS και σελήνιο για αυτοματοποίηση ιστού (για προχωρημένους)
Εικόνα της δομής πλαισίου
Το πλαίσιο είναι όπως υποδηλώνει η εικόνα και αποτελείται από:
- Τα επαναχρησιμοποιήσιμα συστατικά που μπορούν να επαναχρησιμοποιηθούν από κάθε σενάριο δοκιμής
- Το στοιχείο δοκιμής που θα δημιουργηθεί νέο με κάθε νέα υπόθεση δοκιμής.
- Τα συστατικά πόρων που αποτελούν τις εισόδους του πλαισίου όπως (Web Element locators, URL κ.λπ.)
Εδώ το έργο βασίζεται στο Maven μαζί με το δοκιμαστικό πλαίσιο TestNG. Επίσης, έχουμε χρησιμοποιήσει Extent Report. Αλλά δεν μπαίνω στις λεπτομέρειες ενός έργου Maven ή μιας έκθεσης, αλλά απλώς διατηρώ την εστίαση στο PhantomJS.
Λεπτομέρειες κώδικα για καθένα από τα στοιχεία δίνονται παρακάτω. Αυτό το πλαίσιο προορίζεται να επικεντρωθεί στην εφαρμογή του phantomJS, επομένως το πλαίσιο έχει σχεδιαστεί βάσει αυτού, αλλά μπορεί κανείς να επεκτείνει σίγουρα αυτό το πλαίσιο σύμφωνα με τις δικές του επιχειρηματικές προδιαγραφές.
Πρώτον, θα δούμε σε ποιες εξαρτήσεις πρέπει να δηλώσουμε POM.xml για να εκτελέσετε αυτό το έργο
'http://maven.apache.org/POM/4.0.0' xmlns:xsi= 'http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation= 'http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd' > 4.0.0 com.phantom.com com.phantomjs.com 0.0.1-SNAPSHOT org.apache.maven.plugins maven-resources-plugin 3.0.2 maven-plugin org.seleniumhq.selenium selenium-java 3.11.0 org.testng testng 6.8 test com.github.detro.ghostdriver phantomjsdriver 1.0.1 javax.mail mail 1.4 com.relevantcodes extentreports 2.40.2
POM.xml
Επαναχρησιμοποιήσιμα στοιχεία
package ReusableElements; import java.io.File; import java.util.List; import java.util.concurrent.TimeUnit; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.phantomjs.PhantomJSDriver; import org.openqa.selenium.phantomjs.PhantomJSDriverService; import org.openqa.selenium.remote.DesiredCapabilities; import org.testng.annotations.BeforeClass; import com.relevantcodes.extentreports.ExtentReports; import com.relevantcodes.extentreports.ExtentTest; import com.relevantcodes.extentreports.LogStatus; import ScreenShotLoc.ScreenShotLocations; public class InitiateBrowser { public static WebDriver driver = null; public ExtentReports extent; public ExtentTest logger; String workingDir = ScreenShotLocations.extentReportLoc; PropertyReader pr = new PropertyReader(); @BeforeClass public void InitBrowser() { extent = new ExtentReports(workingDir+'\ExtentReports\PhantomJSExectionResults.html', true); logger=extent.startTest('PhantomJS Implementation'); String BrowserName = 'PhantomJS'; if(BrowserName.equalsIgnoreCase('PhantomJS')) { DesiredCapabilities caps = new DesiredCapabilities(); caps.setJavascriptEnabled(true); caps.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY, ScreenShotLocations.PhantomJSdriverLoc); caps.setCapability('takesScreenshot', true); driver = new PhantomJSDriver(caps); List baseUrls = pr.URLReader(); String baseUrl= baseUrls.get(0); String altUrl= baseUrls.get(1); driver.get(baseUrl); logger.log(LogStatus.PASS, 'Browser Initiated'); driver.navigate().to(altUrl); logger.log(LogStatus.PASS, 'Navigated to target browser'); driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); } else if(BrowserName.equalsIgnoreCase('Chrome')) { System.setProperty('webdriver.chrome.driver',ScreenShotLocations.ChromedriverLoc); driver = new ChromeDriver(); List baseUrls = pr.URLReader(); String baseUrl= baseUrls.get(0); driver.get(baseUrl); logger.log(LogStatus.PASS, 'Browser Initiated'); driver.manage().window().maximize(); driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); } } }
InitiateBrowser.java
Αυτό το κομμάτι κώδικα σχετίζεται με την έναρξη προγράμματος περιήγησης.
Εδώ το όνομα του προγράμματος περιήγησης είναι κωδικοποιημένο. Αλλά μπορεί να είναι εξωτερικά (σε ιδιότητες / φύλλο excel). Κάποιος μπορεί να επιλέξει ποιο πρόγραμμα περιήγησης θα χρησιμοποιήσει και εδώ έχουμε χρησιμοποιήσει το PhantomJS.
package ReusableElements; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Properties; public class PropertyReader { Listvals = new ArrayList(); public List PropReader(){ Properties prop = new Properties(); try { prop.load(PropertyReader.class.getClassLoader().getResourceAsStream('ObjectRepository.properties')); vals.add(prop.getProperty('Download_Tab')); vals.add(prop.getProperty('H3_Headerlist')); } catch (IOException ex) { ex.printStackTrace(); } return vals; } public List URLReader() { Properties prp = new Properties(); try { prp.load(PropertyReader.class.getClassLoader().getResourceAsStream('APPURL.properties')); vals.add(prp.getProperty('APPURL')); vals.add(prp.getProperty('ALTERNATE_APPURL')); }catch (IOException ex) { ex.printStackTrace(); } return vals; } }
PropertyReader.java
Αυτό το κομμάτι κώδικα σχετίζεται με το αρχείο ιδιοτήτων ανάγνωσης που έχουμε χρησιμοποιήσει ως εντοπιστής στοιχείων ιστού και κοντέινερ διευθύνσεων URL.
package ReusableElements; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; import org.openqa.selenium.By; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; public class ReuseableMethods extends InitiateBrowser { public void LinktextClick(String loc) { driver.findElement(By.linkText(loc)).click();//Click on the Link } public String GetText(String loc) { String text= driver.findElement(By.xpath(loc)).getText(); return text; } public void takeScreenShot(String loc) throws IOException { File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); FileUtils.copyFile(scrFile, new File(loc),true); } }
ReuseableMethods.java
Αυτό το κομμάτι κώδικα ασχολείται με διάφορες λειτουργίες Selenium που χρησιμοποιούμε τακτικά στα σενάρια μας, αλλά έχουμε διαχωρίσει αυτές τις λειτουργίες από δοκιμαστικά σενάρια για να μειώσουμε τις γραμμές κώδικα στο πλαίσιο και να αυξήσουμε τη χρηστικότητα του.
package ReusableElements; import java.util.Properties; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.FileDataSource; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; public class SendMail { public void SendAutomatedMail() { final String from='XXXX';//change accordingly final String user='XXXX';//change accordingly final String password='XXXX';//change accordingly final String to='XXXX';//change accordingly //Creating the object for the session Properties props = new Properties(); props.put('mail.smtp.auth', 'true'); props.put('mail.smtp.starttls.enable', 'true'); props.put('mail.smtp.host','smtp.gmail.com'); props.put('mail.smtp.port', '587'); Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(user,password); } }); try { Message message = new MimeMessage(session); message.setFrom(new InternetAddress(from)); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to)); message.setSubject('TestExecution completed!! Please find the report'); BodyPart messageBodyPart = new MimeBodyPart(); messageBodyPart.setText('Hi All'); messageBodyPart.setText('please find the attachment'); Multipart multipart = new MimeMultipart(); multipart.addBodyPart(messageBodyPart); messageBodyPart = new MimeBodyPart(); String filename = 'D:/PhantomJSSample/ExtentReports/PhantomJSExectionResults.html'; DataSource source = new FileDataSource(filename); messageBodyPart.setDataHandler(new DataHandler(source)); messageBodyPart.setFileName(filename); multipart.addBodyPart(messageBodyPart); message.setContent(multipart); Transport.send(message); System.out.println('message sent successfully...'); } catch (MessagingException e) {e.printStackTrace();} } }
SendMail.java
Αυτό το κομμάτι κώδικα αφορά την αποστολή αυτόματης αλληλογραφίας μετά την εκτέλεση της δοκιμαστικής θήκης.
Εξαρτήματα δοκιμής
package com.phantomjs.com; import java.util.ArrayList; import java.util.List; import java.io.IOException; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; import org.testng.annotations.Test; import com.relevantcodes.extentreports.LogStatus; import ReusableElements.InitiateBrowser; import ReusableElements.PropertyReader; import ReusableElements.ReuseableMethods; import ReusableElements.SendMail; import ScreenShotLoc.ScreenShotLocations; public class TestScripts extends InitiateBrowser { @Test public void TestScript() throws IOException, InterruptedException { ReuseableMethods rm =new ReuseableMethods(); PropertyReader prop =new PropertyReader(); SendMail sm = new SendMail(); String download,h3_header; rm.takeScreenShot(ScreenShotLocations.screenshotAfterLaunchingURL); driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); List propvals = prop.PropReader(); download= propvals.get(0); h3_header= propvals.get(1); driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); try{ rm.LinktextClick(download);//Click on the Link logger.log(LogStatus.PASS, 'Validate if download Tab is clickable'); } catch(NoSuchElementException e) { logger.log(LogStatus.FAIL, 'Error while clicking on download Tab'); } driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); rm.takeScreenShot(ScreenShotLocations.screenshotAfterClickingDownload); Thread.sleep(2000); try{ int header_size =driver.findElements(By.xpath(h3_header)).size();//Get the total count of h3 headers in the page List headersh3 = new ArrayList(); for(int i=1; i?header_size; i++) { String suggestion_name_xp = '('+h3_header+')'+'('+i+')'; String header =rm.GetText(suggestion_name_xp); System.out.println(header); //Print the name of headers headersh3.add(header); //storing h3 main content headers to the list } logger.log(LogStatus.PASS, 'All main content h3 headers list printed on console'); int headers_count = headersh3.size(); if(headers_count==4) { logger.log(LogStatus.PASS, 'Validate if the main content h3 header count is as per business specification'); } Thread.sleep(2000); } catch(NoSuchElementException e) { logger.log(LogStatus.FAIL, 'Error while printing h3 headers list on console'); } extent.endTest(logger); extent.flush(); sm.SendAutomatedMail(); } }
TestScripts.java
Αυτή είναι η πραγματική περίπτωση δοκιμής όπου:
- Κυκλοφορεί το URL.
- Κάνουμε κλικ στην καρτέλα λήψης και επαληθεύουμε ότι ο σύνδεσμος λήψης μπορεί να κάνει κλικ ή όχι.
- Διαβάζουμε όλες τις κεφαλίδες h3 στην καρτέλα λήψης της σελίδας.
- Επικυρώνουμε τον αριθμό των κεφαλίδων h3.
Επαναχρησιμοποιήσιμα στοιχεία
package ScreenShotLoc; public interface ScreenShotLocations { String screenshotAfterLaunchingURL= 'd:\PhantomJSSample\screenshotAfterLaunchingURL.jpeg'; String screenshotAfterClickingDownload= 'd:\PhantomJSSample\screenshotAfterClickingDownload.jpeg'; String extentReportLoc= 'd:\PhantomJSSample\'; String ChromedriverLoc= 'D:\chromedriver\chromedriver.exe'; String PhantomJSdriverLoc= 'D:\phantomjs-2.1.1-windows\bin\phantomjs.exe'; }
ScreenShotLocations.java
APPURL = https://www.google.com ALTERNATE_APPURL = https://selenium.dev/
APPURL. Ιδιότητες
Download_Tab = Download H3_Headerlist= (//div(@id='mainContent')//h3(1))
ObjectRepository.properties
καλύτερη δωρεάν εφαρμογή λήψης mp3 για Android
Αυτές είναι οι εισροές που τροφοδοτούνται σε αυτό το πλαίσιο καθώς το πλαίσιο έχει σχεδιαστεί για να βασίζεται σε δεδομένα.
- Το ScreenShotLoc.java αποθηκεύει τη θέση του στιγμιότυπου οθόνης στη μονάδα δίσκου και τη θέση του προγράμματος οδήγησης του προγράμματος περιήγησης.
- Το APPURL.properties αποθηκεύει τη διεύθυνση URL της εφαρμογής που συμμετέχει στη δοκιμή.
- Το ObjectRepository.properties αποθηκεύει τους εντοπιστές στοιχείων ιστού.
Στιγμιότυπο οθόνης και αναφορά μετά την εκτέλεση
Τώρα θα δούμε την αναφορά μετά την εκτέλεση:
Θετικό σενάριο: Το παραπάνω στιγμιότυπο οθόνης είναι η αναφορά που δημιουργείται όταν όλα τα βήματα δοκιμής των αυτοματοποιημένων περιπτώσεων δοκιμής εκτελούνται με επιτυχία.
Αρνητικό σενάριο: Το παραπάνω στιγμιότυπο οθόνης είναι η αναφορά που δημιουργείται όταν όλα τα βήματα δοκιμής των αυτοματοποιημένων περιπτώσεων δοκιμής δεν εκτελούνται με επιτυχία.
Στιγμιότυπο αυτόματης αλληλογραφίας:
Σύσταση για χρήση του PhantomJS ως δοκιμαστικού προγράμματος περιήγησης
Παρακάτω δίνονται μερικές προτάσεις σχετικά με το πότε να χρησιμοποιήσετε το PhantomJS ως Test Browser.
- Η εκτέλεση είναι γρήγορη με καλή απόδοση.
- Ένας καλός υποψήφιος για αυτοματοποίηση εάν δεν απαιτείται χειροκίνητη παρακολούθηση καθώς το πρόγραμμα περιήγησης δεν είναι λιγότερο GUI.
- Συνιστάται ιδιαίτερα όταν οι δοκιμαστικές θήκες είναι σχεδιασμένες να εκτελούν δοκιμές καπνού ή περιπτώσεις δοκιμών όπου λαμβάνονται υπόψη μόνο τα σημεία επικύρωσης.
- Δεν συνιστάται για οπισθοδρομικές λειτουργικές δοκιμές.
Προτεινόμενη ανάγνωση = >> Στιγμιότυπα οθόνης στο Σελήνιο
Καλή ανάγνωση !!
Συνιστώμενη ανάγνωση
- Cucumber Selenium Tutorial: Αγγούρι Java Selenium WebDriver Integration
- 7 Παράγοντες που επηρεάζουν την εκτίμηση δοκιμής του έργου αυτοματισμού σεληνίου - Σελήνιο σεμινάριο # 32
- Appium Studio για Eclipse: End-to-end Appium / Selenium Automation From Eclipse
- Εισαγωγή στο Selenium WebDriver - Selenium Tutorial # 8
- Selenium Grid Tutorial: Ρύθμιση και παράδειγμα δοκιμής Cross Browser
- Tutorial ChromeDriver Selenium: Δοκιμές Webdriver Selenium στο Chrome
- Αποτελεσματικά σενάρια Selenium και Αντιμετώπιση προβλημάτων - Σελήνιο Σεμινάριο # 27
- Αποσφαλμάτωση σεναρίων σεληνίου με αρχεία καταγραφής (Tutorial Log4j) - Σεμινάριο σεμινάριο # 26