Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#231 use different browser instances for before after methods #232

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/main/java/com/xceptance/neodymium/NeodymiumRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import org.apache.commons.lang3.StringUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.internal.runners.statements.RunAfters;
import org.junit.internal.runners.statements.RunBefores;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runner.notification.RunNotifier;
Expand All @@ -29,6 +31,8 @@
import com.xceptance.neodymium.module.StatementBuilder;
import com.xceptance.neodymium.module.order.DefaultStatementRunOrder;
import com.xceptance.neodymium.module.statement.browser.multibrowser.Browser;
import com.xceptance.neodymium.module.statement.browser.multibrowser.BrowserRunAfters;
import com.xceptance.neodymium.module.statement.browser.multibrowser.BrowserRunBefores;
import com.xceptance.neodymium.util.Neodymium;

import io.qameta.allure.selenide.AllureSelenide;
Expand Down Expand Up @@ -401,6 +405,28 @@ private void recursiveBuildCrossProduct(Method method, List<StatementBuilder> bu
}
}

@Override
protected Statement withBefores(FrameworkMethod method, Object target,
Statement statement)
{
List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods(
Before.class);
return befores.isEmpty() ? statement
: (Neodymium.configuration().startNewBrowserForSetUp() ? new BrowserRunBefores(statement, befores, target)
: new RunBefores(statement, befores, target));
}

@Override
protected Statement withAfters(FrameworkMethod method, Object target,
Statement statement)
{
List<FrameworkMethod> afters = getTestClass().getAnnotatedMethods(
After.class);
return afters.isEmpty() ? statement
: (Neodymium.configuration().startNewBrowserForCleanUp() ? new BrowserRunAfters(statement, afters, target)
: new RunAfters(statement, afters, target));
}

@Override
public Description getDescription()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package com.xceptance.neodymium.module.statement.browser.multibrowser;

import java.util.ArrayList;
import java.util.List;

import org.junit.internal.runners.statements.RunAfters;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.MultipleFailureException;
import org.junit.runners.model.Statement;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.events.EventFiringWebDriver;

import com.browserup.bup.BrowserUpProxy;
import com.codeborne.selenide.WebDriverRunner;
import com.xceptance.neodymium.NeodymiumWebDriverListener;
import com.xceptance.neodymium.module.StatementBuilder;
import com.xceptance.neodymium.module.statement.browser.multibrowser.configuration.BrowserConfiguration;
import com.xceptance.neodymium.module.statement.browser.multibrowser.configuration.MultibrowserConfiguration;
import com.xceptance.neodymium.util.Neodymium;

public class BrowserRunAfters extends RunAfters
{
private final Statement next;

private final List<FrameworkMethod> afters;

public BrowserRunAfters(Statement next, List<FrameworkMethod> afters, Object target)
{
super(next, afters, target);
this.afters = afters;
this.next = next;
}

@Override
public void evaluate() throws Throwable
{
List<Throwable> errors = new ArrayList<Throwable>();
try
{
next.evaluate();
}
catch (Throwable e)
{
errors.add(e);
}
finally
{
WebDriverStateContainer oldDriver = Neodymium.getWebDriverStateContainer();
BrowserConfiguration oldBrowserConfiguration = MultibrowserConfiguration.getInstance().getBrowserProfiles()
.get(Neodymium.getBrowserProfileName());
for (FrameworkMethod each : afters)
{
boolean isSuppressed = isSuppressed(each);
boolean startNewBrowserForCleanUp = shouldStartNewBrowser(each) && !isSuppressed;

BrowserConfiguration browserConfiguration = oldBrowserConfiguration;
List<Browser> methodBrowserAnnotations = StatementBuilder.getAnnotations(each.getMethod(), Browser.class);

// if @After method is annotated with @Browser tag, it might need to be executed with another
// browser
if (!methodBrowserAnnotations.isEmpty())
{
browserConfiguration = MultibrowserConfiguration.getInstance().getBrowserProfiles()
.get(methodBrowserAnnotations.get(0).value());
}

// if we don't need to start new browser for the cleanup and the browser for the test was not suppressed
// it means that we should use the same browser for cleanup
// as the might have been other @After methods with new browser running previously, let's explicitly set
// the driver to original
if (!startNewBrowserForCleanUp && !isSuppressed && (Neodymium.getDriver() == null || !Neodymium.getDriver().equals(oldDriver.getWebDriver()))
&& oldDriver != null)
{
WebDriverRunner.setWebDriver(oldDriver.getWebDriver());
Neodymium.setWebDriverStateContainer(oldDriver);
Neodymium.setBrowserProfileName(oldBrowserConfiguration.getConfigTag());
Neodymium.setBrowserName(oldBrowserConfiguration.getCapabilities().getBrowserName());
}
// if we need to start new browser for the clean up and any browser configuration for the @After method
// was found, create a new driver
else if (startNewBrowserForCleanUp && browserConfiguration != null)
{
WebDriverStateContainer wDSCont = BrowserRunnerHelper.createWebDriverStateContainer(browserConfiguration);

EventFiringWebDriver eFWDriver = new EventFiringWebDriver(wDSCont.getWebDriver());
eFWDriver.register(new NeodymiumWebDriverListener());
wDSCont.setWebDriver(eFWDriver);

BrowserRunnerHelper.setBrowserWindowSize(browserConfiguration, wDSCont.getWebDriver());
WebDriverRunner.setWebDriver(wDSCont.getWebDriver());
Neodymium.setWebDriverStateContainer(wDSCont);
Neodymium.setBrowserProfileName(browserConfiguration.getConfigTag());
Neodymium.setBrowserName(browserConfiguration.getCapabilities().getBrowserName());
}
else if (!isSuppressed && browserConfiguration == null)
{
throw new RuntimeException("No browser setting for @After method '" + each.getName()
+ "' was found. "
+ "If browser was suppressed for the test and is also not required for the clean up,"
+ " please mark the @After method with @DontStartNewBrowserForCleanUp annotation."
+ " If you need to start a browser for the clean up,"
+ " please, use @Browser annotaion to mention what browser should be used exactly for this @After.");
}
boolean afterFailed = false;
try
{
invokeMethod(each);
}
catch (Throwable e)
{
afterFailed = true;
errors.add(e);
}
finally
{
// if we did a set up of new driver before the @After method, we need to close it
if (startNewBrowserForCleanUp && browserConfiguration != null)
{
// avoid closing driver in case it's selected to keep browser open
if (!(!browserConfiguration.isHeadless()
&& ((Neodymium.configuration().keepBrowserOpenOnFailure() && afterFailed) || Neodymium.configuration().keepBrowserOpen())))
{
WebDriverStateContainer wdst = Neodymium.getWebDriverStateContainer();
WebDriver driver = wdst != null ? wdst.getWebDriver() : null;
if (driver != null)
{
driver.quit();
}
BrowserUpProxy proxy = wdst != null ? wdst.getProxy() : null;
if (proxy != null)
{
proxy.stop();
}
Neodymium.setWebDriverStateContainer(null);
}
}
}
}
}
MultipleFailureException.assertEmpty(errors);
}

private boolean shouldStartNewBrowser(FrameworkMethod each)
{
List<DontStartNewBrowserForCleanUp> methodStartNewBrowserForCleanUp = StatementBuilder.getAnnotations(each.getMethod(),
DontStartNewBrowserForCleanUp.class);
List<DontStartNewBrowserForCleanUp> classStartNewBrowserForCleanUp = StatementBuilder.getAnnotations(each.getDeclaringClass(),
DontStartNewBrowserForCleanUp.class);

// if global config for dontStartNewBrowserForCleanUp is set to false, we should not reach this point
boolean dontStartNewBrowserForCleanUp = true;
if (!classStartNewBrowserForCleanUp.isEmpty())
{
dontStartNewBrowserForCleanUp = false;
}

if (!methodStartNewBrowserForCleanUp.isEmpty())
{
dontStartNewBrowserForCleanUp = false;
}

// if @After method is annotated with @SuppressBrowser annotation, no new browser should be started
return dontStartNewBrowserForCleanUp;
}

private boolean isSuppressed(FrameworkMethod each)
{
List<SuppressBrowsers> methodSuppressBrowserAnnotations = StatementBuilder.getAnnotations(each.getMethod(), SuppressBrowsers.class);

return !methodSuppressBrowserAnnotations.isEmpty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package com.xceptance.neodymium.module.statement.browser.multibrowser;

import java.util.List;

import org.junit.internal.runners.statements.RunBefores;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.events.EventFiringWebDriver;

import com.browserup.bup.BrowserUpProxy;
import com.codeborne.selenide.WebDriverRunner;
import com.xceptance.neodymium.NeodymiumWebDriverListener;
import com.xceptance.neodymium.module.StatementBuilder;
import com.xceptance.neodymium.module.statement.browser.multibrowser.configuration.BrowserConfiguration;
import com.xceptance.neodymium.module.statement.browser.multibrowser.configuration.MultibrowserConfiguration;
import com.xceptance.neodymium.util.Neodymium;

public class BrowserRunBefores extends RunBefores
{
private final Statement next;

private final List<FrameworkMethod> befores;

public BrowserRunBefores(Statement next, List<FrameworkMethod> befores, Object target)
{
super(next, befores, target);
this.befores = befores;
this.next = next;
}

@Override
public void evaluate() throws Throwable
{
WebDriverStateContainer oldWDsCont = Neodymium.getWebDriverStateContainer();
BrowserConfiguration oldBrowserConfiguration = MultibrowserConfiguration.getInstance().getBrowserProfiles()
.get(Neodymium.getBrowserProfileName());
for (FrameworkMethod before : befores)
{
boolean isSuppressed = isSuppressed(before);
boolean startNewBrowserForSetUp = shouldStartNewBrowser(before) && !isSuppressed;
BrowserConfiguration browserConfiguration = oldBrowserConfiguration;

List<Browser> methodBrowserAnnotations = StatementBuilder.getAnnotations(before.getMethod(), Browser.class);

// if @Before method is annotated with @Browser tag, it might need to be executed with another
// browser
if (!methodBrowserAnnotations.isEmpty())
{
browserConfiguration = MultibrowserConfiguration.getInstance().getBrowserProfiles()
.get(methodBrowserAnnotations.get(0).value());
}

// if we don't need to start new browser for the setup and the browser for the test was not suppressed
// it means that we should use the same browser for setup
// as the might have been other @Before methods with new browser running previously, let's explicitly set
// the driver to original
if (!startNewBrowserForSetUp && !isSuppressed && (Neodymium.getDriver() == null || !Neodymium.getDriver().equals(oldWDsCont.getWebDriver()))
&& oldWDsCont != null)
{
WebDriverRunner.setWebDriver(oldWDsCont.getWebDriver());
Neodymium.setWebDriverStateContainer(oldWDsCont);
Neodymium.setBrowserProfileName(oldBrowserConfiguration.getConfigTag());
Neodymium.setBrowserName(oldBrowserConfiguration.getCapabilities().getBrowserName());
}

// if we need to start new browser for the set up and any browser configuration for the @Before method
// was found, create a new driver
else if (startNewBrowserForSetUp && browserConfiguration != null)
{
WebDriverStateContainer wDSCont = BrowserRunnerHelper.createWebDriverStateContainer(browserConfiguration);

EventFiringWebDriver eFWDriver = new EventFiringWebDriver(wDSCont.getWebDriver());
eFWDriver.register(new NeodymiumWebDriverListener());
wDSCont.setWebDriver(eFWDriver);

BrowserRunnerHelper.setBrowserWindowSize(browserConfiguration, wDSCont.getWebDriver());
WebDriverRunner.setWebDriver(wDSCont.getWebDriver());
Neodymium.setWebDriverStateContainer(wDSCont);
Neodymium.setBrowserProfileName(browserConfiguration.getConfigTag());
Neodymium.setBrowserName(browserConfiguration.getCapabilities().getBrowserName());

}
else if (startNewBrowserForSetUp)
{
throw new RuntimeException("No browser setting for @Before method '" + before.getName()
+ "' was found. "
+ "If browser is suppressed for the test and is also not required for the set up,"
+ " please mark the @Before method with @DontStartNewBrowserForSetUp annotation."
+ " If you need to start a browser for the set up,"
+ " please, use @Browser annotaion to mention what browser should be used exactly for this @Before.");
}
boolean beforeFailed = false;
try
{
invokeMethod(before);
}
catch (Throwable e)
{
beforeFailed = true;
throw e;
}
finally
{
// if we did a set up of new driver before the @Before method, we need to close it
if (startNewBrowserForSetUp && browserConfiguration != null)
{
// avoid closing driver in case it's selected to keep browser open
if (!(!browserConfiguration.isHeadless()
&& ((Neodymium.configuration().keepBrowserOpenOnFailure() && beforeFailed) || Neodymium.configuration().keepBrowserOpen())))
{
WebDriverStateContainer wdst = Neodymium.getWebDriverStateContainer();
WebDriver driver = wdst != null ? wdst.getWebDriver() : null;
if (driver != null)
{
driver.quit();
}
BrowserUpProxy proxy = wdst != null ? wdst.getProxy() : null;
if (proxy != null)
{
proxy.stop();
}
Neodymium.setWebDriverStateContainer(null);
}
}

// set driver back to the original to execute the test or clean up (in case of failure)
Neodymium.setWebDriverStateContainer(oldWDsCont);
if (oldBrowserConfiguration != null)
{
Neodymium.setBrowserProfileName(oldBrowserConfiguration.getConfigTag());
Neodymium.setBrowserName(oldBrowserConfiguration.getCapabilities().getBrowserName());
}
if (oldWDsCont != null && oldWDsCont.getWebDriver() != null)
{
WebDriverRunner.setWebDriver(oldWDsCont.getWebDriver());
}
}
}

next.evaluate();
}

private boolean shouldStartNewBrowser(FrameworkMethod each)
{
List<DontStartNewBrowserForSetUp> methodStartNewBrowserForSetUp = StatementBuilder.getAnnotations(each.getMethod(),
DontStartNewBrowserForSetUp.class);
List<DontStartNewBrowserForSetUp> classStartNewBrowserForSetUp = StatementBuilder.getAnnotations(each.getDeclaringClass(),
DontStartNewBrowserForSetUp.class);

// if global config for dontStartNewBrowserForSetUp is set to false, we should not reach this point
boolean dontStartNewBrowserForSetUp = true;
if (!classStartNewBrowserForSetUp.isEmpty())
{
dontStartNewBrowserForSetUp = false;
}

if (!methodStartNewBrowserForSetUp.isEmpty())
{
dontStartNewBrowserForSetUp = false;
}

// if @Before method is annotated with @SuppressBrowser annotation, no new browser should be started
return dontStartNewBrowserForSetUp;
}

private boolean isSuppressed(FrameworkMethod each)
{
List<SuppressBrowsers> methodSuppressBrowserAnnotations = StatementBuilder.getAnnotations(each.getMethod(), SuppressBrowsers.class);

return !methodSuppressBrowserAnnotations.isEmpty();
}
}