-
-
Save beatngu13/8d5f60355d7fbef143198f020b1efca3 to your computer and use it in GitHub Desktop.
import org.junit.jupiter.params.ParameterizedTest; | |
import org.junit.jupiter.params.provider.MethodSource; | |
import org.openqa.selenium.WebDriver; | |
class CrossBrowserTest { | |
@ParameterizedTest | |
@MethodSource( "my.package.WebDriverFactory#getAll" ) | |
void cross_browser_test( final WebDriver driver ) { | |
System.out.println( "Test with " + driver.getClass().getSimpleName() ); | |
} | |
} |
import java.util.Arrays; | |
import java.util.stream.Stream; | |
import org.openqa.selenium.WebDriver; | |
import org.openqa.selenium.chrome.ChromeDriver; | |
import org.openqa.selenium.firefox.FirefoxDriver; | |
public class WebDriverFactory { | |
enum Driver { | |
CHROME, | |
FIREFOX | |
// add more drivers | |
} | |
public static WebDriver get( final Driver driver ) { | |
// add default options | |
switch ( driver ) { | |
case CHROME: | |
return new ChromeDriver(); | |
case FIREFOX: | |
return new FirefoxDriver(); | |
default: | |
throw new IllegalArgumentException( "No '" + driver + "' driver available." ); | |
} | |
} | |
public static Stream<WebDriver> getAll() { | |
return Arrays.stream( Driver.values() ).map( WebDriverFactory::get ); | |
} | |
} |
Yep, that's sufficient if you don't need a factory method for a single driver (WebDriverFactory#driver( Driver )
).
Thank you for putting this together.
I never would have considered the use of a Stream for this. This lead to me to exploring lambda expressions.
Regarding: "WebDriverFactory::driver"
This doesn't compile for me. Shouldn't the double colon be followed by method? Maybe you meant "get" ?
Tested with WebDriverFactory:get and it worked great.
Many thanks.
Hey @jackeymason, glad you like the approach. And you are right, ::driver
was a typo, which was the old method name. Thanks for pointing this out!
do we have complete code. for .e.g I just need to run a simple login test using webdriver on two browsers. where do I pass the browser option to @test Method?
@Vivek-Malhotra your @Test
becomes a @ParameterizedTest
(see https://gist.github.com/beatngu13/8d5f60355d7fbef143198f020b1efca3#file-crossbrowsertest-java-L7), then you can specify the WebDriver
parameter (see https://gist.github.com/beatngu13/8d5f60355d7fbef143198f020b1efca3#file-crossbrowsertest-java-L9).
Or what exactly are you struggling with?
Thanks, @beatngu13
I will try, but is there a way to do it with Junit-4 also. I have an existing framework with a large set of test suite which on Junit-4. I am not sure right now, if switching to Junit-5 will break anything, but will try this option also.
Could it work with BeforeEach/BeforeAll annotations? I have a class with fixtures about running Playwright, creating browser, closing browser after all tests etc.
@standbyoneself I'm not familiar with the Playwright API, do you have an example / some code to look at?
Yes. Here is a class with tests:
import java.util.Date;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import io.qameta.allure.Issue;
import io.qameta.allure.TmsLink;
import ru.sbrf.rmc.annotations.Certificate;
import ru.sbrf.rmc.models.AdminPagePath;
import ru.sbrf.rmc.pages.AdminPage;
@DisplayName("Админка")
public class AdminPageTests extends PageTestFixtures {
private AdminPage adminPage;
@BeforeEach
public void createPage() {
adminPage = new AdminPage(page);
}
@Nested
@DisplayName("Объекты")
class Subjects {
private void shouldCreateAndDeleteSubject(String prefix, String searchQuery) {
long timestamp = new Date().getTime();
String name = prefix + "-" + timestamp;
adminPage.goTo(AdminPagePath.SUBJECTS);
adminPage.goToSubjectForm();
adminPage.fillSubjectName(name);
adminPage.fillSubjectSearchQuery(searchQuery);
adminPage.submitSubjectForm();
adminPage.waitFor(AdminPagePath.SUBJECTS);
adminPage.checkIfSubjectIsVisible(name);
adminPage.deleteSubject(name);
}
@ParameterizedTest(name = "{displayName}")
@Certificate("curuser-6")
@Issue("RMC-6335")
@TmsLink("RMC-T6354")
@CsvSource({"Subject,playwright OR selenium"})
@DisplayName("Создание и удаление объекта с ролью \"Бизнес-администратор\"")
public void shouldCreateAndDeleteSubjectByFeedAdmin(String prefix, String searchQuery) {
shouldCreateAndDeleteSubject(prefix, searchQuery);
}
@ParameterizedTest(name = "{displayName}")
@Certificate("curuser-10")
@Issue("RMC-6335")
@TmsLink("RMC-T6355")
@CsvSource({"Subject,playwright OR selenium"})
@DisplayName("Создание и удаление объекта с ролью \"Куратор процесса\"")
public void shouldCreateAndDeleteSubjectByProcessManager(String prefix, String searchQuery) {
shouldCreateAndDeleteSubject(prefix, searchQuery);
}
}
}
And a fixture class:
import java.lang.reflect.Method;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.*;
import com.microsoft.playwright.*;
import com.microsoft.playwright.options.Cookie;
import ru.sbrf.rmc.AuthClient;
import ru.sbrf.rmc.AuthClientImpl;
import ru.sbrf.rmc.annotations.Certificate;
import ru.sbrf.rmc.mappers.CookieMapperImpl;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class PageTestFixtures {
private Playwright playwright;
private Browser browser;
private BrowserContext context;
protected Page page;
private AuthClient authClient = new AuthClientImpl(new CookieMapperImpl());
private String getCertificateName(TestInfo testInfo) throws NoSuchMethodException {
Optional<Method> optionalMethod = testInfo.getTestMethod();
if (optionalMethod.isEmpty()) {
throw new NoSuchMethodException();
}
Method method = optionalMethod.get();
Certificate annotation = method.getAnnotation(Certificate.class);
return annotation.value();
}
@BeforeAll
public void launchBrowser() {
playwright = Playwright.create();
browser = playwright.chromium().launch();
}
@AfterAll
public void closeBrowser() {
playwright.close();
}
@BeforeEach
public void createContextAndPage(TestInfo testInfo) {
context = browser.newContext(new Browser.NewContextOptions()
.setBaseURL(System.getenv().getOrDefault("BASE_URL", "https://rmp-ift.sberbank.ru/lenta/"))
.setIgnoreHTTPSErrors(true));
page = context.newPage();
try {
String certificateName = getCertificateName(testInfo);
List<Cookie> cookies = authClient.getSessionCookies(certificateName);
context.addCookies(cookies);
} catch (Exception e) {
e.printStackTrace();
}
}
@AfterEach
public void closeContext() {
context.close();
}
}
I have used @ParameterizedTest in couple with @ValueSource(strings = {"chromium","firefox"}), but I have to explicitly call setupBrowser() in each test, which is really annoying. Like that:
Test
@ParameterizedTest(name = "{displayName}")
@Certificate("curuser-6")
@Issue("RMC-6335")
@TmsLink("RMC-T6354")
@ValueSource(strings = {"chromium","firefox"})
@DisplayName("Создание и удаление объекта с ролью \"Бизнес-администратор\"")
public void shouldCreateAndDeleteSubjectByFeedAdmin(String browser) {
setupBrowser(browser);
shouldCreateAndDeleteSubject();
}
Fixture
protected void setupBrowser(String browserType) {
playwright = Playwright.create();
if (browserType.equals("chromium")) {
browser = playwright.chromium().launch();
} else if (browserType.equals("firefox")) {
browser = playwright.firefox().launch();
} else {
throw new IllegalArgumentException();
}
createContextAndPage();
}
Really want to have ability to use BeforeEach/AfterAll annotations for better readability and non-verbose reusability
@standbyoneself I just had a look at the Playwright docs. Are you aware that there is (experimental) Junit 5 support? Apparently, it does all the lifecycle management for you. And for cross-browser testing, maybe OptionsFactory
can help?
Or even simpler