We want to run our tests parallel, we use Guice, TestNg, and Seledine.
The problem is when we add in testng.xml parameter
parallel="tests" thread-count="2"
First, opens first browser, does login, then opens another browser with no page opened. Then it throws error like
com.codeborne.selenide.ex.ElementNotFound: Element not found {By.xpath: //div[@id='toast-container']}
So, as we guess, problem is that Guice @Injection doesn't know which browser to use exactly.
Here's how we use Guice:
We have NavigationModule where we just bind Navigation service to Singleton
public class NavigationModule extends AbstractModule {
@Override
protected void configure() {
bind(NavigationService.class).in(Singleton.class);
}
}
After that we use Navigation service to do some navigation on the page.
public class NavigationService {
@Inject
private LoginPage loginPage;
@Inject
private TemplateManagementPage templateManagementPage;
@Inject
private CreateTemplatePage createTemplatePage;
@Inject
private NavigationMenu navigationMenu;
public TemplateManagementPage logIn(String username, String password) {
return loginPage.login(username, password);
}
public TemplateManagementPage openTemplateManagementPage() {
navigationMenu.openMenu()
.openTemplatesMenu()
.openTemplateManagementPage();
return templateManagementPage;
}
}
In BaseTest we do login and inject NavigationService
@Guice(modules = NavigationModule.class)
public abstract class BaseTest{
@Inject
protected NavigationService navigationService;
protected TemplateManagementPage templateManagementPage;
@BeforeSuite
public void login() {
User user = UserFactory.getDefaultUser();
templateManagementPage = navigationService.logIn(user.getUserName(), user.getPassword());
}
}
And the last thing we open one page before each test method
@BeforeMethod(description = "Open create template page")
public void openCreateTemplatePage() {
templatePage = navigationService.openCreateTemplatePage();
}
Hi there. After few weeks, we finally found the reason of this issue.
The problem was in fields initialization.
Here, in BaseTest was problem
@Guice(modules = NavigationModule.class)
public abstract class BaseTest{
@Inject
protected NavigationService navigationService;
protected TemplateManagementPage templateManagementPage;
@BeforeSuite
public void login() {
User user = UserFactory.getDefaultUser();
templateManagementPage = navigationService.logIn(user.getUserName(), user.getPassword());
}
}
With field
protected TemplateManagementPage templateManagementPage;
In out project, all pages extends Page class
public abstract class Page{
public Page() {
page(this);
}
}
So, as u can see it just does initialization. And here's the problem, when we do initialization of TemplateManagementPage in BaseTest through field, Page constructor calls Selenide page method and that methods creates an instance of browser, and when we wanna do login, it again creates another instance of browser, so basically that's all. All what u need it's to remove
protected TemplateManagementPage templateManagementPage;
and change @BeforeSuite to @BeforeTest
So the final solution looks like
@Guice(modules = NavigationModule.class)
public abstract class BaseTest{
@Inject
protected NavigationService navigationService;
@BeforeTest()
public void login(){
User user = UserFactory.getDefaultUser();
navigationService.logIn(user.getUserName(), user.getPassword());
}
}
So now all tests runs in parallel, as we wanted.
@danteg233 So, can we close the issue?
P.S. I would say that you have over-engineered your tests. I don't see any reason to use dependency injection/Guice. It brings complexity but doesn't solve any real problems. And look, you still have public static method UserFactory.getDefaultUser() - meaning that the whole dependency injection doesn't make sense anymore.
The problem described in the current issue could not exist if you simplify tests and throw DI away. :)
@danteg233 I know you solved this issue, but I'm running into the same thing, and your solution isn't working for me. Is there anyway you could post a full working solution (even sanitized)? Your snippets weren't enough for me to solve the problem
Most helpful comment
@danteg233 So, can we close the issue?
P.S. I would say that you have over-engineered your tests. I don't see any reason to use dependency injection/Guice. It brings complexity but doesn't solve any real problems. And look, you still have public static method
UserFactory.getDefaultUser()- meaning that the whole dependency injection doesn't make sense anymore.The problem described in the current issue could not exist if you simplify tests and throw DI away. :)