~~18/11/29 Wenn Sie Selenide auf die neueste Version (ver5-Serie) aktualisieren, funktioniert dies nicht. Es ist besser, die neueste Version zu verwenden, daher werde ich sie später beheben. ~~ 18/12/03 Ich habe nur Chrome ausprobiert und den Programmcode aktualisiert. IE usw. bleibt wie in der Beschreibung von functions.json.
Sofortige Qualitätssicherung: unschuldig: Um die aktuelle Situation, in der Regressionstests einige Zeit in Anspruch nehmen, schrittweise zu verbessern, haben wir eine Umgebung erstellt, um Systemtests zu automatisieren, die wiederholt dasselbe tun. Ich habe diese Aufzeichnung.
Ich habe nicht aufgezeichnet, wie der Test ausgeführt wird, da es besser ist, auf Pitalium Tutorial zu verweisen.
Dies ist die zur Überprüfung verwendete Software. Alles war großartig. Sie können mit Selenium Grid (Hub, Node-Konfiguration) mit Pitalium testen. Ich erstelle eine Verifizierungsversion unter Windows.
Sanft | Ausführung | Verwenden |
---|---|---|
java | 1.8.0_191 | |
Pitalium | 1.2.4 | Wird als Basis verwendet |
Selenide | 5.0.1 | Wird nur mit PageObject verwendet |
selenium-server-standalone.jar | 3.141.59 | |
chromedriver.exe | 2.44 |
Fahren Sie mit Pitalium Tutorial fort, um eine Testausführungsumgebung zu erstellen.
18/04/23 ClassNotFound kann in CI (Jenkins) vorkommen, daher habe ich es in Maven geändert. Der Bereich ist kein Test, da wir ihn in einem Testprojekt versuchen.
pom.xml
<project xmlns="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">
<modelVersion>4.0.0</modelVersion>
<groupId>Autotest</groupId>
<artifactId>Autotest</artifactId>
<version>0.0.1</version>
<build>
<sourceDirectory>src</sourceDirectory>
<testSourceDirectory>src</testSourceDirectory>
<resources>
<resource>
<directory>resource</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>resource</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.htmlhifive</groupId>
<artifactId>pitalium</artifactId>
<version>1.2.4</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.codeborne</groupId>
<artifactId>selenide</artifactId>
<version>5.0.1</version>
<exclusions>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-api</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-remote-driver</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-support</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0.1-jre</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.8.0-beta2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
<file.encoding>UTF-8</file.encoding>
<project.build.sourceEncoding>${file.encoding}</project.build.sourceEncoding>
<project.reporting.outputEncoding>${file.encoding}</project.reporting.outputEncoding>
<maven.compiler.encoding>${file.encoding}</maven.compiler.encoding>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>
</project>
Meine Umgebung sieht folgendermaßen aus: Aufgrund des später beschriebenen Problems wurde der IE schließlich separat in einem anderen Knoten gestartet.
java -jar selenium-server-standalone-3.141.59.jar -role hub
NodeConfigBrowser.json
{
"capabilities": [
{
"platform": "WINDOWS",
"browserName": "firefox",
"maxInstances": 2,
"seleniumProtocol": "WebDriver"
},
{
"platform": "WINDOWS",
"browserName": "chrome",
"maxInstances": 3,
"seleniumProtocol": "WebDriver"
},
{
"platform": "WINDOWS",
"browserName": "internet explorer",
"maxInstances": 1,
"seleniumProtocol": "WebDriver"
}
],
"hub": "http://XXX.XXX.XXX.XXX:4444/grid/register",
"register": true
}
java -Dwebdriver.ie.driver=IEDriverServer.exe -Dwebdriver.chrome.driver=chromedriver.exe -Dwebdriver.gecko.driver=geckodriver.exe -jar selenium-server-standalone-3.141.59.jar -role node -nodeConfig NodeConfigBrowser.json
Die Verzeichnisstruktur kann sich ändern, aber vorerst habe ich es mit der folgenden Struktur gemacht.
--Seitenpaket
Vom Klang des PageObject-Musters angezogen, habe ich beschlossen, vorerst einen Bildschirm mit einem Objekt zu erstellen. Ich benutze hier Selenide.
~~ Da die Generierung von WebDriver Pitalium überlassen bleibt, habe ich eine übergeordnete Klasse erstellt und WebDriver im Konstruktor an Selenide übergeben. ~~ 18/12/03 Die neueste Version von Selenide (ver5-Serie) hatte hier ein Problem. Geändert, um den Treiber anzugeben, der von Selenide nur einmal in der übergeordneten Testfallklasse verwendet werden soll.
PageBase.java
package page;
import com.htmlhifive.pitalium.core.config.PtlTestConfig;
/**
*Übergeordnete Seitenklasse für die allgemeine Verarbeitung wie Kopf- und Fußzeilen in Seiten
*/
public abstract class PageBase {
/**Basis-URL beginnend mit http oder https*/
protected final String _BASE_URL = PtlTestConfig.getInstance().getTestAppConfig().getBaseUrl();
/*********************************
*Gemeinsame Bedienung
*********************************/
}
Der Grund, warum der Klassenname usw. auf Japanisch ist, wird später beschrieben.
Einloggen.java
package page;
import static com.codeborne.selenide.Selenide.*;
public class __Der Anmeldebildschirm erweitert PageBase{
public static final String _URL = "/login";
/*********************************
*Wähler
*********************************/
//Konto-ID
private static final String _ACCOUNT_TXT_CSS = "#accountID";
//Passwort
private static final String _PASS_TXT_CSS = "#password";
//Anmeldeschaltfläche
private static final String _LOGIN_BTN_CSS = "#login";
/*********************************
*Operation
*********************************/
public __Anmeldebildschirm__Geben Sie Ihre Konto-ID ein(String s) {
$(_ACCOUNT_TXT_CSS).setValue(s);
return this;
}
public __Anmeldebildschirm__Passwort eingeben(String s) {
$(_PASS_TXT_CSS).setValue(s);
return this;
}
public __Anmeldebildschirm__Klicken Sie auf die Schaltfläche Anmelden() {
$(_LOGIN_BTN_CSS).click();
return this;
}
}
Erstellt durch Erben der Pitalium-Klasse. Wir führen Testoperationen und Bildvergleiche durch.
Wieder entschied ich mich, vorerst eine Elternklasse als Basis einzurichten.
TestBase.java
package test;
import java.util.Locale;
import org.junit.Before;
import org.junit.Rule;
import com.codeborne.selenide.Configuration;
import com.codeborne.selenide.WebDriverRunner;
import com.codeborne.selenide.commands.Commands;
import com.codeborne.selenide.junit.TextReport;
import com.google.common.base.Strings;
import com.htmlhifive.pitalium.core.PtlTestBase;
import com.htmlhifive.pitalium.core.model.ScreenshotArgument;
import custom.SetValueCustomize;
public abstract class TestBase extends PtlTestBase {
/**Selenid-Leistungsbericht*/
@Rule
public TextReport report = new TextReport();
private int _ssCount = 1;
@Override
@Before
public void setUp() {
super.setUp();
//Ersetzt durch den Befehl, der die Verarbeitung für IE hinzugefügt hat
Commands.getInstance().add("setValue", new SetValueCustomize(Strings.nullToEmpty(capabilities.getBrowserName()).toLowerCase(Locale.ENGLISH)));
//Stellen Sie das Zeitlimit für die Elementsuche auf 10 Sekunden und den Selenide-Treiber ein
Configuration.timeout = 10000;
WebDriverRunner.setWebDriver(driver);
//Die Standardeinstellung ist keine Ausgabe eines Leistungsberichts
report.onSucceededTest(false);
report.onFailedTest(false);
//Vorverarbeitung der Testausführung
init();
}
/**
*Vorverarbeitung der Testausführung
*/
protected void init() {};
/**
*Aktivieren Sie die Selenide-Leistungsberichterstattung
*/
protected void enablePerfReport() {
report.onSucceededTest(true);
report.onFailedTest(true);
}
/**
*Stellen Sie fest, ob es sich um einen Chrome-Browser handelt
* @return true:Chrome
*/
protected boolean isChrome(){
return "chrome".equals(Strings.nullToEmpty(capabilities.getBrowserName()).toLowerCase(Locale.ENGLISH)) ? true : false;
}
/**
*Stellen Sie fest, ob es sich um einen Edge-Browser handelt
* @return Edge
*/
protected boolean isEdge(){
return "MicrosoftEdge".equals(Strings.nullToEmpty(capabilities.getBrowserName()).toLowerCase(Locale.ENGLISH)) ? true : false;
}
/**
*Beurteilung, ob es sich um einen IE-Browser handelt
* @return IE
*/
protected boolean isIE(){
return "internet explorer".equals(Strings.nullToEmpty(capabilities.getBrowserName()).toLowerCase(Locale.ENGLISH)) ? true : false;
}
/**
*Mache ein Bildschirmfoto
*/
protected void screenShotAndVerifyView() {
screenShotAndVerifyView("image");
}
/**
*Mache ein Bildschirmfoto
* @param Screenshotname
*/
protected void screenShotAndVerifyView(String screenName) {
ScreenshotArgument arg = ScreenshotArgument.builder(screenName + _ssCount).addNewTarget().build();
assertionView.verifyView(arg);
_ssCount++;
}
}
LoginTest.java
package test;
import org.junit.Test;
import page.__Anmeldebildschirm;
public class LoginTest extends TestBase {
@Test
public void loginOK() throws Exception {
driver.get(__Anmeldebildschirm._url);
__Anmeldebildschirmseite= new __Anmeldebildschirm();
page.__Geben Sie Ihre Konto-ID ein("user")
.__Passwort eingeben("password")
.__Klicken Sie auf die Schaltfläche Anmelden();
assertionView.assertView("loginOK");
}
}
Da einige Mitglieder des Testteams nur ungern horizontale Zeichen sagen, haben wir beschlossen, alle Klassen und Methoden im Zusammenhang mit Bildschirmoperationen auf Japanisch zu schreiben.
Darüber hinaus ist die Bildschirmbedienungsmethode so konzipiert, dass Kandidaten mit zwei Unterbalken leicht eingegrenzt werden können.
Ich denke, dass der Schwellenwert hoch ist, weil es niemanden gibt, der Erfahrung in der Codierung von Qualität hat. Deshalb möchte ich mit der Seitenklasse in der Entwicklung fortfahren.
Seitenklasse: Schreiben von Entwicklungscode Testklasse: Qualität & Testteam codiert
Ich glaube nicht, dass ich große Probleme mit der Operation hatte, die ich durchführen möchte: Umarmen: IE und Teme sind jedoch nicht gut.
Ich kenne den Grund nicht, aber das Phänomen, dass die Eingabe nur im IE fehlschlägt, tritt auf. Im IE gibt es viele Informationen, wie zum Beispiel, dass es besser ist, Steuerelemente im Voraus zu platzieren und zu klicken. Deshalb habe ich es nicht verstanden und beschlossen, alles zu tun: rollende_eyes: Entspricht dem Vorgang der Eingabe mit Selenide durch Einhaken (um genau zu sein, kann es ersetzt werden).
SetValueCustomize.java
package common;
import java.io.IOException;
import org.openqa.selenium.Keys;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebElement;
import com.codeborne.selenide.Configuration;
import com.codeborne.selenide.SelenideElement;
import com.codeborne.selenide.commands.Commands;
import com.codeborne.selenide.commands.SetValue;
import com.codeborne.selenide.impl.WebElementSource;
/**
*SetValue-Ersatzklasse
*Der Unterschied ist die individuelle Entsprechung von IE
*/
public class SetValueCustomize extends SetValue {
private boolean _ieFlg;
public SetValueCustomize(String _browserName) {
_ieFlg = "internet explorer".equals(_browserName) ? true : false;
}
@Override
public WebElement execute(SelenideElement proxy, WebElementSource locator, Object[] args) {
WebElement element = locator.findAndAssertElementIsVisible();
if (Configuration.versatileSetValue
&& "select".equalsIgnoreCase(element.getTagName())) {
return super.execute(proxy, locator, args);
}
if (Configuration.versatileSetValue
&& "input".equalsIgnoreCase(element.getTagName()) && "radio".equals(element.getAttribute("type"))) {
return super.execute(proxy, locator, args);
}
if (_ieFlg) {
element.sendKeys(Keys.CONTROL);
try {
Commands.getInstance().execute(proxy, locator, "click", null);
} catch (IOException e) {
throw new NoSuchElementException("IE Click error in SetValueCustomize", e);
}
}
return super.execute(proxy, locator, args);
}
}
Ersetzen Sie den erstellten Befehl im Voraus durch die übergeordnete Testklasse.
TestBase.java
public abstract class TestBase extends PtlTestBase {
@Override
@Before
public void setUp() {
super.setUp();
//Ersetzt durch den Befehl, der die Verarbeitung für IE hinzugefügt hat
Commands.getInstance().add("setValue", new SetValueCustomize(Strings.nullToEmpty(capabilities.getBrowserName()).toLowerCase(Locale.ENGLISH)));
}
}
Wenn die setValue-Methode in verschiedenen Seitenklassen aufgerufen wird, wird die dem angegebenen Methodennamen zugeordnete Klasse aus der Befehlskarte in Selenide abgerufen und die Ausführung aufgerufen.
Einloggen.java
public class login erweitert PageBase{
öffentliches Login__Geben Sie Ihre Login-ID ein(String id) {
$("#account").setValue(id);
return this;
}
}
Lass die Maus wie sie ist! Es schien, als würde es nicht gelöst werden, selbst wenn ich schrie, also ging ich damit um, indem ich die Fähigkeiten mit se: ieOptions spezifizierte.
capabilities.json
[
{
"browserName": "internet explorer",
"se:ieOptions" : {
"enablePersistentHover" : true,
"requireWindowFocus" : true
}
}
]
Aus diesen Gründen wurde willkürlich entschieden, einen Knoten (Terminal) vorzubereiten, der dem IE gewidmet ist und der nur einen Prozess startet und den Betrieb oder die Entfernung von anderen nicht zulässt: unschuldig:
NodeConfigBrowser.json
{
"capabilities": [
{
"platform": "WINDOWS",
"browserName": "internet explorer",
"maxInstances": 1,
"seleniumProtocol": "WebDriver"
}
],
"hub": "http://XXXXX:4444/grid/register",
"register": true
}
Firefox hat versucht, Funktionen mit moz: FirefoxOptions --prefs festzulegen, aber es hat nicht funktioniert. Deshalb habe ich beschlossen, keinen anderen Test als Chrome herunterzuladen: unschuldig:
capabilities.json
[
{
"browserName": "firefox",
"moz:firefoxOptions": {
"prefs": {
"browser.download.folderList": 0,
"browser.download.useDownloadDir": true,
"browser.helperApps.neverAsk.saveToDisk": "text/*,application/*",
"browser.helperApps.alwaysAsk.force": false,
"browser.download.manager.closeWhenDone": true,
"pdfjs.enabledCache.state": false
}
}
}
]
Recommended Posts