Getting the value of a text box from Selenium

by Tom Hundley 26. April 2013 07:55

This isn’t really a big deal to figure out, but there aren’t a lot of good posts about it so I figured I’d put one up.

Problem
I needed to get the value of a text box from Selenium.  My intuition told me that the “Text” property off the IWebElement interface would do it.  Nope… it just returns the inner html of the element, which isn’t what you’re looking for in as the value of a text box.

Solution
Use GetAttribute(“value”). 

EzPz.

Here’s a quick code sample:

 1: using System;
 2: using Microsoft.VisualStudio.TestTools.UnitTesting;
 3: using OpenQA.Selenium;
 4: using OpenQA.Selenium.Firefox;
 5:  
 6: namespace UnitTestProject1
 7: {
 8:     [TestClass]
 9:     public class UnitTest1
 10:     {
 11:         [TestMethod]
 12:         public void TestMethod1()
 13:         {
 14:             IWebDriver driver = new FirefoxDriver();
 15:             driver.Navigate().GoToUrl("http://localhost:32616/");
 16:  
 17:             IWebElement textBox = driver.FindElement(By.Id("testTextBox"));
 18:             
 19:             // Doesn't work
 20:             string value = textBox.Text;
 21:             
 22:             // Works
 23:             value = textBox.GetAttribute("value");
 24:         }
 25:     }
 26: }

 

Hope this helps someone.

Happy coding,

Tom Hundley
Elegant Software Solutions

Tags: ,

ASP.Net | Test Automation

The Open Closed Principle: A Simplified Example

by Tom Hundley 14. March 2013 06:03

You’ve no doubt heard of the application architecture acronym, “SOLID”.  Bob Martin (Uncle Bob) came up with this as a guideline for application architecture.  The acronym stands for:

  1. Single Responsibility Principle (a class should have one and only one reason to change)
  2. Open Closed Principle (a class should be open for extension but closed for change)
  3. Liskov’s Substitution Principle (subclasses implementations should do what you expect them to do)
  4. Interface Segregation Principle (classes shouldn’t have to implement interfaces they don’t need)
  5. Dependency Inversion Principle (don’t tie implementation to concrete dependencies, but instead code to abstractions (i.e.: interfaces))

When I talk to various folks, I find that a lot of people don’t really get the Open / Closed Principle.  To that end, I decided I’d do a quick write up which probably doesn’t do what Uncle Bob was expressing much justice at all, but is hopefully very simple to understand.

In a nutshell, the behavior of a piece of code should be able to be extended without changing it.  That sounds very academic to me, doesn’t really make a lot of sense, and doesn’t seem to have much real world value.  After all, a solution should only be as complicated as the problem you are trying to solve.  Well, another way of looking at this is to say that code which has been tested and put in production shouldn’t be changed.  This reduces the chance of introducing new bugs in existing code and thus keeps total cost of ownership down (less bugs = less $$).  Ok, that makes a little more sense, but how do you do it?

It’s easier to see this principle in action.  Thus, have a look at the code below.

This first code block violates the Open Closed Principle.  A dead give away (or commonly code a “code smell”) is the switch case statement.  Be on the lookout for those in your code; they are often good indicators of a worthwhile refactoring opportunities.

VIOLATION:

 1: using System;
 2: using System.Collections.Generic;
 3: using System.Linq;
 4: using System.Text;
 5: using System.Diagnostics;
 6:  
 7:  
 8: namespace ConsoleApplication1
 9: {
 10:     /*
 11:  * This example is a violation the Open Closed Principle (the O in SOLID), 
 12:  * which means that code is "open for extension, but closed for change".
 13:  * 
 14:  * Consider that the FeedTheAnimals method is far more complicated and has been tested
 15:  * and moved to production. If you need to add new functionality
 16:  * for a new animal, such as a cow, you have to change code which has already been tested. 
 17:  * 
 18:  * This isn't truly extensible.
 19:  */
 20:     
 21:     public enum AnimalType
 22:     {
 23:         Dog,
 24:         Cat,
 25:         Bird
 26:     }
 27:  
 28:     
public
class OpenCloseViolation
 29:     {
 30:         public void FeedTheAnimals(AnimalType animalType)
 31:         {
 32:             switch (animalType)
 33:             {
 34:                 case AnimalType.Dog:
 35:                     {
 36:                         Trace.Write("eat meat");
 37:                         break;
 38:                     }
 39:                 case AnimalType.Cat:
 40:                     {
 41:                         Trace.Write("eat fish");
 42:                         break;
 43:                     }
 44:                 case AnimalType.Bird:
 45:                     {
 46:                         Trace.Write("eat worms");
 47:                         break;
 48:                     }
 49:                 default:
 50:                     {
 51:                         Trace.Write("eat grass");
 52:                         break;
 53:                     }
 54:             }
 55:         }
 56:  
 57:         public void DoWork()
 58:         {
 59:             this.FeedTheAnimals(AnimalType.Dog);
 60:             this.FeedTheAnimals(AnimalType.Cat);
 61:             this.FeedTheAnimals(AnimalType.Bird);
 62:         }
 63:     }
 64: }

By contrast, the following code conforms to the Open Closed Principle.

 1: using System;
 2: using System.Collections.Generic;
 3: using System.Linq;
 4: using System.Text;
 5: using System.Diagnostics;
 6:  
 7: namespace ConsoleApplication1
 8: {
 9:     /*
 10:  * This example conforms to the Open Closed Principle (the O in SOLID), 
 11:  * which means that code is "open for extension, but closed for change".
 12:  * 
 13:  * In this example, the implementation is left to the subclasses and
 14:  * FeedTheAnimals never has to change to add new functionality.
 15:  * 
 16:  * Thus, this is truly extensible.
 17:  */
 18:     
 19:     public class Animal
 20:     {
 21:         public virtual void Eat()
 22:         {
 23:             Trace.Write("eat grass");
 24:         }
 25:     }
 26:  
 27:     public class Dog : Animal
 28:     {
 29:         public override void Eat()
 30:         {
 31:             Trace.Write("eat meat");
 32:         }
 33:     }
 34:  
 35:     public class Cat : Animal
 36:     {
 37:         public override void Eat()
 38:         {
 39:             Trace.Write("eat fish");
 40:         }
 41:     }
 42:     public class Bird : Animal
 43:     {
 44:         public override void Eat()
 45:         {
 46:             Trace.Write("eat worms");
 47:         }
 48:     }
 49:  
 50:     
public
class OpenCloseConformance
 51:     {
 52:         public void FeedTheAnimals(Animal animal)
 53:         {
 54:             animal.Eat();
 55:         }
 56:  
 57:         public void DoWork()
 58:         {
 59:             Animal dog = new Dog();
 60:             this.FeedTheAnimals(dog);
 61:  
 62:             Animal cat = new Cat();
 63:             this.FeedTheAnimals(cat);
 64:  
 65:             Animal bird = new Bird();
 66:             this.FeedTheAnimals(bird);
 67:         }
 68:     }
 69: }

That’s it.  It’s a lot easier than it sounds.  I hope this helps someone.

Happy coding,

Tom Hundley
Elegant Software Solutions

Tags: ,

Application Architecture | C#

Selenium ElementNotVisibleException: Cannot click on element

by Tom Hundley 10. January 2013 09:35

Problem Statement


I am using the Selenium WebDriver to click on a menu item which is not visible until you hover over a top level menu, and when I invoke the Click method on the IWebElement, an ElementNotVisibleException is thrown with the message of Cannot click on element.

The problem is that I have made the IWebElement visible by hovering over the top level menu.  It is, in fact, absolutely visible, thus this exception should not be thrown.  The Click method works just fine on other elements which are not hidden until the user hovers over the menu.

As an aside, here is the code I used to hover over the top menu:

 1: var womensShoesMenu = this.webDriver.FindElement(By.CssSelector("a.topNavLink[href='/Womens-Shoe-Store']"));
 2: var builder = new Actions(this.webDriver);
 3: builder.MoveToElement(womensShoesMenu).Build().Perform();
 4:  

This is the code I used to invoke the Click method:
 1: var wait = new WebDriverWait(this.webDriver, TimeSpan.FromSeconds(5));
 2: var womensBoots = wait.Until<IWebElement>((p) => this.webDriver.FindElement(By.CssSelector("#topNavigation ul div.menuItem a[href='/Womens-Boots']")));
 3: womensBoots.Click();
 4:  
 
I figured using the Wait code would fix the problem with the link not being visible, assuming the code is simply executing too quickly or something.  The debugger shows that the web element is definitely visible, so, what is going?  I can definitively say that it beats the hell out of me; for now, I’m chalking this up to a bug with Selenium WebDriver.  Fortunately, however, I found a solution to the problem.

Solution

Instead of calling the Click method on the Selenium IWebElement object, I used JavaScript instead.  This works like a champ, and so far, appears to be reliable.

 1: var womensBoots = this.webDriver.FindElement(By.CssSelector("#topNavigation ul div.menuItem a[href='/Womens-Boots']"));
 2: ((IJavaScriptExecutor)this.webDriver).ExecuteScript("arguments[0].click();", womensBoots);
 3:  

 

Updated Solution

I’m adding a second solution after posting this article.  It turns out that the Click method of IWebElement works just fine in my scenario above; I simply wasn’t using the WebDriverWait class correctly.  I really just needed to have the browser wait for 1 second after performing the hover on the top menu, and then all of the drivers I was testing (Firefox, Internet Explorer, and Chrome) worked great.  Here is the updated code:

private static void DoWait(int milliseconds)
{
    var wait = new WebDriverWait(webDriver, TimeSpan.FromMilliseconds(milliseconds));
    var waitComplete = wait.Until<bool>(
        arg =>
            {
                System.Threading.Thread.Sleep(milliseconds);
                return true;
            });
}
var womensBoots = webDriver.FindElement(By.CssSelector("#topNavigation ul div.menuItem a[href='/Womens-Boots']"));
DoWait(1000);
womensBoots.Click();
////((IJavaScriptExecutor)webDriver).ExecuteScript("arguments[0].click();", womensBoots);

 

Discussion

I’m new to Selenium, only having started using it as a developer a few days ago, so it is very likely I’m simply doing this wrong and I honestly have no idea of the problem I’m encountering is a bug or not.  I’ve read similar posts about this, so it seems to be a bug, but as I dig deeper into the system I’ll learn more.  Since Selenium is open source, if I get the time, perhaps I’ll even go spelunking into the code to find out and maybe even attempt to fix it!

Credit

A huge thank you goes out to “James” for solving this problem on Stack Overflow:

http://stackoverflow.com/questions/12082946/selenium-webdriver-org-openqa-selenium-elementnotvisibleexception-element-is-n

I hope this helps someone!

Happy Coding,

~Tom Hundley
Elegant Software Solutions

Tags: ,

Test Automation

Month List

RecentComments