Selenium RC/WebDriver - tests on IE in parallel

Всем привет.

стоит задача ускорить выполнение большого количества тестов распаралеливанием их выполнения. Рабочий браузер ИЕ, тест фреймворк основан на Selenium RC+TestNG, пробовали использовать стандартное распаралеливание testNG но с *iexploreproxy режимом у него проблемы, а желательно использовать именно его, поскольку обычные *iexplore режим плохо работает с некоторым функционалом продукта.

может быть у кого-то были подобные задачи и кто-то может поделится опытом?

P.S. также пробовали IEDriverServer+WebDriver, но он ооочень нестабилен.

 

можно написать свою запускалку с параллельным выполнением тестов

копайте в сторону BoundedThreadPoolExecutor

уже мысленно прорабатываю подобный вариант. Хотелось сначала узнать может есть готовые решения.

а как вы делали стандартное расспаралеливание? и какая именно у вас проблема возникла?

я так понимаю, что тесты запускались на одной машине просто в паралель

может быть вам тогда подумать в сторону использования grid и просто запускать эти же тесты просто на разных машинах (например виртуальных), чтобы небыло каких-то коллизий

да, тесты запускались на одной машине в параллель, и я подозреваю что метод основан на пуле потоков в testNG. выкладываю пример xml файла.

 

<suite name="Paralel test" parallel="tests" thread-count="3" verbose="1">
 
  <test name="1 Parallel test" preserve-order="true">
       <parameter name="myparam" value="blabla"/>
       <classes>
             <class name="AccountCreation"/>
               <class name="collectInfo"/>
            <class name="addInfo"/>
          </classes>
  </test>

  <test name="2 Parallel test" preserve-order="true">
       <parameter name="myparam" value="blablablah"/>
       <classes>
             <class name="AccountCreation"/>
               <class name="collectInfo"/>
            <class name="addInfo"/>
          </classes>
  </test>

  <test name="3 Parallel test" preserve-order="true">
       <parameter name="myparam" value="blablablahblah"/>
       <classes>
             <class name="AccountCreation"/>
               <class name="collectInfo"/>
            <class name="addInfo"/>
          </classes>
  </test>

</suite>

проблема заключается в следующем: поскольку используется RC то используем режим *iexploreproxy, поскольку он хорошо справляется с проблемой same origin policy, но в этом режиме тесты весьма нестабильные в параллели могут падать по таймауту не обнаружив нужного локатора.

Использовать грид это конечно вариант (и он также есть на карандаше), но хочется как говорится дешевле и малой кровью, без привлечения дополнительных ресурсов.

использование WebDriver'a с интернет експлорером в параллель отпадает поскольку он при снятии с себя фокуса моментально валится.

 

+ последняя проблема это <parameter name="myparam" для каждого тест пекеджа. он при паралельном запуске просто напросто берется рандомно один из трёх и подставляется в каждый пекедж.

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

может быть конечно, как вариант поискать на github, но не факт что можно будет такой готовый код уже найти

если уж не хочется возиться с гридом, тогда вам конечно надо смотреть в сторону многопоточности и делать любую программную логику какую вам необходимо

 

а какую версию webdriver и iddriver вы использовали, что у вас такие не стабильные результаты?

вытаскивал последний иедрайвер который был на гуглкод. поставил конфигурится кластер из парочки виртуалок, завтра продолжу бой. если получится то отпишусь как прошло.

с нетерпением ждем результатов :)

Поднял я грид кластер, вроде как все работает, но скорее всего либо из-за слабой конфигурации VM, либо из за удаленной работы тесты отрабатывают оооочень медленно, + все таки проблема с  <parameter name="myparam" для каждого тест пекеджа. он при паралельном запуске просто напросто берется рандомно один из трёх и подставляется в каждый пекедж.

 

а мне под каждый тест пакет нужно свой параметр подставлять.

 

в принципе как альтернативу мы уже сконфигурировали кластер для дженкинса, поидее будет не хуже чем в гриде.

 

кто-то может помочь с <parameter> тегом для тестов?

тут скорее всего происходит, что в один момент запуска тестов названия проперти одни и те же и ТестНГ выбирает первый попавшийся

 

хотя я попробовал этот же пример и у меня все работает

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="tests" thread-count="3" verbose="1">
    <test name="Test1" preserve-order="true">
        <parameter name="browser" value="firefox" />
        <parameter name="suite" value="Test1" />
        <classes>
            <class name="test.Test1" />
        </classes>
    </test>
    <test name="Test2" preserve-order="true">
        <parameter name="browser" value="chrome" />
        <parameter name="suite" value="Test2" />
        <classes>
            <class name="test.Test2" />
        </classes>
    </test>
    <test name="Test3" preserve-order="true">
        <parameter name="browser" value="explorer" />
        <parameter name="suite" value="Test3" />
        <classes>
            <class name="test.Test3" />
        </classes>
    </test>
</suite>

 

ну и код каждого теста выглядит вот так вот 

 

package test;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class Test1 {

<span style="color: rgb(128, 128, 48); ">@</span>Parameters<span style="color: rgb(128, 128, 48); ">(</span><span style="color: rgb(128, 0, 128); ">{</span><span style="color: rgb(0, 0, 230); ">"browser"</span><span style="color: rgb(128, 128, 48); ">,</span> <span style="color: rgb(0, 0, 230); ">"suite"</span><span style="color: rgb(128, 0, 128); ">}</span><span style="color: rgb(128, 128, 48); ">)</span>
<span style="color: rgb(128, 128, 48); ">@</span>Test
<span style="color: rgb(128, 0, 0); font-weight: bold; ">public</span> <span style="color: rgb(187, 121, 119); ">void</span> testA<span style="color: rgb(128, 128, 48); ">(</span><span style="color: rgb(128, 128, 48); ">@</span>Optional<span style="color: rgb(128, 128, 48); ">(</span><span style="color: rgb(0, 0, 230); ">"default browser"</span><span style="color: rgb(128, 128, 48); ">)</span> <span style="color: rgb(187, 121, 119); font-weight: bold; ">String</span> browser<span style="color: rgb(128, 128, 48); ">,</span> <span style="color: rgb(187, 121, 119); font-weight: bold; ">String</span> suite<span style="color: rgb(128, 128, 48); ">)</span> <span style="color: rgb(128, 0, 128); ">{</span>
    <span style="color: rgb(187, 121, 119); font-weight: bold; ">System</span><span style="color: rgb(128, 128, 48); ">.</span>out<span style="color: rgb(128, 128, 48); ">.</span>println<span style="color: rgb(128, 128, 48); ">(</span>suite<span style="color: rgb(128, 128, 48); ">+</span><span style="color: rgb(0, 0, 230); ">", "</span><span style="color: rgb(128, 128, 48); ">+</span>getClass<span style="color: rgb(128, 128, 48); ">(</span><span style="color: rgb(128, 128, 48); ">)</span><span style="color: rgb(128, 128, 48); ">.</span>getName<span style="color: rgb(128, 128, 48); ">(</span><span style="color: rgb(128, 128, 48); ">)</span><span style="color: rgb(128, 128, 48); ">+</span><span style="color: rgb(0, 0, 230); ">", "</span><span style="color: rgb(128, 128, 48); ">+</span>browser<span style="color: rgb(128, 128, 48); ">)</span><span style="color: rgb(128, 0, 128); ">;</span>
    assert <span style="color: rgb(128, 0, 0); font-weight: bold; ">true</span><span style="color: rgb(128, 0, 128); ">;</span>
<span style="color: rgb(128, 0, 128); ">}</span>

<span style="color: rgb(128, 128, 48); ">@</span>Parameters<span style="color: rgb(128, 128, 48); ">(</span><span style="color: rgb(128, 0, 128); ">{</span><span style="color: rgb(0, 0, 230); ">"browser"</span><span style="color: rgb(128, 128, 48); ">,</span> <span style="color: rgb(0, 0, 230); ">"suite"</span><span style="color: rgb(128, 0, 128); ">}</span><span style="color: rgb(128, 128, 48); ">)</span>
<span style="color: rgb(128, 128, 48); ">@</span>Test
<span style="color: rgb(128, 0, 0); font-weight: bold; ">public</span> <span style="color: rgb(187, 121, 119); ">void</span> testB<span style="color: rgb(128, 128, 48); ">(</span><span style="color: rgb(128, 128, 48); ">@</span>Optional<span style="color: rgb(128, 128, 48); ">(</span><span style="color: rgb(0, 0, 230); ">"default browser"</span><span style="color: rgb(128, 128, 48); ">)</span> <span style="color: rgb(187, 121, 119); font-weight: bold; ">String</span> browser<span style="color: rgb(128, 128, 48); ">,</span> <span style="color: rgb(187, 121, 119); font-weight: bold; ">String</span> suite<span style="color: rgb(128, 128, 48); ">)</span> <span style="color: rgb(128, 0, 128); ">{</span>
    <span style="color: rgb(187, 121, 119); font-weight: bold; ">System</span><span style="color: rgb(128, 128, 48); ">.</span>out<span style="color: rgb(128, 128, 48); ">.</span>println<span style="color: rgb(128, 128, 48); ">(</span>suite<span style="color: rgb(128, 128, 48); ">+</span><span style="color: rgb(0, 0, 230); ">", "</span><span style="color: rgb(128, 128, 48); ">+</span>getClass<span style="color: rgb(128, 128, 48); ">(</span><span style="color: rgb(128, 128, 48); ">)</span><span style="color: rgb(128, 128, 48); ">.</span>getName<span style="color: rgb(128, 128, 48); ">(</span><span style="color: rgb(128, 128, 48); ">)</span><span style="color: rgb(128, 128, 48); ">+</span><span style="color: rgb(0, 0, 230); ">", "</span><span style="color: rgb(128, 128, 48); ">+</span>browser<span style="color: rgb(128, 128, 48); ">)</span><span style="color: rgb(128, 0, 128); ">;</span>
    assert <span style="color: rgb(128, 0, 0); font-weight: bold; ">true</span><span style="color: rgb(128, 0, 128); ">;</span>
<span style="color: rgb(128, 0, 128); ">}</span>

<span style="color: rgb(128, 128, 48); ">@</span>Parameters<span style="color: rgb(128, 128, 48); ">(</span><span style="color: rgb(128, 0, 128); ">{</span><span style="color: rgb(0, 0, 230); ">"browser"</span><span style="color: rgb(128, 128, 48); ">,</span> <span style="color: rgb(0, 0, 230); ">"suite"</span><span style="color: rgb(128, 0, 128); ">}</span><span style="color: rgb(128, 128, 48); ">)</span>
<span style="color: rgb(128, 128, 48); ">@</span>Test
<span style="color: rgb(128, 0, 0); font-weight: bold; ">public</span> <span style="color: rgb(187, 121, 119); ">void</span> testC<span style="color: rgb(128, 128, 48); ">(</span><span style="color: rgb(128, 128, 48); ">@</span>Optional<span style="color: rgb(128, 128, 48); ">(</span><span style="color: rgb(0, 0, 230); ">"default browser"</span><span style="color: rgb(128, 128, 48); ">)</span> <span style="color: rgb(187, 121, 119); font-weight: bold; ">String</span> browser<span style="color: rgb(128, 128, 48); ">,</span> <span style="color: rgb(187, 121, 119); font-weight: bold; ">String</span> suite<span style="color: rgb(128, 128, 48); ">)</span> <span style="color: rgb(128, 0, 128); ">{</span>
    <span style="color: rgb(187, 121, 119); font-weight: bold; ">System</span><span style="color: rgb(128, 128, 48); ">.</span>out<span style="color: rgb(128, 128, 48); ">.</span>println<span style="color: rgb(128, 128, 48); ">(</span>suite<span style="color: rgb(128, 128, 48); ">+</span><span style="color: rgb(0, 0, 230); ">", "</span><span style="color: rgb(128, 128, 48); ">+</span>getClass<span style="color: rgb(128, 128, 48); ">(</span><span style="color: rgb(128, 128, 48); ">)</span><span style="color: rgb(128, 128, 48); ">.</span>getName<span style="color: rgb(128, 128, 48); ">(</span><span style="color: rgb(128, 128, 48); ">)</span><span style="color: rgb(128, 128, 48); ">+</span><span style="color: rgb(0, 0, 230); ">", "</span><span style="color: rgb(128, 128, 48); ">+</span>browser<span style="color: rgb(128, 128, 48); ">)</span><span style="color: rgb(128, 0, 128); ">;</span>
    assert <span style="color: rgb(128, 0, 0); font-weight: bold; ">true</span><span style="color: rgb(128, 0, 128); ">;</span>
<span style="color: rgb(128, 0, 128); ">}</span>    

}

и результаты которые я получил, как видите все правильно работает

 

Test2, test.Test2, chrome
Test1, test.Test1, firefox
Test3, test.Test3, explorer
Test2, test.Test2, chrome
Test1, test.Test1, firefox
Test3, test.Test3, explorer
Test1, test.Test1, firefox
Test2, test.Test2, chrome
Test3, test.Test3, explorer

какую версию ТестНГ вы используете? у меня 6.3.1

 

как выяснилось корень проблемы крылся в том что данные параметры были обьявлены как static поля и следовательно в качестве значения устанавливался параметр потоком который запускался последним. Поскольку ядро фреймворка писал не я, то на выяснение причины понадобилось поболее времени=)

 

правда после исправления вылезли очередные чудеса, с которыми буду разбиратся уже в понедельник.

ну хоть с этим уже разобрался :) и отлично!

проблему решили. 

 

как писал выше - статик переменные заменили на обычные + немного изменили реализацию инициализации параметров.

ну вот видишь, а ты говорил, тестНГ виноват :)

Доброго дня! Не хочется плодить темы, думаю в этой будет в самый раз  уточнить о параллельном запуске.

 

есть работающие тесты, написанные при помощи Java+Selenium WebDriver +Grid2 и запускаются параллельно в разных браузерах на удаленных и виртуальных машинах  по средствам xml файла .

а есть  работающие тесты, написанные на Java+Selenium Webdriver с использованием паттернов PageFactory и PageObject.  запускаются по одному  и не параллельно.

 а хочется запускать их параллелльно... попытки сваять сие с Grid 2 успехов не принесли .  наверное знаний маловато ...

поэтому вопрос : есть какие-то инные методы запустить параллельно подобные тесты?  а может и с Grid2 запускается все.. только не правильно что-то пишу))

если понадобится -могу код показать.

 

 

как и с помощью чего вы уже пытались реализовать параллелизацию? 

какие у вас возникли проблемы?

 

в общем, тесты запускаются параллельно с помощью testng например

1) Использую следующие инструмменты: Selenium WebDriver

Grid 2,  тесты на Java при помощи PageFactory описаны , использую Test NG для запуска тестов.

2) есть интернет магазин.

-домашняя страница, страница заказа, страница логирования, страница заказов, детализация заказов. под каждую страницу свой класс с элементами и методами.

- действия по тесту: вход на homepage - переход на страницу заказа -выбор опций на странице (ввод данных) - переход на страницу потверждения заказа -логирование на сайт- вход на страницу заказов- выбор заказаа и переход на его страницу- отсылка сообщения мменеджеру- логаут.

3) помимо классов-страниц, есть файл конфигурации (url browser и др. параметры) и классы тестов.

есть базовый тестовый класс, в котром описана инициализация браузеров , какой url открывать , какие исклчюения проверять .

4) есть xml файл в котором расписано кого куда запускать.

5) есть включенный хаб и две ноды (одна из них удаленная машина )

 если я запускаю просто тесты на java webdriver при помощи xml файла  - все работает. а вот с вариантом pagefactory как-то не очень идет.

я понимаю, что не получается собрать воедино xml файл и сам тест.  точнее , чтоб тест выполнялся .должно все работать в базовом..... ошибки от Eclipse конечно помогают, но Java не тот язык с которым я в  ладах. ..

вообщем ниже привожу пример кода, который используется.

//////////////////////////XML Файл :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Same TestCases on Different Browser" verbose="3"  parallel="tests" thread-count="2">   
 <test name="Test1" preserve-order="true">
 <parameter name="browser"  value="chrome"/>
    <classes>
      <class name="test.LoginTestGrid"/>
        </classes>
    </test>
      
      <test name="Test2" preserve-order="true">
 <parameter name="browser"  value="firefox"/>
    <classes>
      <class name="test.LoginTestGrid"/>
    </classes>
     </test>      
</suite>

//////////////////////////////////////////LoginTest (то, что непосредственно должно происходить)

package test;

import org.openqa.selenium.support.PageFactory;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.Test;

import page.CheckoutPage;
import page.ClientPage;
import page.HomePage;
import page.LoginPage;
import page.OrderNowPage;
import page.OrdersPage;

public class LoginTestGrid extends BasicTestCaseGrid{

    private HomePage homePage = PageFactory.initElements(getWebDriver(), HomePage.class);
    private OrderNowPage orderNowPage;
    private CheckoutPage checkoutPage;
    private LoginPage loginPage;
    private ClientPage clientPage;
    private OrdersPage orderPage;
    
        
    @Test
    //public void testUntitled() throws Exception {
    public void testUntitled() throws InterruptedException {
        Thread.sleep(3000);        
        homePage.open();
        orderNowPage = homePage.ordernow();
        orderNowPage = orderNowPage.chooseStandard();
        orderNowPage = orderNowPage.chooseOption();
        orderNowPage = orderNowPage.orderdata(data);
        checkoutPage = orderNowPage.submit();
        loginPage = checkoutPage.loginAs();
        clientPage = loginPage.loginUser(admin);
        orderPage = clientPage.ordersPage();
        orderPage = orderPage.answer(newone);
        }
    
    
    @AfterSuite(alwaysRun = true)
    public void tearDown() throws Exception {
        driver.close();
        
    }       }

//////////////////////////////////////////////////// BaseTest

public class BasicTestCaseGrid {
    
protected  WebDriver driver;
protected  URL nURL ;


   /* данные, которые используются в тесте*/
    
    
    @BeforeClass(alwaysRun = true)  // в этом месте где-то кроется проблема т.к при записи приведенной здесь, мне выпдает ошибка в классе Test в  первой же строке, где упоминается getwebdriver  

@Parameters({"browser"})
    
    protected WebDriver getWebDriver(String browser) {
            

        if (driver != null) {
            return driver;
        }
         DesiredCapabilities capability = null;
        
        if(browser.equals("firefox")){
            System.out.println("firefox");
            capability= DesiredCapabilities.firefox();
            capability.setBrowserName("firefox");
            capability.setPlatform(org.openqa.selenium.Platform.ANY);
                                        
        } else if (browser.equals("chrome")) {
            System.out.println("chrome");
            capability= DesiredCapabilities.chrome();
            capability.setCapability("chrome.switches", Arrays.asList("--start-maximized"));
            capability.setBrowserName("chrome");
            capability.setPlatform(org.openqa.selenium.Platform.WINDOWS);
                 
        }  else if (browser.equals("ie")) {
       
            System.out.println("ie");
            capability= DesiredCapabilities.internetExplorer();
            capability.setBrowserName("ie");
            capability.setPlatform(org.openqa.selenium.Platform.WINDOWS);
        }
       
        try
        {
            nURL = new URL("http://localhost:4444/hub");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        driver = new RemoteWebDriver(nURL, capability);
        driver.navigate().to(ConfigPropertiesGrid.getProperty("login.url"));
        
        // Implicit Waiting
        driver.manage().timeouts().implicitlyWait(Long.parseLong(ConfigProperties.getProperty("imp.wait")), TimeUnit.SECONDS);
        
        return driver;
    }
    
    
    @AfterSuite(alwaysRun = true)
    public void tearDown() throws Exception {
        driver.close();
    }  
}

 

может здесь что-то совсем глупо выглядит. .. просветите, пожалуйста, темных)

надо идти пошагово

вы пытались запускать тесты в параллель?

какие проблемы у вас возникли?

+ если вы хотите начать параллелизировать тесты, лучше делать последовательные шаги

запускать сначала паралельно классы (это самое простое), решить все проблемы которые возникают

а потом уже переключаться на параллелизацию тестов и методов