Σε αυτό το σεμινάριο θα μάθουμε για τα σχέδια σχεδίασης και τις βέλτιστες πρακτικές του Σεληνίου ενώ συνεργαζόμαστε με την ανάπτυξη πλαισίου Αυτοματισμού Selenium (υβριδικό πλαίσιο στο σελήνιο), υπάρχουν δύο παραλλαγές του σχεδιασμού πλαισίου ή του μοντέλου πλαισίου που πρέπει να λάβουμε υπόψη, οι οποίες είναι:
Πρέπει να γνωρίζουμε και να κατανοούμε γιατί απαιτείται μοτίβο σχεδιασμού γλώσσας όταν αναπτύσσουμε το δικό μας πλαίσιο σε ένα από το σελήνιο μοντέλο πλαισίου. Θα προτείναμε να περάσετε από τα προηγούμενα τμήματα του Σειρά φροντιστηρίων ανάπτυξης Selenium Framework για να πάρετε όλη την κατανόηση.
Ας το καταλάβουμε λεπτομερώς:
σχέδια σχεδιασμού σεληνίου και βέλτιστες πρακτικές -υβριδικό πλαίσιο σεληνίου

Κατά τη σχεδίαση οποιουδήποτε Πλαισίου, πρέπει να εξετάσουμε κάποια αρχιτεκτονική σχεδίασης, δηλαδή σχέδια σεληνίου και βέλτιστες πρακτικές, και σύμφωνα με την ανάγκη του τύπου του μοντέλου πλαισίου, πρέπει να επιλέξουμε μια Γλώσσα Σχέδιο για την επίλυση της προβληματικής κατάστασης του σχεδιασμού πλαισίου στο σύνολό του.
Ως εκ τούτου, μόνο για να καταλήξουμε, μπορούμε να επιλέξουμε και το μοντέλο πλαισίου σεληνίου (Hybrid, Μοντέλο αντικειμένου σελίδας, Data Driven, κ.λπ.), αλλά για να εφαρμόσουμε το μοντέλο, πρέπει να ακολουθήσουμε και να εφαρμόσουμε κάποιο μοτίβο σχεδίασης γλώσσας (π.χ. μοτίβα σχεδίασης java/C#)
Γιατί χρειαζόμαστε σχέδιο σεληνίου Σχέδιο και βέλτιστες πρακτικές κατά την κατασκευή του Selenium Framework:
Ποια σχέδια σχεδίασης θα χρησιμοποιηθούν στο Selenium Framework:
Υπάρχουν μερικά μοτίβα σχεδίασης που θα μπορούσατε να χρησιμοποιήσετε για να εφαρμόσετε διαφορετικές περιοχές του πλαισίου, όπως ένα παράδειγμα:
Θα κάνουμε το ζωντανό πρότυπο κωδικοποίησης ολόκληρου του Framework στις επερχόμενες δημοσιεύσεις εδώ.
Σχέδιο Singleton Design για υβριδικό πλαίσιο στο Σελήνιο:
Το Singleton Design Pattern είναι ένα μοτίβο στο οποίο θα μπορούσατε να δημιουργήσετε μόνο ένα αντικείμενο από μια τάξη και να χρησιμοποιήσετε το ίδιο αντικείμενο για να αποκτήσετε πρόσβαση στις μεθόδους της τάξης. θα μπορούσαμε να χρησιμοποιήσουμε το μοτίβο σχεδίασης στο πρόγραμμα διαμόρφωσης όπου χρειάζεται μόνο να διαβάσουμε τα δεδομένα διαμόρφωσης και να φορτώσουμε σε κάποια αποθήκευση δεδομένων (κάθε είδους δομή δεδομένων που θα μπορούσατε να χρησιμοποιήσετε όπως και όταν απαιτείται κατά την εκτέλεση από οποιεσδήποτε κλάσεις και μεθόδους)
Έτσι θα μπορούσαμε να επιτύχουμε το ίδιο με τον παρακάτω τρόπο, ενώ σχεδιάζουμε το ίδιο με το σχέδιο Singleton Design.
ΣΗΜΕΙΩΣΗ: Θα σχεδιάσουμε και θα αναπτύξουμε το πλαίσιο από το μηδέν στην επόμενη ενότητα της σειράς σεμιναρίων, αλλά αυτό το συγκεκριμένο σεμινάριο θα σας δώσει πληροφορίες για την αναγκαιότητα του σχεδιαστικού σχεδίου.
πακέτο com.cyborg.core.generic.dataUtils; εισαγωγή java.io.FileInputStream; εισαγωγή java.io.FileNotFoundException; εισαγωγή java.io.IOException; εισαγωγή java.io.InputStream; εισαγωγή java.util.LinkedHashMap; εισαγωγή java.util.Properties; εισαγωγή java.util.Set; εισαγωγή org.apache.log4j.PropertyConfigurator; // Αυτή είναι η δημόσια κλάση SingleTon Class PropertiesDataUtils { private Properties ιδιότητες = null; δημόσιο στατικό LinkedHashMap configDataStore = νέο LinkedHashMap () InputStream είναι = null; // Αυτή είναι η στατική και ιδιωτική αναφορά της κλάσης που θα μπορούσατε να χρησιμοποιήσετε οπουδήποτε στο πλαίσιο σας private static PropertiesDataUtils ιδιότητεςDataUtils = null; boolean centralizeLog = false; // Αυτός είναι ο Ιδιωτικός κατασκευαστής για τη δημιουργία του αντικειμένου, αλλά δεν μπορείτε να αποκτήσετε πρόσβαση σε αυτό από έξω από την κλάση για να διατηρήσετε τη σχεδίαση του μοτίβου SingleTon, δηλαδή δημιουργία μόνο ενός αντικειμένου. private PropertiesDataUtils(String filePath) {genereDataStore(filePath); centralizeLog = Boolean.parseBoolean(PropertiesDataUtils.configDataStore.get("centralizedLog")); if(centralizeLog) PropertyConfigurator.configure(System.getProperty("user.dir")+"//src//test//resources//config//log4j_central.properties"); else PropertyConfigurator.configure(System.getProperty("user.dir")+"//src//test//resources//config//log4j_local.properties"); } private PropertiesDataUtils() { } // Αυτή η μέθοδος δημιουργεί βασικά την παρουσία της κλάσης SingleTon public static PropertiesDataUtils getInstance(String filePath) { if (propertiesDataUtils == null) propertiesDataUtils = new PropertiesDataUtils(filePath); επιστροφή ιδιότητεςDataUtils; } // αυτή η μέθοδος δημιουργεί βασικά το χώρο αποθήκευσης δεδομένων όπου θέλετε να αποθηκεύσετε όλα τα δεδομένα διαμόρφωσης όπως συζητήθηκε προηγουμένως private void generateDataStore(String filePath) { try { this.properties = new Properties(); is=new FileInputStream(filePath); ιδιότητες.φορτίο(είναι); overrideFromEnvironment(); Σειρά keys = loadAllKeys(); for (Object k : keys) { String key = (String) k; configDataStore.put(key, getPropertyValue(key)); } } catch (FileNotFoundException fileNotFoundException) { String exclusiveData = String.valueOf(fileNotFoundException.getCause().getMessage()); } catch (IOException ioException) { String exclusiveData = String.valueOf(ioException.getCause().getMessage()); } τελικά { if (null != is) { try { is.close(); } catch (Exception e) { String exclusiveData = String.valueOf(e.getCause().getMessage()); } } } } // Αυτή η μέθοδος χρησιμοποιείται για τη φόρτωση όλων των κλειδιών από το αρχείο ιδιοτήτων.
Με αυτήν την προσέγγιση, θα μπορούσαμε να χρησιμοποιήσουμε το σχέδιο σχεδίασης Singleton και να το χρησιμοποιήσουμε στο πλαίσιο μας.
Εργοστάσιο σχεδίασης στο σελήνιο πλαίσιο:
Στο εργοστασιακό σχέδιο, δημιουργούμε μια τάξη (την ονομάζουμε εργοστασιακή κλάση) και από την άλλη έχουμε μια διεπαφή και τελικά υλοποιήθηκε από τον αριθμό κλάσεων «n».
Η εργοστασιακή κλάση επιστρέφει βασικά το αντικείμενο των παραπάνω τάξεων (ανάλογα με την ανάγκη), οπότε δεν χρειάζεται να ασχοληθείτε με τα παραπάνω "N" αριθμός αντικειμένων κλάσεων. Αντίθετα, μπορείτε να δημιουργήσετε ένα αντικείμενο της κλάσης Εργοστάσιο και να καλέσετε τη μέθοδο της κλάσης του εργοστασίου που επιστρέφει το απαιτούμενο βασικό αντικείμενο για τις απαιτούμενες κλάσεις μεταξύ των τάξεων adobe "n"
Τώρα, αυτό το σχέδιο μπορείτε να σκεφτείτε κατά τη δημιουργία της διαφορετικής εφαρμογής Webdriver / browser.
Έχουμε διάφορα πρόγραμμα περιήγησης και την υλοποίηση με διαφορετικό τύπο Selenium πρόγραμμα οδήγησης (π.χ. LocalDriver, RemoteDriver, ThreadDriver, κ.λπ.) και καθώς και όταν χρειάζεστε συγκεκριμένο τύπο προγράμματος οδήγησης και συγκεκριμένο τύπο προγράμματος περιήγησης μπορείτε να αναφέρετε στο αρχείο διαμόρφωσης και βάσει της ανάγκης η εργοστασιακή κλάση θα σας παρέχει την παρουσία του το πρόγραμμα οδήγησης και το πρόγραμμα περιήγησης για περαιτέρω χρήση του σεναρίου αυτοματισμού.
Εδώ είναι η βάση κώδικα για την εφαρμογή αυτού του μοτίβου σχεδίασης κατά τη δημιουργία αλληλεπιδράσεων προγράμματος οδήγησης-προγράμματος περιήγησης:
Σχεδιασμός διασύνδεσης:
πακέτο com.cyborg.core.web.utils.driverUtils; εισαγωγή org.openqa.selenium.WebDriver; εισαγωγή org.openqa.selenium.remote.RemoteWebDriver; δημόσια διεπαφή IDriver { public WebDriver init(String browserName); }
"N" αριθμός εφαρμογής κλάσεων περιήγησης (που εφαρμόζουν τη διεπαφή):
πακέτο com.cyborg.core.web.utils.driverUtils; εισαγωγή org.openqa.selenium.WebDriver; εισαγωγή org.openqa.selenium.chrome.ChromeDriver; εισαγωγή org.openqa.selenium.edge.EdgeDriver; εισαγωγή org.openqa.selenium.firefox.FirefoxDriver; εισαγωγή org.openqa.selenium.ie.InternetExplorerDriver; εισαγωγή org.openqa.selenium.safari.SafariDriver; δημόσια κλάση Το LocalDriver υλοποιεί IDriver { public WebDriver init(String browserName) { String pathToDriver = getDriverPath(browserName); if (null != Όνομα προγράμματος περιήγησης) { switch (browserName) { case "chrome": System.setProperty("webdriver.chrome.driver", pathToDriver); επιστροφή νέου ChromeDriver(); case "firefox": System.setProperty("webdriver.gecko.driver", pathToDriver); επιστροφή νέου FirefoxDriver(); προεπιλογή: System.setProperty("webdriver.chrome.driver", pathToDriver); επιστροφή νέου ChromeDriver(); } } else { System.setProperty("webdriver.chrome.driver", pathToDriver); επιστροφή νέου ChromeDriver(); } } private String getDriverPath(String browserName) { String osData = System.getProperty("os.name").toLowerCase().split("\\s")[0]; if (null != osData) { if (osData.equalsIgnoreCase("mac")) { return "./DriversExe/" + osData + "_" + browserName; } else if (osData.contains("nux") || (osData.contains("nix"))) { return "./DriversExe/linux_" + browserName; } else if (osData.contains("win")) { return "./DriversExe/" + osData + "_" + Όνομα προγράμματος περιήγησης + ".exe"; } } return null; } }
Εδώ είναι η εφαρμογή της κλάσης Απομακρυσμένου προγράμματος οδήγησης:
πακέτο com.cyborg.core.web.utils.driverUtils; εισαγωγή org.openqa.selenium.WebDriver; εισαγωγή org.openqa.selenium.remote.DesiredCapabilities; εισαγωγή org.openqa.selenium.remote.RemoteWebDriver; εισαγωγή com.cyborg.core.generic.dataUtils.PropertiesDataUtils; εισαγωγή java.net.MalformedURLException; εισαγωγή java.net.URL; public class RemoteDriver υλοποιεί IDriver { DesiredCapabilities caps; String remoteHuburl=PropertiesDataUtils.configDataStore.get("WEB_GRID_IP"); @Override public WebDriver init(String browserName) { if (browserName != null) { switch (browserName) { case "firefox": try { return new RemoteWebDriver(new URL(remoteHuburl), caps.firefox()); } catch (MalformedURLException malformedUrlEx) { malformedUrlEx.getCause().getMessage(); malformedUrlEx.printStackTrace(); } case "chrome": try { return new RemoteWebDriver(new URL(remoteHuburl), caps.chrome()); } catch (MalformedURLException malformedUrlEx) { malformedUrlEx.getCause().getMessage(); malformedUrlEx.printStackTrace(); } case "ie": try { return new RemoteWebDriver(new URL(remoteHuburl), caps.internetExplorer()); } catch (MalformedURLException malformedUrlEx) { malformedUrlEx.getCause().getMessage(); malformedUrlEx.printStackTrace(); } προεπιλογή: δοκιμάστε { return new RemoteWebDriver(new URL(remoteHuburl), caps.chrome()); } catch (MalformedURLException malformedUrlEx) { malformedUrlEx.getCause().getMessage(); malformedUrlEx.printStackTrace(); } } return null; } else { return null; } }
Εδώ είναι η εφαρμογή της κλάσης Factory, η οποία παρέχει το αντίστοιχο αντικείμενο κλάσης προγράμματος περιήγησης και προγράμματος οδήγησης:
πακέτο com.cyborg.core.web.utils.driverUtils; public class DriverProvider { public IDriver getDriver(String typeOfDriver) { if (typeOfDriver != null) { switch (typeOfDriver) { case "local": return new LocalDriver(); περίπτωση "Remote": επιστροφή νέου RemoteDriver(); προεπιλογή: επιστροφή νέου LocalDriver(); } } else { return null; } }
Ομοίως, μπορείτε να εφαρμόσετε το Όπιο πρόγραμμα οδήγησης μαζί με τον ίδιο σχεδιασμό, απλώς παρέχετε την εφαρμογή και δηλώστε μια μέθοδο στις διεπαφές IDriver.
Συμπέρασμα: Με αυτό, καταλήγουμε εδώ πώς μπορείτε να χρησιμοποιήσετε μοτίβα σχεδιασμού γλώσσας ως μέρος των προτύπων σχεδιασμού και των βέλτιστων πρακτικών του Σεληνίου, ενώ αναπτύσσετε το υβριδικό πλαίσιο στο Σελήνιο. Στα επόμενα τμήματα του σεμιναρίου, θα δημιουργήσουμε το πλαίσιο μοντέλου Page Object για Selenium Automation.
Για να πάρετε το Συνολικό σεμινάριο για το Σελήνιο, μπορείτε να επισκεφθείτε εδώ.