I try practicing to execute tests in parallel using TestNG invocationCount and threadPoolSize.
A. I write a all-in-one test like this, and it is successful
#Test(invocationCount = 5, threadPoolSize = 5)
public void testThreadPool() {
WebDriver driver = new ChromeDriver();
driver.get("http://www.google.com");
driver.findElement(By.name("q")).sendKeys("Amazon");
driver.quit();*/
}
=> 5 Chrome browsers are opened at the same time (parallel), and tests are successfully executed.
B. I define my test in #before and #after, and it doesn't work
#BeforeTest
public void setUp() {
WebDriver driver = driverManager.setupDriver("chrome");
}
#Test(invocationCount = 5, threadPoolSize = 5)
public void testThreadPool() {
driver.get("http://www.google.com");
driver.findElement(By.name("q")).sendKeys("Amazon");
}
#AfterTest
public void tearDown() {
driver.quit()
}
=> 1 chrome browser is opened, and it seems it is refreshed 5 times, and at the end, there are 5 Amazon words entered in text field, with the following log message:
[1593594530,792][SEVERE]: bind() failed: Cannot assign requested address (99)
ChromeDriver was started successfully.
Jul 01, 2020 11:08:51 AM org.openqa.selenium.remote.ProtocolHandshake createSession
I understand that, with B, 5 threads use the same object driver, that's why only one chrome is opened. But I don't know how to manage driver object in this case so I can get the same result like in A.
Any idea appreciated.
You can use ThreadLocal class to make your webdriver Threadsafe
private ThreadLocal<WebDriver> webdriver = new ThreadLocal<WebDriver>();
#BeforeMethod
public void setUp() {
webdriver.set(driverManager.setupDriver("chrome"));
}
#Test(invocationCount = 5, threadPoolSize = 5)
public void testThreadPool() {
webdriver.get().get("http://www.google.com");
webdriver.get().findElement(By.name("q")).sendKeys("Amazon");
}
#AfterMethod
public void tearDown() {
webdriver.get().quit()
}
Edit : You will need to use BeforeMethod/AfterMethod in above context.
Related
I use BrowserStack. Before each test I create new driver. After each scenario I use driver.quit() because I want to close the session.
When I have more than one test case (e.g two scenario files) to run I get a message Session ID is null. Using WebDriver after calling quit()?.
When I don't use driver.quit() or I use driver.closeApp(), the first session takes too long and even if the second one starts, I cannot use it (I mean I cannot click on elements). I run my tests by junit runners.
Is there any possibility to quit driver after each test and run another one without that error?
private static AppiumDriver<MobileElement> driver;
#Before
public void before() {
driver = new AndroidDriver<>(new URL("URL"), capabilities);
}
public static AndroidDriver<MobileElement> getDriver() {
return (AndroidDriver<MobileElement>) driver;
}
#After
public void after() {
if ( driver == null ) {
driver.quit();
driver = null;
}
}
If you are facing this issue, please go through the BrowserStack documentation for the Junit demo code here, this is will help you solve the issue.
I can see your code mentioned "Before" & "After" only not "BeforeEach" / "AfterEach".
Please try this out
I wrote automated tests with help of JUnit, Selenium Webdriver (v. 3.141.59) and Chromedriver (v. 2.45).
Firstly, I wrote a login test:
[...]
void loginTest() {
driver().findElement(By.id("login-button")).click();
driver().findElement(By.id("name")).sendKeys("mail#xx.com");
driver().findElement(By.id("password")).sendKeys("password");
driver().findElement(By.id("send")).click();
assertTrue(driver().findElement(By.id("logged-in-msg")).isDisplayed());
}
Everything worked fine, all good, test green.
Then I got some more and more complicated and long ids and xpaths I had to use, so I decided to keep tests short and nice and put all my locators in separate class, like this:
public class LocatorsList {
public static final String
SIGN_IN_BUTTON = "login-button",
LOG_IN_USERNAME = "name",
LOG_IN_PASSWORD = "password",
LOG_IN_BUTTON = "send",
SUCCESS_MSG = "logged-in-msg";
}
And my test:
[...]
void loginTest() {
driver().findElement(By.id(SIGN_IN_BUTTON)).click();
driver().findElement(By.id(LOG_IN_USERNAME)).sendKeys("mail#xx.com");
driver().findElement(By.id(LOG_IN_PASSWORD)).sendKeys("password");
driver().findElement(By.id(LOG_IN_BUTTON)).click();
assertTrue(driver().findElement(By.id(SUCCESS_MSG)).isDisplayed());
}
Then it stopped working. Webdriver sends errors:
org.openqa.selenium.NoSuchElementException: no such element:
Unable to locate element: {"method":"id","selector":"name"}
As I watched my test going, this element was right there on the page, webdriver even clicked at it as if it wanted to fill the field... but it didn't. Says 'unable to locate element'.
I tried to change chromedriver and selenium versions but it didn't help.
If that's honestly the only real change to the code, then could it be as simple as you missing the class name before the string? I.e:
driver().findElement(By.id(LocatorsList.SIGN_IN_BUTTON)).click()
This is most probably due to element not present, you need to wait for the element to be loaded. Use
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.presenceOfElementLocated((By.id(LOG_IN_USERNAME))));
After that you can perform the action on that particular element say sendKeys event.
public class Testing {
public static final String
SIGN_IN_BUTTON = "jsid-login-button",
LOG_IN_USERNAME = "login-email-name",
LOG_IN_PASSWORD = "login-email-password",
LOG_IN_BUTTON = "input[type='submit']";
WebDriver driver;
#BeforeMethod
public void setUp() {
System.setProperty("webdriver.chrome.driver", <driverLocation>);
driver = new ChromeDriver();
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
driver.get("https://9gag.com/");
}
#Test
public void demoTest() {
driver.findElement(By.id(SIGN_IN_BUTTON)).click();
WebDriverWait wait = new WebDriverWait(driver, 20);
wait.until(ExpectedConditions.presenceOfElementLocated((By.id(LOG_IN_USERNAME))));
driver.findElement(By.id(LOG_IN_USERNAME)).sendKeys(<YOUR_EMAIL>);
driver.findElement(By.id(LOG_IN_PASSWORD)).sendKeys(<YOUR_PASSWORD>);
driver.findElement(By.cssSelector(LOG_IN_BUTTON)).click();
}
#AfterMethod
public void tearDown() {
driver.quit();
}
}
Hi guys I want to quit the page afte I type "Hello World" in google search using firefox browser and selenium
WebDriver driver = null;
public static void main(String args[]) {
SimpleSelenium ss = new SimpleSelenium();
ss.openBrowser();
ss.getPage();
ss.quitPage();
}
private void openBrowser() {
System.setProperty("webdriver.gecko.driver", "C:/geckodriver.exe");
driver = new FirefoxDriver();
}
private void quitPage() {
driver.quit();
}
private void getPage() {
driver.get("http://www.google.com");
}
1) Create a Junit test class
2) Initialize the driver in your setup method like
ChromeDriver driver = new ChromeDriver();//Download chromeDriver.exe file and point to location where you have installed the like as you mentioned. `driver.System.setProperty("webdriver.gecko.driver", "C:/geckodriver.exe");`
3) Create a test method with your business logic to type hello world
3) Create After and Before Class annotations for the methods .In After class annotation method you can write driver.quit.
You can refer to following link for more clarity
https://www.guru99.com/selenium-tutorial.html
I am Added sample format which is written Using java and testNG..Here Every time First before method will run then 1st test case will execute then after method will work then again before method work then next test case......In this way you can manage your test case and it will also generate Report also.Here you will get better explanation.
public class GoogleTest {
FirefoxDriver driver;
#BeforeMethod
public void setUp1() throws Exception {
System.setProperty("webdriver.gecko.driver", "D:\\\\ToolsQA\\trunk\\Library\\drivers\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get("https://www.google.com");
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
#Test
public void GoogleInputField() throws InterruptedException {
System.out.println("Hello world");
System.out.println("Hello world");
//Write Your test case for test case 1
}
#Test
public void google suggestion() throws InterruptedException {
//Write Your test case for test case 1
}
#AfterMethod
public void getResult(ITestResult result) throws IOException {
driver.quit();
}
}
Dont forget to add Firefox driver on gecko.driver path
I am assuming that you want to open the browser using selenium, load google and then listen till you MANUALLY enter "hello world" in the input box. The method listenForHelloWorld() will do that.
public static void main(String args[]) {
SimpleSelenium ss = new SimpleSelenium();
ss.openBrowser();
ss.getPage();
ss.listenForHelloWorld();
ss.quitPage();
}
private void listenForHelloWorld() {
// Get the search field
WebElement searchField = driver.findElement(By.name("q"));
int count = 1;
while (count++ < 20) {
// if search field value is "hellwo world" break loop which will eventallu lead to `quit()` as it is the next method to exit.
if (searchField.getAttribute("value").equalsIgnoreCase("hello world")) {
break;
}
Thread.sleep(5000)
}
}
If you are asking how to enter "hello world" in browser automatically use below.
driver.findElement(By.name("q")).sendKeys("hello world");
Is there any chance to use annotatios with system properties in Selenium?
#Test
public void
testSigninMobile()
{
if(System.getProperty("browser").equals("iphone")){
login();
}else{
driver.quit();
}
}
I would like to have annotations like that:
#Test if broswer is iphone, firefox but not if it is IE or Edge etc.
public void
testSigninMobile()
{...
I mean the situation where you have for instance 50 tests but your app is not full ready for every browser. I think that it is silly to write to those 50 test such a browser checking logic?
You can write logics inside the #Test method using Capabilities - getBrowserName().
#Test
public void testSigninMobile()
{
Capabilities cap = ((RemoteWebDriver) driver).getCapabilities();
String browserName = cap.getBrowserName().toLowerCase();
System.out.println(browserName);
if("blabla".equalsIgnoreCase(browserName))
{
// Your code
}
else
{
throw new SkipException("Skipping this excecution");
}
}
i like to access some pages that are not under my control. It could be that this pages execute some slow get requests but the main html is fully loaded and displayed. I tried many options but i could make it. The firefoxWebDriver.get(...) doesn't terminate on some sites in a realistic time.
To reproduice the problem, I wrote this small UnitTest showing the problem:
public class Timeout {
private FirefoxDriver driver;
#Before
public void setup() {
final FirefoxProfile profile = new FirefoxProfile();
profile.setPreference("dom.max_script_run_time", 0);
profile.setPreference("webdriver.load.strategy", "fast");
this.driver = new FirefoxDriver(profile);
// this.driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
// this.driver.manage().timeouts().setScriptTimeout(10, TimeUnit.SECONDS);
}
#Test(timeout = 15000)
public void shouldRetriveREDCAFEPageQuiteFast() {
this.driver.get("http://redcafe.vn/Home/su-kien-binh-luan/kagawa-tu-choi-mac-ao-so-7");
}
#Test(timeout = 15000)
public void shouldRetriveMUFCPageQuiteFast() {
this.driver.get("http://news.mufc.vn/detail/172-hoan-tat-giay-phep-lao-dong-m-u-chinh-thuc-so-huu-kagawa.html");
}
#After
public void tearDown() {
this.driver.close();
}
}
Thanks for you help.
<driver>.manage().timeouts().pageLoadTimeout(60, TimeUnit.SECONDS);
will set the page load timeout to 60 seconds, after which it will throw an error. You need to set this up before your first get() call.
The API is supported from Webdriver release 2.20.0 onwards.
Refer API Reference for new Timeout API's