3
\$\begingroup\$

I want to get a result from the website when I submit a form. There are several things that can go wrong.

In a simple scenario I want to return:

true - when form was submitted

false - when form wasn't submitted

null - when we don't know if form was submitted or not

I did that ugly try, because of NullReferenceException (if form is filled correctly, there would be no summary element, and if form is filled incorrectly, there would be no popup element).

How can I make this more elegant?

public bool? GetResult(TimeSpan timeout)
{
 var deadline = DateTime.Now.Add(timeout);
 do
 {
 // check if success
 try
 {
 var success = new WebDriverWait(Driver, TimeSpan.FromSeconds(5))
 .Until(ExpectedConditions.TextToBePresentInElement(Driver.FindElement(By.Id("summary")), "Success!"));
 if (success) return true;
 }
 catch (Exception ex)
 { }
 // check if not enough data
 try
 {
 var notEnoughData = new WebDriverWait(Driver, TimeSpan.FromSeconds(5))
 .Until(ExpectedConditions.TextToBePresentInElement(Driver.FindElement(By.Id("popup")), "Not enough data"));
 if (notEnoughData) return false;
 }
 catch (Exception ex)
 { }
 // check if too much data
 try
 {
 var tooMuchData = new WebDriverWait(Driver, TimeSpan.FromSeconds(5))
 .Until(ExpectedConditions.TextToBePresentInElement(Driver.FindElement(By.Id("popup")), "Too much data"));
 if (tooMuchData) return false;
 }
 catch (Exception ex)
 { }
 // check if empty data
 try
 {
 var tooMuchData = new WebDriverWait(Driver, TimeSpan.FromSeconds(5))
 .Until(ExpectedConditions.TextToBePresentInElement(Driver.FindElement(By.Id("popup")), "Empty data"));
 if (tooMuchData) return false;
 }
 catch (Exception ex)
 { }
 } while (DateTime.Now > deadline);
 return null;
}
Heslacher
50.9k5 gold badges83 silver badges177 bronze badges
asked Jun 5, 2019 at 13:04
\$\endgroup\$
9
  • \$\begingroup\$ You should at least include code for WebDriverWait (so we can review async operations on it) and Driver (so we can try to avoid null reference exceptions). And use StopWatch for verifying elapsed time. \$\endgroup\$ Commented Jun 5, 2019 at 16:07
  • \$\begingroup\$ That doesn't seem to be your working code. \$\endgroup\$ Commented Jun 5, 2019 at 19:07
  • \$\begingroup\$ @dfhwze WebDriverWait is part of Selenium api: seleniumhq.org/docs/04_webdriver_advanced.jsp. \$\endgroup\$ Commented Jun 6, 2019 at 6:28
  • \$\begingroup\$ @Heslacher it is. \$\endgroup\$ Commented Jun 6, 2019 at 6:28
  • 1
    \$\begingroup\$ @dfhwze chack my answer about the NRE \$\endgroup\$ Commented Jun 6, 2019 at 23:45

1 Answer 1

3
\$\begingroup\$

I did that ugly try, because of NullReferenceException (if form is filled correctly, there would be no summary element, and if form is filled incorrectly, there would be no popup element).

This problem can be easyly handled by a null check of the returned WebElement from the call to Driver.FindElement().

A little bit more problematic is IMO the looping condition because the condition only could evaluate to true if the passed TimeSpan is negativ. If this is what you want you really should place a comment there. If you didn't mean to pass a negative timespan then you should reverse the looping condition to DateTime.Now < deadline.

Extracting the repeated call to TimeSpan.FromSeconds(5) to a variable will make the code easier to read.

You know although copy & pasta will save time, you need to check if the pasted code is correct (empty data vs tooMuchData)

 // check if empty data
 try
 {
 var tooMuchData = new WebDriverWait(Driver, TimeSpan.FromSeconds(5))
 .Until(ExpectedConditions.TextToBePresentInElement(Driver.FindElement(By.Id("popup")), "Empty data"));
 if (tooMuchData) return false; 

Implementing the mentioned points will look like so

public bool? GetResult(TimeSpan timeout)
{
 var deadline = DateTime.Now.Add(timeout);
 var waitTimeout = TimeSpan.FromSeconds(5);
 do
 {
 WebElement summaryWebElement = Driver.FindElement(By.Id("summary"));
 if (summaryWebElement != null)
 {
 var success = new WebDriverWait(Driver, waitTimeout).Until(ExpectedConditions.TextToBePresentInElement(summaryWebElement , "Success!"));
 if (success) return true;
 }
 WebElement popupWebElement = Driver.FindElement(By.Id("popup"));
 if (popupWebelement != null)
 {
 var notEnoughData = new WebDriverWait(Driver, waitTimeout).Until(ExpectedConditions.TextToBePresentInElement(popupWebElement, "Not enough data"));
 if (notEnoughData) return false;
 var tooMuchData = new WebDriverWait(Driver, waitTimeout).Until(ExpectedConditions.TextToBePresentInElement(popupWebelement, "Too much data"));
 if (tooMuchData) return false;
 var emptyData = new WebDriverWait(Driver, waitTimeout).Until(ExpectedConditions.TextToBePresentInElement(popupWebElement, "Empty data"));
 if (emptyData) return false;
 }
 } while (DateTime.Now > deadline);
 return null;
} 

Because the checks for the popup text only differs from the expected text you could think about using a foreach loop over an array containing the expected strings.

answered Jun 6, 2019 at 23:35
\$\endgroup\$
1
  • \$\begingroup\$ the only thing I would change is to get rid of that DateTime for checking elapsed time. \$\endgroup\$ Commented Jun 7, 2019 at 4:31

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.