Para hacer este tutorial he dividido el entorno de trabajo en 2 soluciones:

  1. Proyecto: WebSite (Sitio Web a testear)
  2. Proyecto: Automation (Donde se alojarán los test de automatización)

 

1. Proyecto WebSite

Primero que todo debemos crear nuestra solución inicial de los test a través de los siguientes pasos:

Primero abrimos visual studio, entonces hacemos click en nuevo proyecto y dentro de la categoría de C# seleccionamos la plantilla de tipo MVC5 integrada dentro de visual studio, le damos el nombre al proyecto de WebSite.

 

2. Proyecto Automation

Ahora procedemos a crear otra solución para los test de automatización que será un proyecto de tipo libreria de clases al cual llamaremos AutomationTest:

Automation (1)

Entonces instalamos todas las librerías necesarias para que nuestro proyecto de automatización compile y realice las ejecuciones, esto lo haremos a través del panel de administración paquetes de NuGet y otra que será una herramienta para ejecutar los test que proviene de terceros, acá la lista de todas las librerías que se necesitan instalar:

  • Selenium.Support
  • Selenium.WebDriver
  • NUnit
  • NUnitTDNet
  • FluentAssertions
  • TestDriven.Net (Optional)

Ahora es necesario crear la estructura para escribir el codigo, separando los metodos y test en sus respectivas clases:

  • TestBase.cs
  • GlobalsWords.cs
  • Elements.cs
  • AHomePageTest.cs
  • BRegisterPageTest.cs
  • CLogInPageTest.cs

 

2.1 Clase TestBase.cs

Antes de mostrar el código de esta clase es importante conocer y entender como funciona y cual es el comportamiento del ciclo de vida de ejecución de los tests, en la siguiente imagen podemos ver este modelo en orden de prioridades.

Automation_LifeCycle

Este modelo es usado en el momento cuando tu posees una gran cantidad de test y tu deseas continuar con la ejecución de varios test sin que se interrumpa la ejecución de estos mismos una vez que se termina el proceso de tu clase o cuando se cierra el navegador, es bastante utilizado cuando se tiene test que hacer uso del login de un usuario y se desea tener al usuario siempre logueado, esto disminuye el tiempo de ejecución de los test siempre y cuando se tenga una buena planeación al momento de definir y usar los metodos.

 protected IWebDriver driver;

Declara la instancia del controlador web.

[OneTimeSetUp]
 public void OneTimeSetUp()
 {
 driver = new FirefoxDriver();
 driver.Manage().Window.Maximize();
 OnOneTimeSetUp();
 }

protected virtual void OnOneTimeSetUp(){}

Declara el método OneTimeSetUp con el atributo “[OneTimeSetUp]” incluido en el framework de NUnit, este método crea una nueva instancia del controlador utilizando el navegador Firefox, integrado y por defecto de la librería. Una vez el navegador sea abierto este se expandirá a ventana completa y luego definimos el método “OnOneTimeSetUp” lo dejamos vacio para que sea sobreescrito en las paginas de test con la funcionalidad que deseemos.

[SetUp]
 public void SetUp()
 {
 Console.WriteLine(@"Running {0}", GetTestName());
 OnSetUp();
 }

private static string GetTestName()
 {
 return TestContext.CurrentContext.Test.FullName;
 }

protected virtual void OnSetUp(){}

Este método Setup usa el atributo “[SetUp]“, lo usamos para escribir en la consola el nombre completo del test actual en ejecución incluyendo el nombre de su espacio de trabajo en la solución.

[TearDown]
 public void TearDown()
 {
 OnTearDown();
 string ResultTest = string.Empty;
 ResultTest = TestContext.CurrentContext.Result.Outcome.Status.ToString();
 if (driver == null) return;

 try {//Here the code to capture javascipt errors }
 finally
 {
 if (ResultTest.Equals("Failed"))
 {
 CaptureImage(ResultTest, string.Empty);
 }
 }
 Console.WriteLine(@"" + ResultTest + " {0}", GetTestName());
 }

private void CaptureImage(string folder, string captureName)
 {
 try
 {
 var captureDriver = driver as ITakesScreenshot;
 if (captureDriver != null)
 {
 var screenshot = captureDriver.GetScreenshot();
 var path = Path.Combine(TestContext.CurrentContext.WorkDirectory, folder);
 if (!Directory.Exists(path))
 {
 Directory.CreateDirectory(path);
 }

 string captureSuffix = string.Empty;
 if (!string.IsNullOrEmpty(captureName))
 {
 captureSuffix = "_" + captureName;
 }

 var filename = string.Format("{0}{1}.png", TestContext.CurrentContext.Test.FullName, captureSuffix);
 screenshot.SaveAsFile(Path.Combine(path, filename), ImageFormat.Png);
 }
 }
 catch
 {}
}

El método TearDown usa el atributo “[TearDown]“, este método lo usamos para escribir en la consola el estado con el que termina la ejecución del test y luego usamos un bloque para capturar los errores de tipo javascript y guardamos una captura de pantalla en caso de que el test falle.

[OneTimeTearDown]
 public void OneTimeTearDown()
 {
 OnOneTimeTearDown();
 if(driver != null)
 {
 driver.Manage().Cookies.DeleteAllCookies();
 driver.Quit();
 }
 }

El método OneTimeTearDown usa el atributo “[TearDown]“, este método verifica si el controlador tiene proceso activo, en este caso cierra, destruye y elimina el proceso asociado, aquí mas detalles acerca del método:

  • WebDriver.Quit() Este método es utilizado para destruir la instancia del controlador web, también cierra todos los navegadores asociados y mantiene segura la sesión, este método llama al metodo dispose.

 

2.2 Clase GlobalWords.cs

Antes de crear los test de automatización deberiamos hacer una inspección de todas los mensajes de respuesta que el sitio web nos arroja en las secciones que deseamos testear, esto es una buena practica al momento de escribir los test.

 public static string URLPage = "http://localhost:51492/";
 public static string EmailTest = string.Empty;
 public static string PasswordTest = "Kevin#"+DateTime.UtcNow.Year.ToString();

#region HomePage

 public static string TitlePageHome = "Home Page - My ASP.NET Application";

 public static string HomeTitle = "ASP.NET";
 public static string HomeParagraph = "ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.";
 public static string Homelink = "http://www.asp.net/";

 public static string HomeSubtitleCol1 = "Getting started";
 public static string HomeParagraphCol1 = "ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that enables a clean separation of concerns and gives you full control over markup for enjoyable, agile development.";
 public static string HomeSublinkCol1 = "http://www.asp.net/mvc";

 public static string HomeSubtitleCol3 = "Web Hosting";
 public static string HomeParagraphCol3 = "You can easily find a web hosting company that offers the right mix of features and price for your applications.";
 public static string HomeSublinkCol3 = "http://www.asp.net/#migrateidentity";

 public static string HomelinkText = "Learn more »";

#endregion HomePage
  • URLPage: variable usada para referenciar la pagina principal del proyecto.
  • EmailTest: variable usada para guardar el email creado en los test.
  • PassWordTest: variable usada para guardar la contraseña creada en los test.

2.3 Clase Elements.cs

Algunas veces necesitamos modificar el tiempo de espera de los métodos o adicionar funcionalidades que no están incluidas dentro de la librería de selenium, aqui un ejemplo sobre como sobrecargar el método “FindElement” y configurar el tiempo de espera pasandolo como un parametro.

public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds)
 {
 IWebElement element = null;
 if (timeoutInSeconds > 0)
 {
 try
 {
 var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
 element = wait.Until(ExpectedConditions.ElementExists(by));
 }
 catch
 {
 element = null;
 }

}
 Assert.IsNotNull(element, "Can't find the element: " + @by);
 return element;
 }

Al momento de inspeccionar y capturar las etiquetas una herramienta muy utilizada puede ser Firepath y Firebug (Firefox plugins) Aqui link para instalar, y una pequeña demostración sobre como referenciarlo usando el tipo “CSS selector” a través de las siguientes imágenes.

public static void ButtonClick(this IWebDriver driver)
 {
 var ButtonRegister = driver.FindElement(By.CssSelector(".btn.btn-default"));
 ButtonRegister.Click();
 }

public static void SendTextToField(this IWebDriver driver, string IdField, string text)
 {
 var EmailField = driver.FindElement(By.Id(IdField));
 EmailField.Clear();
 EmailField.SendKeys(text);
 }

2.4 Clase AHomePageTest.cs

La clase usa el atributo “[TestFixture]” del framework NUnit, esta clase hereda de la clase TestBase para poder reutilizar todos sus métodos.

 [TestFixture]
 public class AHomePageTest : TestBase {}

Nosotros podemos recargar el método “OnSetup” para indicar la url a abrir al iniciar y hacer una validación del titulo de la pagina.


 protected override void OnSetUp()
 {
 driver.Navigate().GoToUrl(GlobalsWords.URLPage);
 Assert.AreEqual(GlobalsWords.TitlePageHome, driver.Title, msgerror(GlobalsWords.TitlePageHome, driver.Title));
 }

Una forma correcta de escribir tus test es definir un buen nombre que enumere el numero del test escrito y detalle brevemente a que hace referencia el test, por ejemplo: TestCase###_LittleDescriptionHere.

[Test]
 public void TestCase001_ValidateSectionUpHome()
 {
 var Title = driver.FindElement(By.ClassName("jumbotron")).FindElement(By.TagName("h1"));
 Assert.AreEqual(GlobalsWords.HomeTitle, Title.Text, msgerror(GlobalsWords.HomeTitle, Title.Text));

 var paragraph = driver.FindElement(By.ClassName("lead"));
 Assert.AreEqual(GlobalsWords.HomeParagraph, paragraph.Text, msgerror(GlobalsWords.HomeParagraph, paragraph.Text));

 var link = driver.FindElement(By.CssSelector(".btn.btn-primary.btn-lg"));
 Assert.AreEqual(GlobalsWords.HomelinkText, link.Text, msgerror(GlobalsWords.HomelinkText, link.Text));

 link.Click();
 Assert.AreEqual(GlobalsWords.Homelink, driver.Url, msgerror(GlobalsWords.Homelink, driver.Url));
 }

A continuación podemos ver una pequeña demostración sobre como tu puedes ejecutar los test para verlos en acción:

Demo Automation

Aqui puedes descargar el codigo completo de este ejemplo.

Fuente original del articulo: Kevinricar24 Blog

Gracias y espero que este articulo sea de su agrado.