Code & QA

Extension Methods

I want to have a method in the framework which can take screenshots during my tests execution. Screenshots may be added to the summary reports for better understanding of a test execution flow. The IWebDriver can take screenshots, but I want all its actions being wrapped into a custom method for easier usage. I decided to implement the method as an extension method of IWebDriver interface because it will allow invoking the method such as if the IWebDriver actually had this method compiled inside its own native code.

Extension methods must be static and they must be located in a static class. I added new class to the Mapping project and named it Extensions.sc for the purpose.

For my screenshot-making method I have to add references to the following libraries:

● Selenium tool files: Selenium.WebDriverBackedSelenium.dll, ThoughtWorks.Selenium.Core.dll, WebDriver.dll, WebDriver.Support.dll;

● project Logger: file Logger.dll located in Logger/bin/Debug folder;

● reference to System.Drawing library

Below is the method that takes screenshots:

using Logger;
using OpenQA.Selenium;
using System;
using System.Configuration;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
namespace Mapping
{
    /// <summary>
    /// stores static extension methods for ISearcContext and other entities
    /// </summary>
    public static class Extensions
    {
        /// <summary>
        /// creates screenshot of opened browser window and saves it as a file
        /// </summary>
        /// <param name="driver">Current IWebDriver or IWebElement</param>
        /// <param name="screenshotDescription">Description of the screenshot</param>
        /// <returns>Path to saved picture file or empty string if an exception has occurred</returns>
        public static string TakeScreenshot(this IWebDriver driver, string screenshotDescription)
        {
            string screenshotFolder = Report.ReportFolderPath + "\\ScreenShots";
            string screenshotFileName = string.Empty;
            try
            {
                var screenshot = ((ITakesScreenshot) driver).GetScreenshot();
                Directory.CreateDirectory(screenshotFolder);
                screenshotFileName = screenshotFolder + "\\" + Regex.Replace(screenshotDescription, @ "\s+", " ").Replace(" ", "-") + "_" + DateTime.Now.ToString(CultureInfo.InvariantCulture).Replace(":", "-").Replace("/", "-").Replace(" ", "_") + ".jpeg";
                screenshot.SaveAsFile(screenshotFileName, System.Drawing.Imaging.ImageFormat.Jpeg);
            } catch (Exception e)
            {
                Report.AddWarning("Getting screenshot", "Screenshot picture is not saved with path '" + screenshotFileName + "'", e.Message);
            }
            return screenshotFileName;
        }
    }
}

Considering that taking a screenshot has a sense only for reporting, the best way for using the method is passing it as a parameter to the Report class methods which log tests execution events.

So, I built the Mapping project and added the reference to it in the Tests project.

Now TakeScreenshot method may be invoked in the tests:

using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;
using System.Collections.Generic;
using Logger;
using System.Reflection;
using Mapping;
namespace Tests {
    /// <summary>
    /// Represents collection of tests (test methods). Name of the class is the name of test collection
    /// Attributes [TestFixture] and [TestClass] indicates that the class is a test suite (collection of tests)
    /// </summary>
    [TestFixture]
    [TestClass]
    public class Example: BaseTest {
        /// <summary>
        /// Test method that performs searching with Google and verifies page title after the search
        /// </summary>
        [Test]
        [TestMethod]
        public void GoogleSearch() {
            const string searchTerm = "selenium";
            var scope = new Dictionary < string,
                string > {
                    {
                        "Navigate to Google search page",
                        "Google search page is loaded"
                    },
                    {
                        "Do nothing",
                        ""
                    },
                    {
                        "Perform search on the term " + searchTerm,
                        "Title of search result page starts with " + searchTerm
                    }
                };
            Report.StartTestCase(GetType().Name, MethodBase.GetCurrentMethod().Name, "Google Search", scope);
            Report.RunStep();
            driver.Navigate().GoToUrl("http://www.google.com");
            Report.AddInfo("Navigation to Google Search page", string.Empty, driver.TakeScreenshot("Google Search page"));
            Report.RunStep();
            //no action - no screenshot. Let's pass this step without any screenshot
            Report.AddInfo("No action");
            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
            Report.RunStep();
            IWebElement query = driver.FindElement(By.Name("q"));
            query.Clear();
            query.SendKeys(searchTerm);
            IWebElement btnSearch = driver.FindElement(By.Name("btnG"));
            btnSearch.Click();
            Report.AddInfo("Search is performed", "Search result page is opened", driver.TakeScreenshot("Search button is clicked result"));
            wait.Until(d => d.Title.StartsWith(searchTerm));
            NUnit.Framework.Assert.IsTrue(driver.Title.StartsWith(searchTerm));
            Microsoft.VisualStudio.TestTools.UnitTesting.Assert.IsTrue(driver.Title.StartsWith(searchTerm));
            Report.AddInfo("Verification", screenshotPath: driver.TakeScreenshot("Search result"));
        }
    }
}

Interfaces       Table Of Content     Global variables

Leave a Reply

Your email address will not be published. Required fields are marked *


Notice: Undefined offset: 0 in /home/chyqruxavcln/public_html/learnseleniumtesting.com/wp-content/plugins/cardoza-facebook-like-box/cardoza_facebook_like_box.php on line 924