Есть отличная удаленная работа для php+codeception+jenkins+allure+docker спецов. 100% remote! Присоединиться к проекту

selenide не передается драйвер в Before suite/test

remote
selenide
selenium
webdriver
testng
java
Теги: #<Tag:0x00007f7b64cbca50> #<Tag:0x00007f7b64cbc7d0> #<Tag:0x00007f7b64cbc640> #<Tag:0x00007f7b64cbc4d8> #<Tag:0x00007f7b64cbc370> #<Tag:0x00007f7b64cbc208>

(Ok Tober) #1

Привет, помогите понять почему код работает по-разномую
создал чистый maven проект с testng(6.9.9) и selenide(2.24) + remoteWedriver +Grid
Пытаюсь запустить тест не в дефолтном фаерфоксе, а в хроме (просто форФан), но возникла проблемка
вот код (url"ы спрятал):

public class TestClass extends SelenideTest{
@Test
public void test1() {
$(By.id(“login”)).click(); //просто проверяю или передается драйвер, на этом моменте обнаруживается что, если в SelenideTest стоит beforeSuite||beforeTest - то драйвера нет и создается еще один инстанс. С beforeClass ||beforeMethod все проходит с первом драйвере
}}

public class SelenideTest extends BaseTest {
@BeforeSuite(alwaysRun = true)
public void setUp () throws Exception{
super.setUp();
WebDriverRunner.setWebDriver(driver);
driver.manage().window().maximize();
open(URL);
}}

public class BaseTest {
protected WebDriver driver;
public void setUp() throws Exception{
driver = new RemoteWebDriver(new URL(remoteWbUrl), new DesiredCapabilities().chrome());
}}

если все-таки оставить beforeSuite - то можно пофиксить, вставив в тест строку > WebDriverRunner.setWebDriver(driver);
но честно говоря мне такое решение не очень нравится.

В моем понимании - что BeforeSuite, что BeforeClass запустится перед тестом(это и происходит), но в первом случае дрвйвер не находится в тесте, а во втором все ок. Почему, в чем тогда разница?


(Stan) #2

Я могу ошибаться, но разве в селениде драйвер создается не в open() ?


(Ok Tober) #3

забыл добавить. там дефолтно создается Фаерфокс, я хочу в коде прописать Хром .
не ищите глубокого смысла, просто разбираюсь в новой для меня штуке)


(Ok Tober) #4

Тоесть да, реализация может быть (и наверное должна быть) другая, но мне интересен в даном контексте только момент с инстансом вебдрайвера который теряется, если поменять 1ну аннотацию BeforeSuite||BeforeTest на BeforeClass||BeforeMethod


(Sergey Korol) #5

Я надеюсь, вы just for fun читали wiki? :wink:

Создавая кастомный инстанс драйвера, вы обязаны его засетить в скоуп selenide. Да и чем вам не подошел -Dbrowser=chrome? Ну или -Dremote=url, если уж так хочется грида…


(Ok Tober) #6

Читали) Но если абстрагироваться от кривой реализации - в чем проблема с аннотациями? Меня именно этот вопрос интересует, а не “как открыть хром с помощью селенид”


(Sergey Korol) #7

Ок, пойдем от обратного… Приведите полный листинг кода, когда у вас воспроизводится проблема с одним семейством аннотаций, и не воспроизводится - с другим. Можете даже sample project на GitHub залить. Ибо ваше описание содержит слишком много if/else для полноценного воспроизведения.


(asolntsev) #8

Привет!
Удачи в освоении новых просторов! Любопытство рулит!

Насчёт метода WebDriverRunner.setWebDriver(driver) - вот кусочек из его явадока:smile:

NB! Webdriver instance should be created and used in the same thread.
A typical error is to create webdriver instance in one thread and use it in another.
Selenide does not support it.
If you really need using multiple threads, please use com.codeborne.selenide.WebDriverProvider

То есть - вызывать setWebDriver нужно в том же потоке, что и использовать вебдрайвер. А TestNG, зараза такая, вызывает методы @BeforeSuite и @Test в разных потоках.

Это одна из причин, почему я недолюбливаю TestNG - он всё усложняет без необходимости.


(Sergey Korol) #9

Не знаю, что там у кого не работает, или запускается в других потоках. Не поленился - набросал сэмл. Результат: во всех Before id потока = 1. RemoteWebDriver сетил как напрямую в BeforeSuite, так и при помощи -Dremote=URL. Оба варианта отрабатывают корректно.

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


(Ok Tober) #10

Привет, спасибо, я не догадался сам посмотреть)
Так и оказалось, если запускать сам тест напрямую - будет 1н поток, но если из testng.xml -получается

suite id 1…
beforeTest id 1…
BeforeMethod id 11…
test id 11…
aftertest id 1…

Надо было вам наверное сразу показать testng.xml , там было

< suite name=“Suite” verbose=“1”>
… < test name=“SelemnideTest” parallel=“methods” thread-count=“5” preserve-order=“true”>
… …< packages>
… … …< package name=“com.test.selenide”/>
… …< /packages>
…< /test>
< /suite>

если убрать " parallel=“methods” , то все будет тоже гнаться в одном потоке.

Очевидно я немного не разбираюсь в том “как оно работает”, будем смотреть.
Спасибо!


(Sergey Korol) #11

Вы допустили концептуальную ошибку, при этом, наговаривая на кривизну библиотек.

Если вы создаете инстанс браузера в BeforeSuite, о какой параллелизации по методам в 5 потоков идет вообще речь? Каким образом вы собирались делить единственный инстанс между 5ю тестами?

Исходя из приведенной xml, TestNG вполне корректно отработал. Вы попросили его запускать методы в параллели, вот он вам и выделил независимые потоки под методы. Поcему BeforeMehod / Test имели одинаковые id, в отличие от BeforeSuite / BeforeTest. Попроси вы его параллелить по классам, BeforeClass также будет запущен в одном потоке с BeforeMethod / Test. Аналогичная ситуация и с tests.

П.С. В следующий раз будьте добры выкладывать полный листинг нерабочего кода. И не спешите обвинять во всех бедах библиотеки. :wink:


(Ok Tober) #12

вопрос стоял*

,а не “библиотеки работают неправильно, и я на них наговариваю тут”.

инстанс браузера я создал 1 и запускал 1 тест, тест прошел другом потоке, спасибо что ответили на мой вопрос


(Sergey Korol) #13

Ну фраза о кривой реализации прозвучала сразу после линки на wiki селенида. О чем тогда шла речь?


(Ok Tober) #14

Я имел в виду мою кривую реализацию кода, а не селенид))) Типа “мой код кривоват, но все-же с одной аннотацией работает, а сдругой нет. почему”
Селенид классный, а я был неправильно понят)


(Eugene Moskalenko) #15

А я, чет не понял, как быть с подобным? Это выходит надо враппер написать, который будет заниматься, распаралеливанием, а не просто WebDriverRunner.setWebDriver(driver); в @BeforeSuite засунуть?

Спасибо…

[TestNG] Running:
  /Users/Mac/IdeaProjects/web-test/suite.xml
Nov 28, 2016 10:48:36 AM com.codeborne.selenide.impl.WebDriverThreadLocalContainer getWebDriver
INFO: No webdriver is bound to current thread: 14 - let's create new webdriver
Starting ChromeDriver 2.25.426935 (820a95b0b81d33e42712f9198c215f703412e1a1) on port 24295
Only local connections are allowed.
log4j:WARN No appenders could be found for logger (org.apache.http.client.protocol.RequestAddCookies).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Nov 28, 2016 10:48:40 AM com.codeborne.selenide.webdriver.WebDriverFactory createWebDriver
INFO: BrowserName=chrome Version=54.0.2840.98 Platform=MAC
Nov 28, 2016 10:48:40 AM com.codeborne.selenide.webdriver.WebDriverFactory createWebDriver
INFO: Selenide v. 3.5.1
Nov 28, 2016 10:48:40 AM com.codeborne.selenide.webdriver.WebDriverFactory createWebDriver
INFO: Selenium WebDriver v. 2.53.0 build time: 2016-03-15 10:43:46
Nov 28, 2016 10:48:40 AM com.codeborne.selenide.impl.WebDriverThreadLocalContainer createDriver
INFO: Create webdriver in current thread 14: ChromeDriver -> ChromeDriver: chrome on MAC (e196aff4a4ecbdc9f2e0cf53012afbff)
[AppClassLoader@18b4aac2] warning javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified

Element not found {.text-center}
Expected: text 'Login to Some Text'

по сути браузер открывается, но урл в него не передается, а урл я этот передаю в своих тестах здесть:

public class LoginPage extends BasePage<LoginPage> {

    public LoginPage() {
        $(".text-center").shouldHave(text("Login to Some Text"));
    }

    public LoginPage openPage() {
        open("site.com/login-page.html");
        return new LoginPage();
    }

    @Step("Login with name & password")
    public CPPage loginWith(String name, String password) {
        $("#email").val(name);
        $("#password").val(password);
        $(".btn").click();
        return page(CPPage.class);
    }

    public SelenideElement getTextInvalidSignInMessages() {
        return $(".alert-danger");
    }

}

сам тест:

    @Title("Main logIn form")
    @Test(enabled = true, groups = "Login", priority = 10)
    public void signIn() {
        //------------------- Test Data -------------------//
        String name = "foobar1";
        String pass = "foobar2";

        // --------------------- Test Case ----------------------//
        loginPage().openPage().loginWith(name, pass);
    }

(Eugene Moskalenko) #16

Блин, вот я дурень :slight_smile: Я же проверку сделал в конструткоре, который происходит раньше, чем в след методе я линк вставляю. Поэтому тесты не доходили до линка, не вставляли его в браузер, и пытались проверить наличие текста на страницах :slight_smile: