overload in step find element - java

I have selenium java code testing some site in ff 41 and selenium 2.48. Last step of my code is findElement (timeout 30 sec). I don't have any error and my test does not fail. But I see overload in this step, its duration is 88 - 150 sec.
Any idea why my test does not fail after 30 sec?
Here is my last step code
errorMessage = "";
boolean flag23 = false;
for (int k = 0; k < 30; k++)
{
try
{
List<WebElement> element23 = findElements("print-confirmation");// "//a[#class='print-confirmation']");
if (element23.size() != 0)
{
flag23 = true;
break;
}
}
catch (Exception e)
{
pause(1000);
}
}
assertTrue(flag23); // new WebDriverWait(driver,
// 30).until(ExpectedConditions.presenceOfElementLocated(By.id("//a[#class='print-confirmation']")));
writer.append("\ntest89028:23 OK " + getRunTime(System.currentTimeMillis() - startTime));
startTime = System.currentTimeMillis();

If I get it right, you call findElements 30 times and you pause 1s after each iteration if you do not find your element yet. So you need worst case 30s only for pausing, plus time for the whole loop and especially for findElements. So your recorded time is more than 30s, since you record the whole code block execution. I don't know if I got it right and this might help you.

I'm not sure what is in the findElements() function... maybe a wait or sleep? Something in there is likely magnifying the wait time or you have an implicitWait() set. I would rewrite this block of code like this... (and remove any implicitWait()).
boolean flag23 = false;
try
{
new WebDriverWait(driver, 30).until(ExpectedConditions.presenceOfElementLocated(By.xpath("//a[#class='print-confirmation']")));
flag23 = true;
}
catch (TimeoutException e)
{
System.out.println("Element not found due to TimeoutException");
}
assertTrue(flag23);
I think it's easier to read and is more controlled. You should not mix implicit and explicit waits or you will get weird behaviors (likely similar to this).
http://www.seleniumhq.org/docs/04_webdriver_advanced.jsp#explicit-and-implicit-waits
WARNING: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example setting an implicit wait of 10s and an explicit wait of 15 seconds, could cause a timeout to occur after 20 seconds.

Related

Fastest way to kill NoSuchElementException or any Exception when element is not found in Selenium WebDriver

Is there a fastest way to kill the process in catch (when using try/catch)? Cos usually it takes 1 minute to make the process proceed after exception has been caught.
I have this code below:
public boolean elementExist(WebDriver driver, By locator){
boolean exist = false;
try{
exist = driver.findElements(locator).size()>0;
} catch (org.openqa.selenium.NoSuchElementException e) {
return false;
}
return exist;
}
Whenever the script didn't found the element it waits 1 minute to proceed. I need to lower down the 1 minute to at least 5-10 secs bcos it's such a waste of time.
Or if there's another way and faster to handle if the element does not exist please help.
Try to set
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
Right after
WebDriver driver = new FirefoxDriver(); //or ChromeDriver
ImplicityWait basically tells Selenium "Hey, every operation you are trying to perform should Timeout after 3 seconds"

Increasing the performance of a multi-thread Selenium WebDriver based brute force bot

everyone!
I have just created a brute force bot which uses WebDriver and multithreading to brute force a 4-digit code. 4-digit means a range of 0000 - 9999 possible String values. In my case, after clicking the "submit" button, not less than 7 seconds passes before the client gets a response from the server. So, I have decided to use Thread.sleep(7200) to let the page with a response be fully loaded. Then, I found out that I couldn't afford to wait for 9999*7,5 seconds for the task to be accomplished, so I had to use multithreading. I have a Quad-Core AMD machine with 1 virtual core per 1 hardware one, which gives me the opportunity to run 8 threads simultaneously. Ok, I have separated the whole job of 9999 combinations between 8 threads equally, each had got a scope of work of 1249 combinations + remainder thread starting at the very end. Ok, now I'm getting my job done in 1,5 hours (because the right code appears to be in the middle of the scope of work). That is much better, BUT it could be even more better! You know, the Thread.sleep(7500) is a pure waste of time. My machine could be switching to other threads which are wait() because of limited amount of hardware cores. How to do this? Any ideas?
Below are two classes to represent my architecture approach:
public class BruteforceBot extends Thread {
// All the necessary implementation, blah-blah
public void run() {
brutforce();
}
private void brutforce() {
initDriver();
int counter = start;
while (counter <= finish) {
try {
webDriver.get(gatewayURL);
webDriver.findElement(By.name("code")).sendKeys(codes.get(counter));
webDriver.findElement(By.name("code")).submit();
Thread.sleep(7200);
String textFound = "";
try {
do {
textFound = Jsoup.parse(webDriver.getPageSource()).text();
//we need to be sure that the page is fully loaded
} while (textFound.contains("XXXXXXXXXXXXX"));
} catch (org.openqa.selenium.JavascriptException je) {
System.err.println("JavascriptException: TypeError: "
+ "document.documentElement is null");
continue;
}
// Test if the page returns XXXXXXXXXXXXX below
if (textFound.contains("XXXXXXXXXXXXXXXx") && !textFound.contains("YYYYYYY")) {
System.out.println("Not " + codes.get(counter));
counter++;
// Test if the page contains "YYYYYYY" string below
} else if (textFound.contains("YYYYYYY")) {
System.out.println("Correct Code is " + codes.get(counter));
botLogger.writeTheLogToFile("We have found it: " + textFound
+ " ... at the code of " + codes.get(counter));
break;
// Test if any other case of response below
} else {
System.out.println("WTF?");
botLogger.writeTheLogToFile("Strange response for code "
+ codes.get(counter));
continue;
}
} catch (InterruptedException intrrEx) {
System.err.println("Interrupted exception: ");
intrrEx.printStackTrace();
}
}
destroyDriver();
} // end of bruteforce() method
And
public class ThreadMaster {
// All the necessary implementation, blah-blah
public ThreadMaster(int amountOfThreadsArgument,
ArrayList<String> customCodes) {
this();
this.codes = customCodes;
this.amountOfThreads = amountOfThreadsArgument;
this.lastCodeIndex = codes.size() - 1;
this.remainderThread = codes.size() % amountOfThreads;
this.scopeOfWorkForASingleThread
= codes.size()/amountOfThreads;
}
public static void runThreads() {
do {
bots = new BruteforceBot[amountOfThreads];
System.out.println("Bots array is populated");
} while (bots.length != amountOfThreads);
for (int j = 0; j <= amountOfThreads - 1;) {
int finish = start + scopeOfWorkForASingleThread;
try {
bots[j] = new BruteforceBot(start, finish, codes);
} catch (Exception e) {
System.err.println("Putting a bot into a theads array failed");
continue;
}
bots[j].start();
start = finish;
j++;
}
try {
for (int j = 0; j <= amountOfThreads - 1; j++) {
bots[j].join();
}
} catch (InterruptedException ie) {
System.err.println("InterruptedException has occured "
+ "while a Bot was joining a thread ...");
ie.printStackTrace();
}
// if there are any codes that are still remain to be tested -
// this last bot/thread will take care of them
if (remainderThread != 0) {
try {
int remainderStart = lastCodeIndex - remainderThread;
int remainderFinish = lastCodeIndex;
BruteforceBot remainderBot
= new BruteforceBot(remainderStart, remainderFinish, codes);
remainderBot.start();
remainderBot.join();
} catch (InterruptedException ie) {
System.err.println("The remainder Bot has failed to "
+ "create or start or join a thread ...");
}
}
}
I need your advise on how to improve the architecture of this app to make it successfully run with say, 20 threads instead of 8. My problem is - when I simply remove Thread.sleep(7200) and at the same time order to run 20 Thread instances instead of 8, the thread constantly fails to get a response from the server because it doesn't wait for 7 seconds for it to come. Therefore, the performance becomes not just less, it == 0; Which approach would you choose in this case?
P.S.: I order the amount of threads from the main() method:
public static void main(String[] args)
throws InterruptedException, org.openqa.selenium.SessionNotCreatedException {
System.setProperty("webdriver.gecko.driver", "lib/geckodriver.exe");
ThreadMaster tm = new ThreadMaster(8, new CodesGenerator().getListOfCodesFourDigits());
tm.runThreads();
Okay, so everyone can't wait until my question will get a response so I decided to answer it as soon as I can (now!).
If you would like to increase a performance of a Selenium WebDriver-based brute force bot like this one, you need to reject using the Selenium WebDriver. Because the WebDriver is a separate process in the OS, it does not even need a JVM to run. So, every single instance of the Bot was not only a thread managed by my JVM, but a Windows process also! This was the reason why I could hardly use my PC when this app was running with more than 8 threads (each thread was invoking a Windows process geckodriver.exe or chromedriver.exe). Okay, so what you really need to do to increase performance of such a brute force bot is to use HtmlUnit instead of Selenium! HtmlUnit is a pure Java framework, its jar could be found at Maven Central, its dependency could be added to your pom.xml. This way, brute forcing a 4-digit code takes 15 - 20 minutes, taking into account that after each attempt the website responds not faster than 7 seconds after each attempt. To compare, with Selenium WebDriver it took 90 minutes to accomplish the task.
And thanks again to #MartinJames, who has pointed that Thread.sleep() does let the hardware core to switch to other threads!

Java short delay

I have been trying to create a way to recreate the pokemon's "Rolling text" where one letter appears at a time. The problem is being able to create a timer short enough to make it reasonable.
This is what i have tried:
public static void roll(String text) {
int i = 0;
while(i < text.length()) {
try {
Thread.sleep(200); //1000 milliseconds is one second.
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
System.out.print(text.charAt(i));
i++;
}
}
This will work fine if i set the value in Thread.sleep to anything above 250. The problem is, if i set seconds below 250 then it will wait the entire length of time (If i tell it to wait 100 millisends 100 times, it will wait 10 seconds) before outputting anything.
Im not sure if this is a problem with the type of timer itself or if there is something else at play here.
You can use System.out.flush(); to force the buffer to be written out.

How to wait for the results to get displayed within a for loop while running selenium script?

How to wait for the results to get displayed within a for loop while running selenium script?
I have used below code:
for (k = 1; k < s2.getRows(); k++)
{
//redeem flow
d1.findElementByXPath("html/body/div[2]/div/div/div/div[2]/ul/li[3]/a").click();
d1.findElementByXPath("html/body/div[2]/div/div/div/div[2]/ul/li[3]/ul/li[2]/a").click();
d1.findElement(By.xpath("html/body/div[3]/div[2]/form/div[1]/div[2]/input")).sendKeys(s2.getCell(0, k).getContents());
//pause for list to be populated
try
{
Thread.sleep(1000L);
}
catch (Exception e)
{
}
// Get all items in autocomplete list
List<WebElement> items1 = d1.findElements(By.xpath("html/body/ul/li[3]/a"));
// Look for item
for( i= 0; i <items1.size();i++)
{
if(items1.get(i).getText().contains(s2.getCell(0, k).getContents()))
{
items1.get(i).click();
break;
}
}
//calendar handling
d1.findElementById("checkin").click();
d1.findElementByXPath("html/body/div[8]/div[2]/div/a/span").click();
d1.findElementByXPath("html/body/div[8]/div[2]/table/tbody/tr[3]/td[3]/a").click();
//Select Room Type
d1.findElementById("roomtype").sendKeys("Single");
//Occupant's Nationality
d1.findElementById("nationality").sendKeys("India");
//Click search button
d1.findElementByXPath("html/body/div[3]/div[2]/form/div[5]/input").click();
//after 2 min wait
d1.manage().timeouts().implicitlyWait(2, TimeUnit.MINUTES);
}
d1.manage().timeouts().implicitlyWait(2, TimeUnit.MINUTES); This statement does not ensure wait for the 2 minutes which is my requirement.
Using thread.sleep is never a good idea because it might cause strange results in case you are using a Framework like Testng/Junit since webdriver methods are mostly not Thread Safe , I would recomend you to use the concept of "Expected Conditions" .........
API documentation below
https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html
You can use below webdriver wait to solve this issue.
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(element));
wait.until(ExpectedConditions.elementToBeClickable(element));
wait.until(ExpectedConditions.presenceOfElementLocated(element))
If you're not waiting for a specific condition u could use Thread
Thread.sleep(1000)
This is in miliseconds so it will wait 1 second.
Otherwise use
WebDriverWait.until(condition-that-finds-the-element)
You can find documentation about implicit and explicit waits here:
http://www.bizalgo.com/2012/01/14/timing-races-selenium-2-implicit-waits-explicit-waits/

Executing statement after 10 seconds

I am running my java listener codes.
What happens is that my server will send some command to the client.
Thereafter I want to wait and see in 10s if there is no reply, then keep retrying for 5 times.
Below is what I do.
//Select code from the db with the codeID, codeText.
//send the code to the client.
long t= System.currentTimeMillis();
long end = t+10000;
while(System.currentTimeMillis() < end) {
}
//Select from db to check if codeupdated.
If updated dont do anything else I need to repeat the above pause ?
I having issue to repeat it for 5 times?
There is no guarantee for your construct to last exactly 10 seconds, and it's very costly in terms of performance.
Just use Thread.sleep.
for (int i = 0; i < 5; i++) {
// TODO your request here
boolean success = true; // TODO change to whatever outcome of your
// request
if (success) {
break;
}
else {
try {
Thread.sleep(10000l);
}
catch (InterruptedException ie) {
// TODO handle interruptions if applicable
}
}
}
Use
Thread.sleep(10*1000); //sleep 10 seconds.
You should use Thread.sleep() to pause execution
It's well explained here :
http://docs.oracle.com/javase/tutorial/essential/concurrency/sleep.html

Categories

Resources