2016-07-27 3 views
-2

Я создал общий класс webdriver, который я могу использовать для своих тестов на селен. Всякий раз, когда я создаю новый тест, я получаю webdriver из этого класса.Подключить тест Selenium к SauceLabs

Вот что я использую, чтобы создать мой водитель

package com.atmn.config; 

import java.net.MalformedURLException; 
import java.net.URL; 
import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 
import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.remote.CapabilityType; 
import org.openqa.selenium.remote.DesiredCapabilities; 
import org.openqa.selenium.remote.RemoteWebDriver; 

public class Driver { 


    private static Log log = LogFactory.getLog(Driver.class); 
    public static String USERNAME = "name"; 
    public static String ACCESS_KEY = "key"; 

    public static WebDriver driver = createDriver("firefox", "47.0", "Windows 10"); 

    public static WebDriver createDriver(String browser, String version, String os) { 

     try{ 
      DesiredCapabilities capabilities = new DesiredCapabilities(); 
      capabilities.setCapability(CapabilityType.BROWSER_NAME, browser); 
      capabilities.setCapability(CapabilityType.VERSION, version); 
      capabilities.setCapability(CapabilityType.PLATFORM, os); 

      // Launch remote browser and set it as the current thread 
      return new RemoteWebDriver(
        new URL("http://"+USERNAME+":"+ACCESS_KEY+"@ondemand.saucelabs.com:80/wd/hub"), 
        capabilities); 
     } 
     catch(MalformedURLException e) 
     { 
      e.printStackTrace(); 
      //log message 
      log.info(e.getMessage()); 
     } 
     return null; 
    } 

Вот мой тест, который будет работать на SauceLabs использовать для Windows 10 и Firefox 47.

package com.atmn.tests; 

import com.tplus.atmn.tasks.CommonTasks; 
import com.tplus.atmn.objects.TOA6; 
import java.lang.reflect.Method; 
import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 
import org.openqa.selenium.By; 
import org.testng.Assert; 
import org.testng.annotations.DataProvider; 
import org.testng.annotations.Test; 
import com.tplus.atmn.tasks.HttpRequest; 


public class Testing extends CommonTasks { 

    private static Log log = LogFactory.getLog(TB6_TOA.class); 


    @Test (groups = {"Testing"}) 
    public static void endToEnd() throws Exception { 


     //Load URL 
     HttpRequest http = new HttpRequest(); 
     String URL = http.internetWebAddress(); 
     driver.get(URL); 


     //Page 1 
      // Item Text 
     verifyText(Object.ItemText, "Multiple Choice - Single Answer Radio - Vertical"); 
     verifyText(Object.Progress_PercentComplete, "0%"); 
      //URL 
     verifyNoRedirect(); 
      //Go to next page 
     driver.findElement(Object.Start).click(); 
     System.out.println("Next Button was clicked."); 

} 
} 

Вместо того, чтобы просто бежать мое тест в 1 браузере в SauceLabs, я хочу запустить этот тест на нескольких комбинациях браузера/ОС параллельно. Я не уверен, как изменить класс драйвера, чтобы это произошло.

+0

ли вы Google на этот вопрос? Вы читали их вики помощи? – JeffC

+0

Это серьезный вопрос. Да, я искал ее. Да, я посмотрел на вики. Я не могу понять это, поэтому я разместил вопрос. – TestRaptor

+0

Да, это серьезный вопрос. Когда я смогу ответить на ваш вопрос и найти ответы менее чем за 60-е годы, я обычно спрашиваю, беспокоился ли он, чтобы он ответил на свой вопрос. Вы прочитали эту статью под названием [Running Tests in Parallel] (https://wiki.saucelabs.com/display/DOCS/Java+Test+Setup+Example#JavaTestSetupExample-RunningTestsinParallel) в вики Saucelabs? Похоже, у него будет то, что вы ищете. Если нет, чего не хватает? – JeffC

ответ

0

Значит, вы используете TestNG. Эта тестовая платформа поддерживает параллельную работу (это параметр, который вы можете добавить в файл пакета, а также другим способом). Он также позволяет принимать аргументы в методе тестирования с использованием DataProvider. Существует множество способов создания тестовой среды, и есть много факторов, которые должны учитывать то, как она структурирована.

Во-первых, вы создаете статический экземпляр WebDriver в классе Driver, который не то, что вам нужно. Вам нужно несколько экземпляров, поэтому то, что вам действительно нужно, это фабричный метод в этом классе, который позволяет вам создавать WebDrivers для каждого метода по мере необходимости. Еще одно соображение, которое вы хотите учесть, - это тот факт, что TestNG не создает новые экземпляры объекта тестового класса для каждого метода. Из-за этого вы либо не можете сохранять какое-либо состояние в качестве поля объекта тестового класса, если оно не выполняется таким образом, чтобы избежать конфликтов (например, поле ThreadLocal). К сожалению, в случае теста Selenium вам захочется выйти из WebDriver, когда вы закончите с ним, чтобы освободить ресурсы SauceLabs. Обычно вы можете это сделать с помощью метода конфигурации @AfterMethod, но вам не гарантируется, что методы настройки будут выполняться в том же потоке, что и метод тестирования, поэтому использование поля ThreadLocal не будет работать, чтобы разрешить доступ к одному и тому же аргументу (например, веб-драйвер). Вы можете использовать карту методов тестирования для веб-драйверов на объекте класса (TestNG позволяет вам вводить тестовый метод в качестве аргумента), но в случае поставщика данных, позволяющего использовать несколько комбинаций OS/браузера, он будет иметь те же тесты метод также. В конце концов с TestNG и Selenium я считаю, что лучше всего (или, по крайней мере, проще) использовать DataProviders и просто хранить поля в объекте тестового класса и ограничивать параллелизм уровнем класса.

Это, как говорится, пример того, как тестировать с помощью параллельных методов, которые. Начиная с простого раздела зависимости pom.xml, чтобы показать версии, используемые для этого примера. Даже если ваши версии немного разные, это должно быть очень похоже.

<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> 

Обновления Driver класса, чтобы убедиться, что чисто возвращает новый экземпляр драйвера каждый раз. Я удалил части регистратора, чтобы сохранить некоторое пространство. Я также просто сделал его неинтуитивным, поскольку он действительно является только статической фабрикой и позволяет экземплярам этого не имеет смысла. Также вы, вероятно, не должны допускать доступ к таким вещам, как имя и ключ, поскольку они являются исключительно деталями реализации.

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."); 
    } 
} 

Наконец, в самом тестовом классе вам необходимо определить фактический метод тестирования и поставщик данных. Если вам нужен один и тот же поставщик данных для нескольких тестов/тестовых классов, это нормально.Обратитесь к документации TestNG для деталей:

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(); 
     } 
    } 
} 

Пожалуйста, обратите внимание, что есть ряд вещей об этих примерах, что мне не нравится с архитектурной точки зрения, но я хотел бы дать вам идея нескольких вопросов, о которых стоит подумать, и быстрый рабочий пример, похожий на то, что у вас уже есть. Наконец, чтобы параллельно запускать тестовые классы, вы должны создать, а затем запустить набор TestNG. Они обычно определяются в XML (хотя вы также можете использовать YAML).

<!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> 

Наконец работает, что приводит к двум тестам, которые загружены в Google и выполняются действия, наряду с этим выходом образца:

starting test in thread: PoolService-1 
starting test in thread: PoolService-0 
Смежные вопросы