Sie verwenden also TestNG. Dieses Testframework unterstützt das parallele Ausführen von Builds (eine Einstellung, die Sie einer Suite-Datei hinzufügen oder auf andere Weise festlegen können). Sie können auch Argumente für eine Testmethode verwenden, die DataProvider
verwendet. Es gibt viele, viele Möglichkeiten, ein Test-Framework zu erstellen, und es gibt viele Faktoren, die in seine Struktur einfließen sollten.
Als Erstes erstellen Sie eine statische WebDriver-Instanz in der Driver
-Klasse, die nicht das ist, was Sie wollen. Sie benötigen mehrere Instanzen. Was Sie also wirklich wollen, ist die Factory-Methode für diese Klasse, mit der Sie WebDrivers für jede Methode nach Bedarf erstellen können. Eine weitere Überlegung, die Sie berücksichtigen sollten, ist die Tatsache, dass TestNG keine neuen Instanzen des Testklassenobjekts für jede Methode erstellt. Aus diesem Grund können Sie entweder keinen Zustand als ein Feld auf dem Testklassenobjekt speichern, es sei denn, dies geschieht in einer Weise, die eine Konkurrenz vermeidet (z. B. ein Feld ThreadLocal
). Leider werden Sie im Fall eines Selenium-Tests den WebDriver beenden müssen, wenn Sie damit fertig sind, um die SozeLabs-Ressourcen freizugeben. Normalerweise können Sie das mit einer Konfigurationsmethode @AfterMethod
tun, aber Sie können nicht garantieren, dass die Konfigurationsmethoden im selben Thread wie die Testmethode ausgeführt werden, so dass die Verwendung eines ThreadLocal
Feldes nicht den Zugriff auf das gleiche Argument ermöglicht (z. B. die Webtreiber). Sie könnten eine Karte von Testmethoden für Webtreiber auf dem Klassenobjekt verwenden (TestNG ermöglicht es Ihnen, die Testmethode als Argument zu injizieren), aber im Falle eines Datenproviders, der mehrere OS/Browser-Kombinationen zulässt, wird es den gleichen Test haben Methode auch. Am Ende mit TestNG und Selen finde ich es am besten (oder zumindest am einfachsten), nach meiner Erfahrung DataProvider zu verwenden und die Felder nur auf dem Testklassenobjekt zu speichern und die Parallelität auf Klassenebene einzuschränken.
Dies gesagt, hier ist ein Beispiel dafür, wie man mit parallelen Methoden das testen. Beginnend mit einem einfachen pom.xml
Abhängigkeitsbereich, um die für dieses Beispiel verwendeten Versionen zu zeigen. Auch wenn Ihre Versionen ein wenig anders sind, sollte es sehr ähnlich sein.
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.53.1</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.9.10</version>
</dependency>
</dependencies>
Aktualisieren Sie die Driver
Klasse um sicherzustellen, dass es wieder sauber eine neue Treiber-Instanz jedes Mal. Ich habe die Logger-Teile entfernt, nur um Platz zu sparen. Ich habe es auch einfach nicht-instanziierbar gemacht, da es eigentlich nur eine statische Fabrik ist und Instanzen davon nicht sinnvoll erscheinen lassen. Außerdem sollten Sie wahrscheinlich keinen Zugriff auf Dinge wie den Namen und den Schlüssel erlauben, da es sich um reine Implementierungsdetails handelt.
public final class Driver {
private static final String USERNAME = "name";
private static final String ACCESS_KEY = "key";
public static WebDriver createDriver(String browser, String version, String os) {
// Should probably validate the arguments here
try {
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.BROWSER_NAME, browser);
capabilities.setCapability(CapabilityType.VERSION, version);
capabilities.setCapability(CapabilityType.PLATFORM, os);
return new RemoteWebDriver(new URL("http://" + USERNAME + ":" + ACCESS_KEY + "@ondemand.saucelabs.com:80/wd/hub"),
capabilities);
} catch (MalformedURLException e) {
throw new RuntimeException("Failure forming the URL to create a web driver", e);
}
}
private Driver() {
throw new AssertionError("This is a static class and shouldn't be instantiated.");
}
}
Schließlich müssen Sie in der Testklasse selbst die eigentliche Testmethode und einen Datenprovider definieren. Wenn Sie denselben Datenprovider für mehrere Tests/Testklassen benötigen, ist das in Ordnung.Wenden Sie sich an die TestNG Dokumentation:
http://testng.org/doc/documentation-main.html#parameters-dataproviders
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class FooTest {
@DataProvider(name = "DriverInfoProvider", parallel = true) // data providers force single threaded by default
public Object[][] driverInfoProvider() {
return new Object[][] {
{ "firefox", "47.0", "Windows 10" },
{ "chrome" , "51.0", "Windows 10" },
// etc, etc
};
}
@Test(dataProvider = "DriverInfoProvider")
public void testFoo(String browser, String version, String os) {
WebDriver driver = Driver.createDriver(browser, version, os);
try {
// simple output to see the thread for each test method instance
System.out.println("starting test in thread: " + Thread.currentThread().getName());
// Putting this in a try catch block because you want to be sure to close the driver to free
// up the resources even if the test fails
driver.get("https://www.google.com");
driver.findElement(By.name("q")).sendKeys("Hello, world");
} finally {
driver.quit();
}
}
}
Bitte beachten Sie, dass es eine Reihe von Dingen, über diese Beispiele sind, die ich nicht von einer Architektur Standpunkt mag, aber ich wollte Ihnen eine geben Vorstellung einiger der zu bedenkenden Probleme und ein schnelles Arbeitsbeispiel, das dem ähnlich ist, was Sie bereits haben. Um schließlich Testklassen parallel auszuführen, würden Sie eine TestNG-Suite erstellen und dann ausführen. Diese sind normalerweise in XML definiert (Sie können jedoch auch YAML verwenden).
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="MySuiteNameHere" parallel="methods" thread-count="15">
<test name="Selenium Tests">
<classes>
<class name="foo.bar.FooTest"/>
</classes>
</test>
</suite>
schließlich, dass die Führung auf zwei Tests ausgeführt wird, die Google geladen und ausgeführt, um die Aktion zusammen mit dieser Beispielausgabe:
starting test in thread: PoolService-1
starting test in thread: PoolService-0
Sie diese Frage google Haben? Hast du ihr Hilfe-Wiki gelesen? – JeffC
Ist das eine ernste Frage? Ja, ich habe es gegoogelt. Ja, ich habe das Wiki angesehen. Ich bin nicht in der Lage, es herauszufinden, weshalb ich die Frage gestellt habe. – TestRaptor
Ja, es ist eine ernste Frage. Wenn ich deine Frage googlen und Antworten in weniger als 60s finden kann, frage ich allgemein, ob der Fragesteller sich die Mühe gemacht hat, seine eigene Frage zu googeln. Hast du diesen Artikel mit dem Titel [Tests parallel ausführen] (https://wiki.saucelabs.com/display/DOCS/Java+Test+Setup+Example#JavaTestSetupExample-RunningTestsinParallel) auf dem Socelabs-Wiki gelesen? Es scheint, als würde es das haben, wonach du suchst. Wenn nicht, was fehlt? – JeffC