I have just noticed that Appium & Selenium is taking at least 2 minutes to find element when element is not there.
I want to reduce that time for search.
Code is :
if(!driver.findElements(By.id(AppConstants.notificationcount)).isEmpty())
{
// DO SOMETHING
}
else
{
System.out.println("No Element available");
}
Now most of time my element not available so I want appium to check it and redirect quickly to ELSE part , but it is taking long time , Any solution?
Have you checked your implicit wait time?
It is 0 by default, but maybe you are setting it somewhere to a value > 2 mins:
driver.manage().timeouts().implicitlyWait(timeInSeconds, TimeUnit.SECONDS);
If your implicit wait time is bigger than 0 and you are searching for an element with
driver.findElements(...);
but your Element does NOT exist, then Selenium will wait the WHOLE specified time!
Selenium only does not wait, when at least one element is found. In this case it will search the page once and return immediately with the list of elements found.
So findElements() is without restriction great to check the existence of an element, but only good for checking non-existence when you specified a very low implicit wait time (or the default 0).
If you absolutely need an implicit wait time > 0 for whatever reason, then you can create your own method that handles this like in this solution.
In your case you could set implicit wait time to 0 right before your posted code:
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
// then follows your code:
if(!driver.findElements(By.id(AppConstants.notificationcount)).isEmpty())
{
// DO SOMETHING
}
else
{
System.out.println("No Element available");
}
If you need an implicit wait time other than 0 elsewhere then just set it back to the original value after your piece of code.
The quicker way to check is store the elements in a list and then check if it is empty
List<WebElement> elements = driver.findElements(By.id("AppConstants.notificationcount"));
if (elements.isEmpty()) {
System.out.println("No Element available");
}else{
elements.get(0).click();//if present click the element
}
Hope this helps you.
Related
The delay1 can only contain agent.paint. On the exit of the delay1, a new agent gets released from the delay.
But the released agent is not an agent.paint instead it is an agent.repair or agent.bwork.
The delay2, delay4, and delay7 can contain agent.repair and agent.bwork but these delays are full, so now the agent is a problem, which is not supposed to happen.
Problem:
In delay1 only agent.paint can go, after getting free from delay and In delay2, delay4 or delay7 only agent.repair or agent.bwork can go, if delay have them.
And that is not happening in the existing model.
I try to explain in the image below:
My existing approach which is no working.
There are several things that are incorrect in your model. First of all, please keep in mind that when you use the word agent in a flowchart block, it always refers to the agent contained in the current flowchart block from where you are calling it.
I assume, in the "on exit" function of delay1 you want to release an agent from delay which has a parameter paint == true. However, you wrote the function as
if (delay.size() > 0 && agent.paint == true) delay.stopDelay(delay.get(0));
The second condition agent.paint == true refers to the current agent in delay1 flowchart block and not the agent in the delay that you want to release. Additionally, you are calling stopDelay() for the agent at position 0 in the delay block, regardless of whether this agent is the correct agent.
Instead, you need to iterate over all agents contained in the delay flowchart block, find the agent that meets your condition and release this specific agent. Your code can look like this:
if (delay.size() > 0) {
Agent agentToRelease = null;
for (int i = 0; i++; i < delay.size() {
if (delay.get(i).paint == true) { // Note: The function delay.get(i) is very slow. See if you can use Collection instead.
agentToRelease = delay.get(i);
break;
}
}
if (agentToRelease != null) {
delay.stopDelay(agentToRelease);
}
}
The same goes for delay2, delay4 and delay7.
The "on enter" function of delay is always called by the agent that is currently entering the delay. Because you check the condition for this specific agent here, you can directly call stopDelay() for this agent in case the condition returns true. So the first part of your code should look like this (the same goes for the remaining conditions)
if (agent.paint == true && delay1.size() + moveTo.size() < 2) {
delay.stopDelay(agent);
} else if (...)
in delay you are using stopDelay with an agent without caring for the value of its 3 parameters.
So it's perfectly possible to release an agent that is NOT paint when delay1 is empty... and this agent will go to any of the other 3 delays... no reason why not to.
Besides this.. you have moveTo blocks that mess up your condition... so if an agent is in moveTo4 and delay2 is empty, it will go to delay 2 anyways... because why not? You don't have any restriction for that to happen
You are overcomplicating an extremely simple problem
I am learning automation through Selenium (using Java programming language), and I am working on a test case. The last step in my case involves checking for the presence of a button an a page, by using findElement.By.xpath, and I have two versions of the step. With either version, my entire test case passes. However, the two versions each generate a different result by themselves. If I use the first version, with the int, I get "Write review button' does not exist" result. If I use the second version with the Boolean, I get "Write review button' exists!"
Since the test case passes, and with the second version generating the 'button exists' result, the problem cannot be with the xpath, so the issue with the second version getting the wrong result must be in the logic, yet I cannot tell what it is.
I tried rerunning the case multiple times to see if the problem is a glitch, but same result. I tried finding similar problems online, but cannot find anything that shows exactly how my problem is wrong.
int i = driver.findElements(By.xpath("//ul[#class='comments_advices']")).size();
if (i > 0) { System.out.println("'Write review button' exists!"); }
else { System.out.println("'Write review button' does not exist :( ");
}
boolean reviewButtonPresent = driver.findElements(By.xpath("//ul[#class='comments_advices']")).size() > 0;
if (reviewButtonPresent = true) { System.out.println("'Write review button' exists!"); }
else { System.out.println("'Write review button' does not exist :( "); }
The two instances of code you have are essentially the same and I see no reason for them to perform differently. My guess is that it's a timing issue. To make it behave more consistently, I would add a wait for the review button to appear. Since the button may not be there at times, it will throw a timeout exception so you will need to catch that to have a clean pass/fail for each run. To do this, I would use the function below that returns a boolean based on whether the element exists or not after waiting.
public static boolean elementExists(By locator, int timeout)
{
try
{
new WebDriverWait(driver, timeout).until(ExpectedConditions.presenceOfElementLocated(locator));
return true;
} catch (Exception e)
{
return false;
}
}
The above method tests for the "presence" of the element which means, does it exist in the DOM? If you want to make sure that it's actually visible (and not just present), you will want to change .presenceOfElementLocated() to .visibilityOfElementLocated().
Since you are new to Selenium, I would also recommend that you use a common library to do your validations like JUnit or TestNG. This will keep you from having to write your own custom code for validations and go through the process of finding bugs in your own custom code. Using JUnit, you would use
Assert.assertTrue("Verify the review button exists", elementExists(By.xpath("//ul[#class='comments_advices']"), 10));
See the JUnit docs.
There are some differences between the two blocks of code.
Apparently your first code block is logically correct which is as follows:
Code:
int i = driver.findElements(By.xpath("//ul[#class='comments_advices']")).size();
if (i > 0)
System.out.println("'Write review button' exists!");
else
System.out.println("'Write review button' does not exist :( ");
Output:
Write review button' does not exist
But it's not perfect, which I will explain later in this discussion.
Your second code block is a bit deceptive as it contains two logical operators in the same line and you have left it to the compiler to decide the Operator Precedence which is a clear deviation from the best practices. Possibly you were lucky as > had more precedence then = as in:
boolean reviewButtonPresent = driver.findElements(By.xpath("//ul[#class='comments_advices']")).size() > 0;
Solution
Ideally you need to:
Induce WebDriverWait for the visibilityOfAllElementsLocatedBy().
Evalute the size() through a if()
Sample Code:
if (new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//ul[#class='comments_advices']"))).size()>0)
System.out.println("'Write review button' exists!");
else
System.out.println("'Write review button' does not exist :( ");
Outro
Operator Precedence:
The operators in the following table are listed according to their precedence order. The closer to the top of the table an operator appears, the higher its precedence. Operators with higher precedence are evaluated before operators with relatively lower precedence. Operators on the same line have equal precedence. When operators of equal precedence appear in the same expression, a rule must govern which is evaluated first. All binary operators except for the assignment operators are evaluated from left to right; assignment operators are evaluated right to left.
I want to check several attributes of element (for example, is element displayed and that it's content is not empty) and I also want to know is there any simple way to this, because now I have code like this:
result= adplace.findElement(By.xpath("../../..")).findElement(ADPL_CURRENT_STATUS).isDisplayed()
&& !(adplace.findElement(By.xpath("../../..")).findElement(ADPL_CURRENT_STATUS).getAttribute("innerText").equals(""));
And I want something like this (this is obviously not working code):
result= adplace.findElement(By.xpath("../../..")).findElement(ADPL_CURRENT_STATUS)
.isDisplayed() &&
.getAttribute("innerText").equals(""));
Is there any possibility to simplify my code?
Make a WebElement variable and reuse, no need to find the element again:
WebElement elm = adplace.findElement(By.xpath("../../..")).findElement(ADPL_CURRENT_STATUS);
result = elm.isDisplayed() && (!elm.getText().equals(""));
Note that I've also replaced the innerText with getText() method call.
I am new to Java test automation and trying to write a simple for statement that will find the existence of a particular account number that identifies the element that is present.
My problem is that I can't get the loop to go through more than once. It seems that it breaks out of the loop right away when the condition is false.
I have exhausted the search. Any pointers or example. Appreciate it folks.
Here is the complete cssSelector format for my element I am trying to loop through:
#edit_account_**1201** > div.row.delete-mode.hideout > div.col-md-4 >
div.btn.btn-danger.btn-sm
Simply, what I would like to achieve since I know the range of the edit_account numbers and the format is to loop through the range, lets say 1200 -1250. And Once the element/cssSelector if visible and present I break our of the loop. :-)
for(int i =1200; i<1250; i++){
System.out.println("Checking through now");
if(driver.findElement(By.cssSelector("#edit_account_"+i+DELETE_CONFIRMATION_BUTTON)).isDisplayed()){
driver.findElement(By.cssSelector("#edit_account_"+i+DELETE_CONFIRMATION_BUTTON)).click();
System.out.println("Account number deleted is:" + i);
break;
}
}
I bet you are getting an exception when you try to locate the initial element. Do you see an exception? If so, can you provide the stack trace?
Consider grabbing all the elements you need first with:
List<WebDriver> elements = driver.FindElements(By....whatever your locator is...)
And, then iterating through the list with a loop and running your assertions or conditional logic.
You can have two solution :
Try using driver.FindElements which will not throw an exception or
Try to catch the exception and continue back to the beginning of the loop after that.
loop{
try{
if(){
driver.findelement....
}
}
catch(){
}
}
I'm running Selenium on a site that changes the value of a disabled input text box using jquery. Looking at the HTML, the value of the input box continues to say "Not Available" even though the value is obviously changed.
I can get the current value using Firebug with
$("#inputid").val()
but I get the value "Not Available when I've used my selenium code:
driver.findElement(By.id("inputid")).getAttribute("value");
Any suggestions on how to get this value in Selenium? I want to avoid trying to use something like JavascriptExecutor but if that's the best solution it would be good to know.
I don't have access to the jQuery code so I can't help you there. Sorry :-/
If the value is changed by jQuery due to some DOM events, chances are your Selenium test is going to check for the new value too fast. You can get the value after it changes away from "Not Available" with something like this:
WebDriverWait wait = new WebDriverWait(driver,10);
String value = wait.until(new ExpectedCondition<String>() {
public String apply(WebDriver driver) {
String value = driver.findElement(By.id("inputid")).getAttribute("value");
if value.equals("Not Available")
return null;
return value;
}
});
(Disclaimer: It's been ages since I've written Java code so I may have goofed in the code above.) The wait.until call will run the apply method until it returns something else than null. It will wait for at most 10 seconds. The value returned by wait.until will be the value that was last returned by the apply that terminated the end. In other words, it will return the new value of the element.
You say
Looking at the HTML, the value of the input box continues to say "Not Available" even though the value is obviously changed.
Yes, that's a quirk of the DOM. When you change the value of the input field, the value attribute on the element that represent the input field does not change. What changes is the value property on the element. This is why you have to do $("#inputid").val(), not $("#inputid").attr('value').