I am trying to make an if statement so I can use my code in multiple situations.
When i try to assert displayed or enable I get in some situations an exception Iwebelement could not be found.
I want to make a statement that if element exist 'x' should happen and when element does not exist 'y' should happen.
As mentioned I tried Displayed, Enabled. I also tried asserFalse but that also didnt gave me the required result.
It was asked for code but I only need a if statement that let something true if element exist otherwise should skip it. When I do
if (element.Displayed)
{
}
But in some cases I get an exception and I dont want the exception
is this in a TestNG or JUnit test?
I would usually handle this in a normal case inside the if statement:
pseudocode:
if(exists(x)){
assertTrue(....);
}
else{
assertFalse(....);
}
Search for multiple elements and even if one exists (>0), then return true, otherwise, non of the elements with a specific By exist.
bool ElementExists()
{
return driver.FindElements(By.Id("your locator")).Count > 0;
}
Then just do
bool ElementExists(By locator)
{
TimeSpan originalWait = driver.Manage().Timeouts().ImplicitWait;
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(0);
bool exists = driver.FindElements(locator).Count > 0;
driver.Manage().Timeouts().ImplicitWait = originalWait;
return exists;
}
if(ElementExists(By.Id("your locator")))
{
//Do Stuff
}
else
{
//Do Stuff when element does not exist
}
Edit: Also reduce your implicit wait to 0 seconds so you don't wait long for your bool to return (the webdriver will wait for the element to appear as long as you told).
Your approach will work only when the element is displayed or exists , if not it will throw the exception and you are not handling that, so the script is failing for you.
You can create a method like below by handling the exception(I have written it in java , please make the required changes).
public static Boolean isElementDisplayed(WebDriver driver, By element) {
try {
driver.findElement(element).isDisplayed();
System.out.println("Element is displayed");
return true;
} catch (NoSuchElementException | ElementNotVisibleException e) {
System.out.println("Element not displayed");
return false;
}
}
And you can use the above method in you test cases 'n' number times like this.
if(isElementDisplayed(driver, By.xpath("locator")){
//do what you have to do if element is exists
}else{
//do what you have to do if element is not exists
}
Hope this will solve your problem
Related
Is there anything wrong with doing something like this? I am basically just trying to assert that these elements exist and if not then return false:
public static bool IsAllDataPresent()
{
try
{
Driver.Instance.FindElement(By.Id("id-a");
Driver.Instance.FindElement(By.Id("id-b");
Driver.Instance.FindElement(By.Id("id-c");
return true;
}
catch (NoSuchElementException)
{
return false;
}
}
Is this is wrong then any help would be greatly appreciated. I am new to try catch.
If there is a method that tells you what you need to know without throwing, then call it.
If there is not, then you are in what I call a "vexing exception" situation. The best way out of that situation is to write the method that is missing.
public static bool IsPresent(string id)
{
try
{
Driver.Instance.FindElement(By.Id(id);
return true;
}
catch (NoSuchElementException)
{
return false;
}
}
And now your method is sensible:
public static bool IsAllDataPresent() =>
IsPresent("id-a") && IsPresent("id-b") && IsPresent("id-c");
Notice how when you write the correct abstraction, your method bodies get nice and concise.
For your specific question about checking multiple things and using try-catch... there's no problem with that, other than if it does fail, you're throwing away the exception which would tell you which of the things was missing.
In general, if you're expecting to find elements, you should wait for them to exist. If they exist right now, no waiting is done.
Example:
WebDriverWait wait = new WebDriverWait(Driver.Instance, new TimeSpan(0,0,5));
wait.Until(ExpectedConditions.ElementExists(By.Id("id-a")));
wait.Until(ExpectedConditions.ElementExists(By.Id("id-b")));
wait.Until(ExpectedConditions.ElementExists(By.Id("id-c")));
return true;
If you don't wait, there's a risk you'll test the browser for an element which isn't there right now, but will exist in a few milliseconds time, and your script gives a premature, false negative, answer.
As you are trying to assert that these three elements exist and if not then return false you can optimize your code as per the code block below :
public static bool IsAllDataPresent()
{
if(Driver.Instance.FindElement(By.XPath("//*[#id='id-a' or #id='id-b' or #id='id-c']")).size() != 3)
{
Console.WriteLine("All the 3 elements exists")
return true;
}
else
{
Console.WriteLine("All the 3 elements doesn't exists")
return false;
}
}
I used below code and found that TRY block is not working for the situation when element is not present :
try
{
var actual = new WebDriverWait(m_WebDriver, TimeSpan
.FromSeconds(5))
.Until(ExpectedConditions
.ElementIsVisible(By.XPath(XpathUnderTest)))
.Displayed;
return actual;
}
catch (Exception ex)
{
return false;
}
I have a use-case where presence of Webelement is depend on other conditions so it is not present or visible all the time on webpage. If element is present then it's working and if element is not present then Try catch is not able to handle the scenario using you above code.
I also tried : bool isPresent = Driver.Findelements.(xpath).Count() > 0; // list
but it is not working as well if element is not present
As per your code block it's the right behavior as WebDriverWait with ElementIsVisible is correct.
As per the documentation, ExpectedConditions with ElementIsVisible will return the IWebElement once it is located and visible. In case the ExpectedConditions fails a Boolean value is returned back.
As in your try block you are defining :
var actual;
And trying to :
return actual;
So, irespective of the return from ExpectedConditions with ElementIsVisible your try block returns False Positive.
Solution :
WebDriverWait with ExpectedConditions must be implemented outside any Try-Catch block. Next steps can be decided with respect to the return type.
Is there any way to tell the C# compiler that a function never returns? I'm running into the following problem. This is a boiled down version for simplicity.
public int myMethod()
{
try
{
return anythingHere();
}
catch
{
Environment.Exit(1); //or a function which always either calls Environment.Exit or throws an exception
}
}
'package.class.myMethod()' not all code paths return a value.
If not, is there a general way to frame this sort of thing other than inserting unreachable code? Having a 'return 0' or somesuch after the Exit just seems ridiculous to me. As far as I know there is no way that a function can return from an Environment.Exit call, so no return value is needed if that branch is taken (if it threw an exception the function still wouldn't need to have returned a value).
EDIT:
Maybe something like this?
public T MyExit<T>()
{
Environment.Exit(1);
return default(T);
}
Still not entirely satisfactory though.
C# does not support this.
In fact, it is impossible to do this in the general case.
Make the method void, and pass in an object that contains the 'anythingHere' type of information you need as an out type, so that it can be set, but the method itself won't actually return anything.
public void myMethod(out anythingObject)
{
try
{
anything = new anythingObject(stuff goes here);
}
catch
{
Environment.Exit(1); //or a function which always either calls Environment.Exit or throws an exception
}
}
I'm not sure if it's what you're looking for, but this would avoid unreachable code:
public int myMethod()
{
int retVal = 0;
try {
retVal = anythingHere();
} catch {
Environment.Exit(1);
}
return retVal;
}
It might be better to throw an exception than to call Environment.Exit. If someone else used your class, and their process suddenly shut down, they'd be pretty surprised. By throwing an exception you can at least explain why the problem happened.
At the top level entry point of your app (i.e., Main) you could then set up a global exception handler (AppDomain.UnhandledException) that handles all exceptions and calls Environment.Exit.
Make it a void, instead of an int.
public void myMethod(out int i)
{
try
{
i = anythingHere();
}
catch
{
Environment.Exit(1);
}
}
I want an extension method or generic method where I want code execution to continue even there is some exception and keep recording the exceptions in a list. This is an example what I tried
public void ValidateName()
{
if (_customer.Name.Length < 5)
throw new Exception("shortname");
}
public void ValidateAge()
{
if (_customer.Age < 5)
throw new Exception("short age");
}
internal void Validate()
{
this.CatchAndContinue(delegate()
{
this.ValidateName(); // throws exception and add to list
this.ValidateAge(); // but this should also execute
});
}
public void CatchAndContinue(Action action)
{
try
{
action();
}
catch (Exception ex)
{
exceptions.Add(ex);
}
}
For current class I can pass exceptions to ValidateName and ValidateAge method, but I want if we can do the way I want, with little change in validate() method body. I know semantically it sounds weired but I need lot of places to do this. Or if there is something better to achieve it
EDIT
This validation is simple example, not in all scenerio it will be validator only. By the way in this case I want to provide UI the list of errors and why throw, because when model constructed from DB (due to wrong data in DB) such objects should not be created. These are just examples of concern
Don't use exceptions for control flow.
Instead, your validate method should return a bool, and let the client of the validate method decide what to do. One step beyond that is return a ValidationResult with a ValidationStatus property that indicates success or failure and a Message property that records the reason that validation failed.
Yield / return may be useful to you.
http://msdn.microsoft.com/en-us/library/9k7k7cf0%28v=vs.80%29.aspx
Does it have to be exceptions?
To clarify:
internal IEnumerable<string> Validate()
{
if( _customer.Age > 5 ) { yield return "Too Old"; }
if( _customer.Name.Length < 3 ) { yield return "Not enough name characters"; }
}
// using it
IEnumerable<string> errors = myCustomer.Validate();
if( errors.Length > 0 ) {
// uh oh, print out the errors!
foreach( string error in errors ) {
MsgBox(error);
}
}
Instead of throwing exceptions in the Validate methods, I would add to the exceptions list and return a bool value indicating success/failure (return part is optional, add it only if you care about the status of validation).
Something like:
public void ValidateName()
{
if (_customer.Name.Length < 5) {
LogValidationFailure("shortName"); // you can add more params if needed
return; // or return false if you need it
}
// do normal business here
}
Not only is this cleaner, it is better performing since try/catch and exception throwing are expensive.
I've noticed this problem happening a lot in most things I do, so I'm thinking there must be a design pattern for this.
Basically if an exception is thrown, attempt to solve the problem and retry. If I place it in the try, all it will do is catch the exception, but I want to retry whatever it was doing and if it fails again, retry again a certain number of times.
Is there a common pattern for this sort of stuff?
check this SO answer.. hope that helps u
Cleanest way to write retry logic?
public static class RetryUtility
{
public static void RetryAction(Action action, int numRetries, int retryTimeout)
{
if(action == null)
throw new ArgumenNullException("action");
do
{
try
{
action();
return;
}
catch
{
if(numRetries <= 0)
throw; // Avoid silent failure
else
{
Thread.Sleep(retryTimeout);
numRetries--;
}
}
}
while(numRetries > 0);
}
}
Call
RetryUtility.RetryAction( () => SomeFunctionThatCanFail(), 3, 1000 );
Credit goes to LBushkin
This runs indefinately but it would be easy to add a loop counter to the while clause
var solved = false;
var tries = 0;
while (!solved)
{
try
{
//Do Something
solved = true;
}
catch
{
//Fix error
}
finally
{
if(solved || IsRediculous(tries))
break;
tries++;
}
}
try/catch inside a loop, with a counter for retries?
EDIT: And your requirement of "retry whatever it was doing," you need custom logic for that, how to retry varies wildly (ie, reopen a stream, recreate the object, pause for X milliseconds, etc...), so you need it's own try/catch inside a loop for every atomic operation.
By "atomic operation" I mean a set of related statements, such as read a file. The whole file read into memory might be an atomic operation, for example.
On some limited basis, you might want to put your try/catch into a loop, and force break if is ultimately successful. Such might be for internet access testing and you want user to have another attempt at connection.
Something like this, maybe:
int MAX_RETRIES = 5;
for (var attempt=1; attempt <= MAX_RETRIES; attempt++) {
try {
DoSomethingThatMightThrow();
}
catch (AnExceptionIKnowHowToHandle) {
if (attempt < MAX_RETRIES)
continue;
throw;
}
}
Depends what you are trying, but typically you want to check for the possibility of an exception happening PRIOR to executing the code that could cause an exception.
For example, check that a file exists before accessing it, and create it (or whatever) if it doesn't.
Are you sure exception handling is the proper methodology here? If you can "solve the problem" you can probably detect the error condition prior to calling the exception-generatiing code.
Exception handling is most natural for things which are truly exceptional. A failed Internet connection (as in the previous answer) is something that can be detected and handled before calling exception-throwing code.
Yes, it is quite common to have a loop with a number of retries where you break out of the loop on success. A couple of things:
You might want to add a delay before retrying so that you don't use up all your retries in just a few milliseconds before the temporary problem had time to fix itself.
If you eventually fail, you should throw the first exception you caught, not the last one. The second exception could be the result of failing to recover correctly from the first failure and might not help to debug the original problem.
Coding what others have already mentioned:
var success = false;
var attempts = 0;
var maxAttempts = 0;
do {
attempts++;
try {
/* your code */
success = condition;
} catch(SuperciliousException e) {
/* recover */
}
} while(!success && attempts < maxAttempts);