I am trying to build a bot with selenium. the problem is that from time to time the website logging me out without any notice. I know how to detect it, and I know the way to handle it. the problem is that it is not reasonable to check before every line if the server logged me out. this is what I can do:
ChromeDriver driver = new ChromeDriver();
driver.get(url);
Connect(driver, loginData);
if(isConnected(driver) == false)
reconnect(driver, loginData);
driver.findElement(By.id("element-id")).click();
if(isConnected(driver) == false)
reconnect(driver, loginData);
...
But checking if I need to reconnect every line is not a good solution.
I thought about making a thread that checks all the time if I disconnected but I don't know how to pause the main thread until I reconnect to the server when I find out I disconnected
You can have a solution similar to your own, but instead of creating your own wrapper to ChromeDriver, you can use EventFiringWebDriver for that.
you can run the check inside a while loop in a side thread, and if the server disconnects you, stop the main thread. after you reconnect, restart it again.
The website logging you out seems to be time out. As I guess, you are testing in a non-production environment, please look for how to set the time_out = 0 (no-expire).
Thread solutions would be too clumsy and a single non synchronous miss can produce undetectable erroneous results.
I solved it by wrapping ChromeDriver with a class of my own that checks before every operation if a disconnect has detected. if anyone has a better solution I would like to hear. This is my solution:
public java.util.List<WebElement> findElements(By by) throws disconnectException {
if(keepLogin) {
if(checkConnectionOver()) {
throw new disconnectException();
}
}
return driver.findElements(by);
}
public WebElement findElement(By by) throws disconnectException {
if(keepLogin) {
if(checkConnectionOver()) {
throw new disconnectException();
}
}
return driver.findElement(by);
}
public Object executeScript(String script, Object... args) throws disconnectException {
if(keepLogin) {
if(checkConnectionOver()) {
throw new disconnectException();
}
}
return driver.executeScript(script, args);
}
public void get(String url) {
driver.get(url);
}
public String getCurrentUrl() {
return driver.getCurrentUrl();
}
Related
For instance consider the below scenario.
App1: I have a multiple-threaded java app, which enters a lot of files in DB.
App2: when i access the DB using some other app, its slow in fetching results.
So when both apps work simultaneously, it takes great time for DB fetching results on the front-end app2.
Here, i want to pause all transactions(threads) on App1 for some 'x min' time. Considering a trigger has already been installed when app 2 is being used. So when App2 is idle, App1 will resume as if nothing happened. Please list some or one best approach to achieve this
Map<Thread, StackTraceElement[]> threads = Thread.getAllStackTraces();
for (Map.Entry<Thread, StackTraceElement[]> entry : threads.entrySet()) {
entry.getKey().sleep();
}
This didn't worked well.
Just to try:
private List<PausableThread> threads = new ArrayList<PausableThread>();
private void pauseAllThreads()
{
for(PausableThread thread : this.threads)
{
thread.pause();
}
}
And your Thread class will be something like this:
public class MyThread extends Thread implements PausableThread
{
private boolean isPaused = false;
#Override
public void pause()
{
this.isPaused = true;
}
#Override
public void run()
{
while(!Thread.currentThread().isInterrupted())
{
// Do your work...
// Check if paused
if(this.isPaused)
{
try
{
Thread.sleep(10 * 1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
And the PausableThread interface:
public interface PausableThread
{
void pause();
}
Posting a solution answer, for my scenario.
I created a global flag and used it as a switch.
SO now, before DB interaction i just added a condition [in various functions where threads were performing variety of jobs, this solved the instance issue i was worried about]
if(isFlagChecked){thread.sleep(someDefinedTime);}
wait here if flag is true
continue with business logic...[db transacts here]
So, my issue was solved with just this, although it wouldn't pause thread running in intermediate state, which is kind of a good thing - one less trouble.
Parallel, in my trigger function - i checked for the elapsed time and changed the flag to false after desired time has passed. Check code skeleton below.
#async
void pause() // triggered by parallel running app when required
{
isFlagChecked=true;
resumeTime=new Date(timeInMillis + (someDefinedTime)) // resume time to switch flag condition
while (true) {
if (new Date().compareTo(resumeTime) > 0)
isFlagChecked=false;
}
}
Tried and tested, all running well, the performance improved significantly [least for my scenario].
I'm working on a BDD project.
Sometimes the tests go too fast for the developers to see what is happening when they run them.
At the moment I'm solving it placing something like
Thread.sleep(humanWaitTime)
before each method but it defeats the purpose of writing efficient code.
Is there any way to set this globally so that it can easily be taken out when doing a regression test and not clutter my code?
Thank you!
You can use WebDriverEventListener and fake wait for not existing element,
you should:
create class: public class CustomDriverListener implements
WebDriverEventListener and implement all methods
in this class add next method:
private void fakeWaiter(WebDriver driver) {
WebDriverWait wait = new WebDriverWait(driver, 20);
try {
wait.until(listenerDriver -> listenerDriver.findElement(By.xpath("//[.='it'sFakeElement']")));
} catch (org.openqa.selenium.TimeoutException e) {
//ignore it
}
}
add invocation of this method to methods that you need, like:
#Override
public void afterFindBy(By by, WebElement element, WebDriver driver) {
fakeWaiter(driver);
}
#Override
public void afterClickOn(WebElement element, WebDriver driver) {
fakeWaiter(driver);
}
#Override
public void afterChangeValueOf(WebElement element, WebDriver driver, CharSequence[] keysToSend) {
fakeWaiter(driver);
}
#Override
public void afterScript(String script, WebDriver driver) {
fakeWaiter(driver);
}
Create EventFiringWebDriver object and register your
CustomDriverListener:
WebDriver webDriver = new ChromeDriver();
EventFiringWebDriver driver = new EventFiringWebDriver(webDriver);
driver.register(new CustomDriverListener());
Now if you use "driver" in your tests all operations will be slower(depend on timer in fakeWaiter method)
P.S. sorry for bad formatting =(
You can probably use Implicit wait,
driver.manage().timeouts().implicitlyWait(TimeOut, TimeUnit.SECONDS);
Lets say on top of your code block, you write:-
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
Then, before each line of your code, the webdriver instance will wait for 15 seconds, you don't have to give wait times after each statement.
The implicit wait will tell to the web driver to wait for certain amount of time before it throws a "No Such Element Exception". The default setting is 0. Once we set the time, web driver will wait for that time before throwing an exception.
I have created WebDriver tests which run for the same duration.
Some of the tests lest say ‘PopupX’ will appear at 30 seconds.
On some of the test ‘PopupX’ will appear at 60 Seconds
On some of the test ‘PopupX’ will appear at 35 Seconds
You understand the id.
The popup always has a unique Id being the ‘X’ to close the application and even different popups have the same ‘X’ close option.
Does anyone know of a way to constantly search and close ‘A form of continuous polling’ which will close the popup if it was to appear at anytime in any of the test cases?
I know the following method listed below works and can successfully close the popup:
public void closeGiveawayPopup() throws InterruptedException {
WebDriverWait wait = new WebDriverWait(driver, 10);
try {
List<WebElement> elements = wait
.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.cssSelector(".close")));
for (WebElement element : elements) {
if (element.isDisplayed()) {
element.click();
Thread.sleep(1000);
wait.until(ExpectedConditions.invisibilityOfAllElements(elements));
Thread.sleep(2000);
}
}
} catch (Exception e) {
throw (e);
}
I have tried to add the following method below in the TestNG 'BeforeMethod' annotation but the url dosnt even load:
public void closeGiveawayPopup() throws Exception {
try {
List<WebElement> elements = getDriver().findElements(By.cssSelector(".close"));
for (WebElement element : elements) {
if (element.isDisplayed()) {
element.click();
}
}
} catch (Exception e) {
throw (e);
}
}
Details of the popup have been listed below:
I don't think you are doing anything wrong Phil. #BeforeMethod annotation is the way to go. The only thing that needs improving is to include (if you don't have it already) a #BeforeClass annotation for your browser startup/shutdown respectively. Perhaps, this is why 'the browser does not even open' as you mention in your description above. So something like this:
#BeforeClass
public void initialSetup(String browser){
Webdriver driver = new browser ();
driver.get("https://www.buyagift.co.uk/");
}
#BeforeMethod
public void closeGiveAwayPopup(){
//same as your code
}
#Test(priority=1)
public void makeSureIarrivedOnTheHomePage(){
titleGrabbed = driver.getTitle().toString();
titleExpected = "Experience Days and Gifts from Buyagift";
Assert.assertEquals(titleGrabbed ,titleExpected )
}
#Test(priority=2)
public void clickLoginButton(){
//more actions
}
#AfterClass
public void shutDown(){
driver.quit();
}
The only way I can think of in order to have this 'continuous polling' effect that you are after is to make your #Test really really small (1 step at a time). This way hopefully you can achieve the desired effect. So don't bundle a lot of WebDriver actions under 1 #Test as you are increasing the risk of a pop-up appearing in the meantime.
The only thing that puzzles me is your comment 'the url does not even load'. Are you sure you are grabbing the actual pop-up and not closing the whole window?
If that is the case, or if the above does not work for you, try using Xpath instead of CSS. From your screenshot you need to expand both div[#id='competition_inner_ and outer details'] and find the close button somewhere (probably you are looking for an < input >, < i > or < button > tag, then I will be able to help you more and give you the full Xpath so you can try for yourself.
So something like this:
driver.findElement(By.xpath("//div[#id='competiton_giveaway_popup']//button[#id='close']"));
PS. Another thing that came to mind, double check that you are using actual Testng annotations instead of Junit as it is easy to get confused and misclick sometimes when importing from IDE (I'm looking at you Eclipse!). So you can delete the #BeforeMethod annotation and write it again making sure it points to Testng.
PS2. On your step#9 you have missed the
WebDriverWait wait = new WebDriverWait(driver, 10);
line. I hope this is not the one giving you trouble, please double check and let me know.
Best of luck!
I have a page crawler developed in Java using Selenium libraries. The crawler goes through a website that launches through Javascript 3 applications which are displayed as HTML in popup windows.
The crawler has no issues when launching 2 of the applications, but on the 3rd one the crawler freezes forever.
The code I'm using is similar to
public void applicationSelect() {
...
//obtain url by parsing tag href attributed
...
this.driver = new HtmlUnitDriver(BrowserVersion.INTERNET_EXPLORER_8);
this.driver.seJavascriptEnabled(true);
this.driver.get(url); //the code does not execute after this point for the 3rd app
...
}
I have also tried clicking on the web element through the following code
public void applicationSelect() {
...
WebElement element = this.driver.findElementByLinkText("linkText");
element.click(); //the code does not execute after this point for the 3rd app
...
}
Clicking on it produces exactly the same result. For the above code, I've made sure I am getting the right element.
Can anyone tell me what could be the problem I'm having?
On the application side, I cannot disclose any information about the html code. I know this makes things harder for trying to solve the problem and for that I apologize in advance.
=== Update 2013-04-10 ===
So, I added the sources to my crawlers and saw where in this.driver.get(url) it was getting stuck on.
Basically, the driver gets lost in an infinite refresh loop. Within a WebClient object instantiated by HtmlUnitDriver, an HtmlPage is loaded which continually refreshes seemingly without end.
Here is the code from WaitingRefreshHandler, which is contained in com.gargoylesoftware.htmlunit:
public void handleRefresh(final Page page, final URL url, final int requestedWait) throws IOException {
int seconds = requestedWait;
if (seconds > maxwait_ && maxwait_ > 0) {
seconds = maxwait_;
}
try {
Thread.sleep(seconds * 1000);
}
catch (final InterruptedException e) {
/* This can happen when the refresh is happening from a navigation that started
* from a setTimeout or setInterval. The navigation will cause all threads to get
* interrupted, including the current thread in this case. It should be safe to
* ignore it since this is the thread now doing the navigation. Eventually we should
* refactor to force all navigation to happen back on the main thread.
*/
if (LOG.isDebugEnabled()) {
LOG.debug("Waiting thread was interrupted. Ignoring interruption to continue navigation.");
}
}
final WebWindow window = page.getEnclosingWindow();
if (window == null) {
return;
}
final WebClient client = window.getWebClient();
client.getPage(window, new WebRequest(url));
}
The instruction "client.getPage(window, new WebRequest(url))" calls WebClient once again to reload the page, only to once more call this very same refresh method. This seems to go on indefinetly, not filling up the memory quickly only because of the "Thread.sleep(seconds * 1000)", which forces a 3m wait before trying again.
Does anyone have any suggestion on how I can work around this issue? I got a suggestion to create 2 new HtmlUnitDriver and WebClient classes which extend the original ones. Then override the relevant methods in order to avoid this problem.
Thanks again.
I solved my eternal refresh problem by creating a do nothing RefreshHandler class:
public class RefreshHandler implements com.gargoylesoftware.htmlunit.RefreshHandler {
public RefreshHandler() { }
public void handleRefresh(final Page page, final URL url, final int secods) { }
}
In addition, I extended the HtmlUnitDriver class and by overriding the method modifyWebClient, I set the new RefreshHandler:
public class HtmlUnitDriverExt extends HtmlUnitDriver {
public HtmlUnitDriverExt(BrowserVersion version) {
super(version);
}
#Override
protected WebClient modifyWebClient(WebClient client) {
client.setRefreshHandler(new RefreshHandler());
return client;
}
}
The method modifyWebClient is a do nothing method created in HtmlUnitDriver exactly for this purpose.
Cheers.
I'm working on a Java project where I need to have multiple tasks running asynchronously. I'm led to believe Executor is the best way for me to do this, so I'm familiarizing myself with it. (Yay getting paid to learn!) However, it's not clear to me what the best way is to accomplish what I'm trying to do.
For the sake of argument, let's say I have two tasks running. Neither is expected to terminate, and both should run for the duration of the application's life. I'm trying to write a main wrapper class such that:
If either task throws an exception, the wrapper will catch it and restart the task.
If either task runs to completion, the wrapper will notice and restart the task.
Now, it should be noted that the implementation for both tasks will wrap the code in run() in an infinite loop that will never run to completion, with a try/catch block that should handle all runtime exceptions without disrupting the loop. I'm trying to add another layer of certainty; if either I or somebody who follows me does something stupid that defeats these safeguards and halts the task, the application needs to react appropriately.
Is there a best practice for approaching this problem that folks more experienced than me would recommend?
FWIW, I've whipped-up this test class:
public class ExecTest {
private static ExecutorService executor = null;
private static Future results1 = null;
private static Future results2 = null;
public static void main(String[] args) {
executor = Executors.newFixedThreadPool(2);
while(true) {
try {
checkTasks();
Thread.sleep(1000);
}
catch (Exception e) {
System.err.println("Caught exception: " + e.getMessage());
}
}
}
private static void checkTasks() throws Exception{
if (results1 == null || results1.isDone() || results1.isCancelled()) {
results1 = executor.submit(new Test1());
}
if (results2 == null || results2.isDone() || results2.isCancelled()) {
results2 = executor.submit(new Test2());
}
}
}
class Test1 implements Runnable {
public void run() {
while(true) {
System.out.println("I'm test class 1");
try {Thread.sleep(1000);} catch (Exception e) {}
}
}
}
class Test2 implements Runnable {
public void run() {
while(true) {
System.out.println("I'm test class 2");
try {Thread.sleep(1000);} catch (Exception e) {}
}
}
}
It's behaving the way I want, but I don't know if there are any gotchas, inefficiencies, or downright wrong-headedness waiting to surprise me. (In fact, given that I'm new to this, I'd be shocked if there wasn't something wrong/inadvisable about it.)
Any insight is welcomed.
I faced a similar situation in my previous project, and after my code blew in the face of an angry customer, my buddies and I added two big safe-guards:
In the infinite loop, catch Errors too, not just exceptions. Sometimes unexcepted things happen and Java throws an Error at you, not an Exception.
Use a back-off switch, so if something goes wrong and is non-recoverable, you don't escalate the situation by eagerly starting another loop. Instead, you need to wait until the situation goes back to normal and then start again.
For example, we had a situation where the database went down and during the loop an SQLException was thrown. The unfortunate result was that the code went through the loop again, only to hit the same exception again, and so forth. The logs showed that we hit the same SQLException about 300 times in a second!! ... this happened intermittently several times with occassional JVM pauses of 5 seconds or so, during which the application was not responsive, until eventually an Error was thrown and the thread died!
So we implemented a back-off strategy, approximately shown in the code below, that if the exception is not recoverable (or is excepted to recover within a matter of minutes), then we wait for a longer time before resuming operations.
class Test1 implements Runnable {
public void run() {
boolean backoff = false;
while(true) {
if (backoff) {
Thread.sleep (TIME_FOR_LONGER_BREAK);
backoff = false;
}
System.out.println("I'm test class 1");
try {
// do important stuff here, use database and other critical resources
}
catch (SqlException se) {
// code to delay the next loop
backoff = true;
}
catch (Exception e) {
}
catch (Throwable t) {
}
}
}
}
If you implement your tasks this way then I don't see a point in having a third "watch-dog" thread with the checkTasks() method. Furthermore, for the same reasons I outlined above, I'd be cautious to just start the task again with the executor. First you need to understand why the task failed and whether the environment is in a stable condition that running the task again would be useful.
Aside to eyeballing it, I generally run Java code against static analysis tools like PMD and FindBugs to look for deeper issues.
Specifically for this code FindBugs didn't like that results1 and results2 are not volatile in the lazy init, and that the run() methods might ignore the Exception because they aren't explicitly being handled.
In general I am a bit leery of the use of Thread.sleep for concurrency testing, preferring timers or terminating states/conditions. Callable might be useful in returning something in the event of a disruption that throws an exception if unable to compute a result.
For some best practices and more food for thought, check out Concurrency in Practice.
how about this
Runnable task = () -> {
try{
// do the task steps here
} catch (Exception e){
Thread.sleep (TIME_FOR_LONGER_BREAK);
}
};
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(task,0, 0,TimeUnit.SECONDS);
have you tried Quartz framework ?