How can I catch whether the element is not visible - c#

I'm trying to create a script where I can check if the element is or is not displayed on the UWP app. I have a methods that checks if the element is Displayed or Not Displayed..
if the element is actually displayed and I called the "IsElementDisplayed", the test seems to works fine and continue the test execution.. But when the element is really NOT displayed and I called the "IsElementDisplayed", It doesn't return false boolean value.. but it just stops the test execution and says, "no such given parameters found"...
Please check my sample code....
I have a class which contains my locators and returns the instance of WindowsElement:
protected WindowsElement Id(string id)
{
return Driver.FindElementById(id);
}
protected WindowsElement XPath(string xpath)
{
return Driver.FindElementByXPath(xpath);
}
protected WindowsElement Name(string name)
{
return Driver.FindElementByName(name);
}
protected WindowsElement AccessibilityId(string id)
{
return Driver.FindElementByAccessibilityId(id);
}
and then I have Page class which contains properties of my elements.. sample code below:
public WindowsElement SaveObligation_Btn => this.AccessibilityId("OBLGTN_saveObligation_btn");
public WindowsElement CancelObligation_Btn => this.AccessibilityId("OBLGTN_CancelObligation_btn");
public WindowsElement ObligationAdd_Btn => this.AccessibilityId("SMMRY_AddObligation_btn");
And lastly I have a testhelper class that contains methods such as:
public bool IsNotDisplayed(WindowsElement element)
{
try
{
Assert.IsFalse(element.Displayed, $"Element: {element} is not displayed on the page!");
return false;
}
catch (Exception)
{
return true;
}
}
but when I trying to call the "IsNotDisplayed" method to return false if it caught any exceptions.., My test execution stops and I will have an error that is pointing to my Locator class and says, the "element is NOT found with the given parameters"...
I expect the method "isNotDisplayed" should return false boolean value, so I can validate if the element is visible or not.

I'm not familiar with C#.
But in Python, I will write like this:
try:
element = //find your element
if element.is_displayed():
return True
else:
raise AssertionError
except Exception:
return False

first question is what you want to do when noElementIsDisplayed? Of course, it will catch some exceptions. In your scenario, if you do not want to do anything when exception thrown then you should leave catch block empty.
try the following code:
public bool IsNotDisplayed(WindowsElement element)
{
try
{
Assert.IsFalse(element.Displayed, $"Element: {element} is not displayed on the page!");
return false;
}
catch (Exception e)
{
// do nothing and it will continue your script.
}
}

This will return true if the element is displayed else it will return false.
C# Code
public bool IsNotDisplayed(WindowsElement element)
{
try
{
element.Displayed;
}
catch (Exception)
{
return false;
}
return true;
}
Java Code
public static boolean IsDispayed(WebElement webelement)
{
try {
webelement.isDisplayed();
} catch (Exception e) {
return false;
}
return true;
}
Python Code
try:
element = driver.find_element_by_xpath('XPATH')
if element.is_displayed():
return True
else:
raise AssertionError
except Exception:
return False

Try the below code for c#. This is an alternative..
private bool IsElementPresent(By by)
{
try
{
driver.FindElement(by);
return true;
}
catch (NoSuchElementException)
{
return false;
}
}

Related

Element.Disabled throws error as element not found

for my test I need this element.Disabled to return false.
When test reaches to a page where that element is not displayed , test gets failed with element not found.
below code fails as username textbox doesnot display on the page
if (VerifyUsernameTextBox())
{
do something
}
public bool VerifyUsernameTextBox()
{
return username.Displayed; // code fails with no element found while return false is expected .
}
What to do so I get element.Displayed as false .
You find the element by driver.findElement(), right?
Remember, findElement throws an exception if it doesn't find an element, so you need to properly handle it.
You can do like this:
private bool IsUsernamePresent(By by)
{
try
{
driver.findElement(by);
return true;
}
catch (NoSuchElementException)
{
return false;
}
}
then
public bool VerifyUsernameTextBox()
{
return IsUsernamePresent(By.Id("element_username_id"));
}

Check if element is present when using POM

I have an issue finding i good way of checking if an element is present.
I´m using Page Object Model when automating my test cases meaning i declare all elements in a specific class, and not in the actual [tests]. How can i transform this simple method for verifying declared elements like this:
private IWebElement LoginButton => driver.FindElement(By.Id("LoginButton"));
IsElementPresent(IWebElement element)
{
try
{
//Something something
}
catch(NoSuchElementException)
{
return false;
}
return true;
}
I had a similar issue not long ago:
Managed to include a retry strategy/policy in it, so I'm waiting for the element to exist in the DOM.
public static void WaitForElementToExistInDom(Func<IWebElement> action)
{
RetryPolicy.Do(() =>
{
if (!DoesElementExistInDom(action))
throw new RetryPolicyException();
}, TimeSpan.FromMilliseconds(Timeouts.DefaultTimeSpanInMilliseconds), TestConstants.DefaultRetryCount);
}
public static bool DoesElementExistInDom(Func<IWebElement> action)
{
var doesExist = false;
try
{
var element = action.Invoke();
if (element != null)
doesExist = true;
}
catch (StaleElementReferenceException)
{
}
catch (NullReferenceException)
{
}
catch (NoSuchElementException)
{
}
return doesExist;
}
And you can call it like this:
WebDriverExtensionMethods.WaitForElementToExistInDom(() => Map.YourElement);
If the element is stalled or not existing, internally we're going to handle the exceptions and try again.
And because the evaluation 'if the element exists in the DOM' is done when you're getting calling the element from the MAP, we're wrapping it in an Action/Func, this way the evaluation is done in method (and so the catching of the exceptions), you don't have to use find selector outside of the element map itself.
I think you are looking for something simple like
public bool ElementExists(By locator)
{
return Driver.FindElements(locator).Any();
}
You would call it like
if (ElementExists(By.Id("LoginButton")))
{
// do something
}
You can't pass in an element because in order to pass it in, you would have to locate it first which would not be possible (it would throw an exception) if it's not present.
If you are trying to check an existing element, you could do something like the below.
public bool ElementExists(IWebElement e)
{
try
{
bool b = e.Displayed;
return true;
}
catch (Exception)
{
return false;
}
}

Creating a generic function based on these three functions in a base class without adding parameters

I have multiple similar performing functions across many files in my project that all derive from a base class. Each of these files contains a function called IsAt() that returns a boolean based on whether I am on the correct page or not in my process. Below are some examples of the functions being used across these files..
Example 1.
public bool IsAt()
{
try
{
DriverUtils.WaitTillElementVisible(_driver, ObjectRepository.H1);
}
catch (WebDriverTimeoutException)
{
return false;
}
if (ObjectRepository.PageHeaderLocator.Text != ObjectRepository.textOnPageIdentifier)
return false;
Console.WriteLine($"Login Page loaded successfully");
return true;
}
Example 2.
public bool IsAt()
{
try
{
DriverUtils.WaitTillElementVisible(_driver, ObjectRepository.UseAuthCodeBy);
}
catch (WebDriverTimeoutException)
{
return false;
}
if (ObjectRepository.UseAuthCodeLocator.Text != ObjectRepository.textOnPageIdentifier)
return false;
Console.WriteLine("Select two factor provider page loaded successfully!");
return true;
}
Example 3.
public bool IsAt()
{
try
{
DriverUtils.WaitTillElementVisible(_driver, ObjectRepository.H1);
}
catch (WebDriverTimeoutException)
{
return false;
}
if (ObjectRepository.PageHeaderLocator.Text != ObjectRepository.TextInPageIdentifier)
return false;
Console.WriteLine("Forgot password page loaded successfully");
return true;
}
The Structure:
Based on the functions here is the structure here's how I think it would be implemented..
public virtual bool IsAt()
{
OpenQA.Selenium.By obj;
var message = "My message!";
try
{
DriverUtils.WaitTillElementVisible(_driver, obj);
}
catch (WebDriverTimeoutException)
{
return false;
}
if(obj.locator.text != obj.textOnPageIdentifier)
return false;
Console.WriteLine(message);
return true;
}
How can I implement these functions as a single generic function? Is it possible without introducing parameters to the function? eg. public bool IsAt(string message, obj myObject)
Do you mean this?
//example 1
public bool IsAt()
{
return this.IsAt(ObjectRepository.H1, ObjectRepository.PageHeaderLocator.Text, $"Login Page loaded successfully");
}
//example 2
public bool IsAt()
{
return this.IsAt(ObjectRepository.UseAuthCodeBy, ObjectRepository.UseAuthCodeLocator.Text, "Select two factor provider page loaded successfully!");
}
//example 3
public bool IsAt()
{
return this.IsAt(ObjectRepository.H1, ObjectRepository.PageHeaderLocator.Text, "Forgot password page loaded successfully");
}
//base class
protected bool IsAt(object element, string match, string message)
{
try
{
DriverUtils.WaitTillElementVisible(_driver, element);
}
catch (WebDriverTimeoutException)
{
return false;
}
if(match != ObjectRepository.TextInPageIdentifier)
return false;
Console.WriteLine(message);
return true;
}

How to avoid code duplication inside two methods?

I have two identical methods, but one of them have return statement inside try catch
public void A(Guid agentId)
{
var agent = _agentsProvider.GetAgentById(agentId);
var updateCompletionSource = C(agentId);
try
{
var cacheEntry = UpdateAgentMetadataCacheEntry(agent, true, false);
updateCompletionSource.SetResult(cacheEntry);
}
catch (Exception e)
{
updateCompletionSource.SetException(e);
}
}
private Entry B(IAgent agent)
{
var updateCompletionSource = C(agent.Id);
try
{
var cacheEntry = UpdateAgentMetadataCacheEntry(agent, false, false);
updateCompletionSource.SetResult(cacheEntry);
return cacheEntry;
}
catch (Exception e)
{
updateCompletionSource.SetException(e);
return GetPreviousCacheEntry();
}
}
How to collect identical part and create new method with this part?
Unless GetPreviousCacheEntry could have problematic side-effects, it seems to me that you don't need method A at all.
Just call method B and ignore the return value if you're not interested in it.
As noted in comments, the methods aren't identical other than the return statements though - because they use a different second argument for UpdateAgentMetadataCacheEntry, and they have different parameters too (one has a Guid and one has an Agent). You could refactor this into:
private Entry B(IAgent agent, bool foo)
{
var updateCompletionSource = C(agent.Id);
try
{
var cacheEntry = UpdateAgentMetadataCacheEntry(agent, foo, false);
updateCompletionSource.SetResult(cacheEntry);
return cacheEntry;
}
catch (Exception e)
{
updateCompletionSource.SetException(e);
return GetPreviousCacheEntry();
}
}
... with a meaningful name for foo, obviously. I'll assume the difference in parameter type isn't a problem in reality.
Like Jon said, you don't need method A. Just add another parameter for boolean value.
public void A(Guid agentId)
{
var agent = _agentsProvider.GetAgentById(agentId);
AnotherA(agent, true);
}
private Entry B(IAgent agent)
{
return AnotherA(agent, false);
}
private Entry AnotherA(IAgent agent, bool a)
{
try
{
var cacheEntry = UpdateAgentMetadataCacheEntry(agent, a, false);
updateCompletionSource.SetResult(cacheEntry);
return cacheEntry;
}
catch (Exception e)
{
updateCompletionSource.SetException(e);
return GetPreviousCacheEntry();
}
}

C# Refactoring of If Statement

I am experimenting with different areas of C# and refactoring best practices/patterns.
As can be seen the Validate method below has 3 child validation methods.
Is there a way to redesign this method/refactor it so that the if statement are remove? (possibly using Delegate?).
Also what general code standard improvements would you suggest?
public bool Validate()
{
bool validDump;
validDump = ValidateRecordIdentifiers();
if (!validDump)
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(
LogMessages.StatusMessages.JobValidationFailed));
return false;
}
validDump = ValidateTotals();
if (!validDump)
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(
LogMessages.StatusMessages.JobValidationFailed));
return false;
}
validDump = ValidateRecordCount();
if (!validDump)
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(
LogMessages.StatusMessages.JobValidationFailed));
return false;
}
LogLogic.AddEntry(LogLogic.GetEnumDescription(
LogMessages.StatusMessages.JobValidationPassed));
return true;
}
bool valid = false;
if(ValidateRecordIdentifiers() && ValidateTotals() && ValidateRecordCount())
{
valid = true;
}
/******AN Alternate Suggestion for the above code********/
bool valid = ValidateRecordIdentifiers() &&
ValidateTotals() &&
ValidateRecordCount();
/*******End Alternate Suggestion*************/
var statusMessage = (valid) ?
LogMessages.StatusMessages.JobValidationPassed :
LogMessages.StatusMessages.JobValidationFailed
LogLogic.AddEntry(LogLogic.GetEnumDescription(statusMessage));
return valid;
See short circuiting:
http://msdn.microsoft.com/en-us/library/2a723cdk%28VS.71%29.aspx
Framework:
class Validator
{
Func<bool> validatorDelegate;
Action failDelegate;
public Validator(Func<bool> v, Action fail)
{
validatorDelegate = v;
failDelegate = fail;
}
public bool Validate()
{
bool rc = validatorDelegate();
if (!rc) failDelegate();
return rc;
}
}
class ValidatorCollection : List<Validator>
{
Action successDelegate;
Action failDelegate;
public ValidatorCollection(Action failDelegate, Action successDelegate)
{
this.successDelegate = successDelegate;
this.failDelegate = failDelegate;
}
public bool Validate()
{
var rc = this.All(x => x.Validate());
if (rc) successDelegate();
return rc;
}
public void Add(Func<bool> v)
{
this.Add(new Validator(v, failDelegate));
}
}
Usage:
class test
{
public bool Validate()
{
return new ValidatorCollection(
FailAction,
SuccessAction)
{
valTrue,
valTrue,
valFalse
}.Validate();
}
public void FailAction()
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
}
public void SuccessAction()
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationPassed));
}
public bool valTrue()
{
return true;
}
public bool valFalse()
{
return false;
}
}
public bool Validate()
{
return Validate(ValidateRecordIdentifiers, ValidateTotals, ValidateRecordCount);
}
public bool Validate(params Func<bool>[] validators)
{
var invalid = validators.FirstOrDefault(v => !v());
if (invalid != null)
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
return false;
}
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationPassed));
return true;
}
You could modify your validate methods so that they take in the LogLogic parameter and add an entry themselves for failing.
They could still return a boolean value, and this could be used to keep your return as soon as possible.
return ValidateRecordIdentifiers(LogLogic)
&& ValidateTotals(LogLogic)
&& ValidateRecordCount(LogLogic);
The first thing that jumps out is duplication:
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
So I'd look to collapse it into something like:
public StatusMessages Validate() {
LogMessages.StatusMessages status = LogMessages.StatusMessages.JobValidationFailed;
if( ValidateRecordIdentifiers() && ValidateTotals() && ValidateRecordCount())
status = LogMessages.StatusMessages.JobValidationPassed;
LogLogic.AddEntry(status.ToString());
return status;
}
There's a number of different ways to write this but your method is short and readable. The suggestions posted so far are, imo, much less readable and harder to debug (where would you set a breakpoint?). I would leave this method as is and look for other refactoring opportunities.
You are writing the same error message regardless of which validation function fails. It might be more helpful to log a specific error message in each case.
Otherwise you can rewrite what you already have much simpler:
if (ValidateRecordIdentifiers() && ValidateTotals() && ValidateRecordCount())
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationPassed));
return true;
}
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
return false;
You can take a look at Validation Application Block and Code Contracts
You could do something simple like this:
bool validDump;
string message;
if ((!ValidateRecordIdentifiers()) ||
(!ValidateTotals()) ||
(!ValidateRecordCount()))
{
message = LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed);
}
else
{
message = LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationPassed);
validDump = true;
}
LogLogic.AddEntry(message);
return validDump;
Maybe:
public bool Validate()
{
if (ValidateRecordIdentifiers() && ValidateTotals() && ValidateRecordCount())
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationPassed));
return true;
}
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
return false;
}
This looks to me like a case for structured exception handling. It looks like an exception condition that you are handling in the sense that something invalid has been input, and it results in abandoning the process. Have you considered using try/catch in the parent function and throw within the child functions to handle this?
Example:
public bool Validate()
{
try
{
ValidateRecordIdentifiers();
ValidateTotals();
ValidateRecordCount();
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationPassed));
return true;
}
catch (ValidationException ex)
{
LogLogic.AddEntry(ex.status);
return false;
}
}
class ValidationException : ApplicationException
{
public readonly LogMessages.StatusMessages status;
ValidationException(LogMessages.StatusMessages status)
{
this.status = status;
}
}
void ValidateRecordIdentifiers()
{
if (bad)
throw new ValidationException(LogMessages.StatusMessages.JobValidationFailed);
}
void ValidateTotals()
{
if (bad)
throw new ValidationException(LogMessages.StatusMessages.JobValidationFailed);
}
void ValidateRecordCount()
{
if (bad)
throw new ValidationException(LogMessages.StatusMessages.JobValidationFailed);
}
Edit: I generally don't like to use exception handling for errors that are not immediately reported out to the UI because exception handling can be costly, and excessive exception throwing can make the application harder to debug if you're trying to find real exception cases among a bunch of exceptions that aren't really "exceptional". But depending on your specific case, it may be appropriate. Just use with caution.
Your function does two things: validation and logging. You could separate them like this. This also lets you log these errors differently if you ever decide to do this.
public bool ValidateAndLog()
{
LogMessages.StatusMessages result=Validate();
LogLogic.AddEntry(LogLogic.GetEnumDescription(result));
return result==LogMessages.StatusMessages.JobValidationPassed;
}
private LogMessages.StatusMessages Validate()
{
//of course you can combine the next three ifs into one
if (!ValidRecordIdentifiers())
return LogMessages.StatusMessages.JobValidationFailed;
if (!ValidateTotals())
return LogMessages.StatusMessages.JobValidationFailed;
if (!ValidateRecordCount())
return LogMessages.StatusMessages.JobValidationFailed;
return LogMessages.StatusMessages.JobValidationPassed;
}
public bool Validate()
{
return LogSuccess(
new[] {ValidateRecordIdentifiers, ValidateTotals, ValidateRecordCount }
.All(v=>v()));
}
private bool LogSuccess(bool success)
{
LogLogic.AddEntry(LogLogic.GetEnumDescription(success
? LogMessages.StatusMessages.JobValidationPassed
: LogMessages.StatusMessages.JobValidationFailed
);
return success;
}
Value readability above all else (well, as long as it is in the same ballpark efficiency).
About the only changes I would make is to eliminate the unneeded variable, and use the function call in the conditional, and replace the ! operator with == false. This is easier to see for aging programmers like myself with bad eyesight :)
As implied by the comment of another poster, it is better to make the function read InvalidXX instead, to avoid using negation or == false and for better readability.
Also, as far as combining all the conditionals into a single "AND" statement, I would do that in lisp, but not in c#, because it will making debugging and tracing harder.
In particular, you probably don't want to put the same error message for each case - you should have a different one for each case so you know exactly what happened. Combining all cases into a single expression won't allow you to do this.
public bool Validate() {
if (ValidRecordIdentifiers() == false) {
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
return false;
}
if (ValidTotals() == false) {
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
return false;
}
if (ValidateRecordCount() == false) {
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationFailed));
return false;
}
LogLogic.AddEntry(LogLogic.GetEnumDescription(LogMessages.StatusMessages.JobValidationPassed));
return true;
}
As the statement of those if conditions are the same for all, so you can do the check in one condition and do the reset job at the below.
public bool Validate()
{
bool validDump;
if(ValidateRecordIdentifiers() && ValidateTotals() && ValidateRecordCount()) {
LogLogic.AddEntry(LogLogic.GetEnumDescription(
LogMessages.StatusMessages.JobValidationPassed));
return true;
}
LogLogic.AddEntry(LogLogic.GetEnumDescription(
LogMessages.StatusMessages.JobValidationFailed));
return false;
}

Categories

Resources