(The code in this example is Visual Basic.net but could of course be easily transferred into C#). So we have set up Selenium (as described here) and followed some general tips (as described here). Now it’s time to write our first unit test in Visual Studio using Visual Basic.net and Selenium. We will do a rather simple test but it covers several aspects of web testing. We will write a test to check whether a link to our current domain dotnet-developer.de is returned as first result from bing when we search for “dotnet-developer.de”. So we have to write a webtest with these steps:
- Go to Bing.com
- Enter “dotnet-developer.de” into the search box
- Start search by pressing ENTER or clicking the Search-Button
- Check the first result returned by Bing.com
You could watch a video about the final result on Youtube at http://www.youtube.com/user/dotnetdeveloperde:
Open Bing Homepage
The first step is then to navigate to bing.com so first line of code is:
Enter search text into textbox
Now we want to enter “dotnet-developer.de” into the searchbox. So we need to find out details about the searchbox. Therefore we start Firefox and manually go to “http://www.bing.com” and inspect the homepage within firebug. Click on Firebugs “Inspect”-Icon and select the Searchbox. The corresponding HTML-Code is now marked in Firebug.
In the second line of Firebug use your right mouse-button and click on the leftmost element, in current case it’s “input#sb…..sq_qbox” (when you move the mouse on the items you might notice that Firebug marks there position within the web page). On the right-click menu select “Copy XPath”.
Now the following value is copied: //*[@id=”sb_form_q”] So in current case we got an ID, in other cases you get an Xpath like this: /html/body/table/tbody/tr/td/div/div/div/form/div
Both is fine, but if you have an ID I’d prefer to use the ID rather than the XPath because XPath changes if the design of the page changes but ID will still be the same until the field is renamed (which might appear only in rare cases). Now we need to click in this field from Selenium. First we need to get a handle to it:
Dim SearchBox As IWebElement SearchBox = GetWebElement(driver, By.Id("sb_form_q"), 10)
So we have a handle to the search box. Now we want to enter some text:
As the text is inserted we now want to start the search. This could be done in several ways, e.g. press enter:
Or we could grab the “Search”-Button and click it. So we click again the “Inspect” button in Firebug (as described above) and get the XPath for the button:
SearchButton = GetWebElement(driver, By.Id("sb_form_go"), 10) SearchButton.Click()
So after calling one of these 2 methods Bing should display a result page.
Check Result page
Now we do the same manually in our Firefox instance. So got to http://www.bing.com, enter “dotnet-developer.de” and start the search.
For the test we want to check the first result returned by Bing. So get a reference to it as already described above using Firebugs “Inspect” icon and get the XPath for the first link. It should be like this:
/html/body/div/div/div/div/div/div/div/div/div/div/ul/li/div/div/div/h3/a. So we get the web element as usual but we will see that the XPath depends on whether Bing e.g. displays adverts or not. For example when we use Bing to search for “Microsoft” we will get this XPath:
/html/body/div/div/div/div/div/div/div/div/div/div/ul/li/div/div/div/h3/a. See the difference? So using the proposed XPath might work now but will fail if Microsoft starts displaying ads for the search term. Anyway, it would be fine if you use this command:
FirstResult = GetWebElement(driver, By.XPath("/html/body/div/div/div/div/div/div/div/div/div/div/ul/li/div/div/div/h3/a"), 10)
But let’s try to make it work regardless of their ads. Having a closer look at the source code shows that Bing returns the search result in an unordered list of class “sb_results”.
So the better approach would be to start at list “sb_results” instead of the beginning of the document. Using XPath this is rather easy (If you are not familiar with Xpath you might start with the Wikipedia Article).
So we now have a handle to the first link in the Resultlist. Again we have several options. First we could check the text. It is available in WebElements property “Text”:
Dim Expected As String = "dotnet-developer.de | Tips for vb.net,…" Assert.AreEqual(Expected, FirstResult.Text, "Subject is not correct")
Of course this works fine, but only if the subject of dotnet-developer.de is not changed. So of course it would be better to check for the link, not for the text.
When we have a look at the source code of the Bing result page we see the structure of the first link looks like this:
<a h=”ID=SERP,5082.1″ href=”http://www.dotnet-developer.de/”><strong>dotnet-developer.de</strong> | Tips for vb.net,…</a>
As usual, the anchor has a ‘href’ attribute. Each Selenium Webelement has a method ‘GetAttribute’ where we could specify the attribute to be retrieved. So in current case we want to check attribute ‘href’:
Dim expected As String = "http://www.dotnet-developer.de" Assert.AreEqual(expected, FirstResult.GetAttribute("href"), "URL is not correct!")
Here is the full source code:
Imports System.Text Imports OpenQA.Selenium Imports OpenQA.Selenium.Firefox Imports OpenQA.Selenium.Support.UI <TestClass()> Public Class UnitTest1 Private testContextInstance As TestContext '''<summary> '''Gets or sets the test context which provides '''information about and functionality for the current test run. '''</summary> Public Property TestContext() As TestContext Get Return testContextInstance End Get Set(ByVal value As TestContext) testContextInstance = Value End Set End Property Public driver As IWebDriver Const HomePageURL As String = "http://www.bing.com/" <TestInitialize()> Public Sub Initialization() driver = New FirefoxDriver End Sub <TestCleanup()> Public Sub Termination() driver.Quit() End Sub <TestMethod()> Public Sub TestMethod1() Dim SearchBox As IWebElement Dim FirstResult As IWebElement 'Go to Bing Homepage driver.Navigate.GoToUrl(HomePageURL) 'Get Handle for Searchbox SearchBox = GetWebElement(driver, By.Id("sb_form_q"), 10) 'Enter Search Text SearchBox.SendKeys("dotnet-developer.de") 'Different ways to start the search 'Method 1: Press ENTER SearchBox.SendKeys(Keys.Enter) 'Method 2: Grab Search-Button and click it 'Dim SearchButton As IWebElement 'SearchButton = GetWebElement(driver, By.Id("sb_form_go"), 10) 'SearchButton.Click() 'Now get the first result returned by Bing search FirstResult = GetWebElement(driver, By.XPath("//ul[@class='sb_results']/li/div/div/div/h3/a"), 10) 'Method 1: Compare the subject Dim ExpectedText As String = "dotnet-developer.de | Tips for vb.net,…" Assert.AreEqual(ExpectedText, FirstResult.Text, "Subject is not correct") 'Method 2: Compare the link Dim ExpectedURL As String = "http://www.dotnet-developer.de/" Assert.AreEqual(ExpectedURL, FirstResult.GetAttribute("href"), "URL is not correct!") End Sub ''' <summary> ''' Retrieve Web Element using default driver and default timeout ''' </summary> ''' <param name="definition">Definition of the WebElement to grab</param> ''' <returns></returns> ''' <remarks></remarks> Private Overloads Function GetWebElement(ByVal definition As OpenQA.Selenium.By) As IWebElement Const DefaultTimeout As Integer = 10 Return GetWebElement(definition, DefaultTimeout) End Function ''' <summary> ''' Retrieve Web Element using default driver ''' </summary> ''' <param name="definition">Definition of the WebElement to grab</param> ''' <param name="timeoutSeconds">Seconds to wait until a timeout is thrown</param> ''' <returns></returns> ''' <remarks></remarks> Private Overloads Function GetWebelement(ByVal definition As OpenQA.Selenium.By, ByVal timeoutSeconds As Integer) As IWebElement Return GetWebelement(driver, definition, timeoutSeconds) End Function ''' <summary> ''' Waits until the given element is enabled and visible ''' </summary> ''' <param name="webDriver"></param> ''' <param name="definition"></param> ''' <param name="seconds"></param> ''' <returns></returns> ''' <remarks>Needs to wait for .displayed because for e.g. in a collapsed Treeview all nodes are available but not visible ''' if the parent node is collapsed and therefore the following error would appear: ''' OpenQA.Selenium.ElementNotVisibleException: Element is not currently visible and so may not be interacted with ''' </remarks> Private Overloads Function GetWebElement(ByVal webDriver As IWebDriver, ByVal definition As OpenQA.Selenium.By, ByVal seconds As Integer) As IWebElement Dim wait As New WebDriverWait(webDriver, TimeSpan.FromSeconds(seconds)) wait.Until(Function(d) Return d.FindElement(definition).Enabled And d.FindElement(definition).Displayed End Function) GetWebElement = webDriver.FindElement(definition) End Function End Class