Mostrando entradas con la etiqueta Testing. Mostrar todas las entradas
Mostrando entradas con la etiqueta Testing. Mostrar todas las entradas

miércoles, 8 de octubre de 2014

Agrupar Test Unitarios en listas

Si, demasiado tiempo sin escribir por aquí, pero es que entre GenbetaDev y mi nuevo blog de Kinect, tengo pocas cosas que decir en esta, mi memoria de código.

Sin embargo estoy en un proyecto en donde somos varios desarrolladores, en donde yo pico mi propio proyecto en MVC + EF. Y en donde construyo mi propia batería de test, en medio de cienes de test de los demás desarrolladores.

Y como no me fio un carajo de los test de los demás (hay cosas como DeleteAllCustomers_Test), solo quiero llevar el control y lanzar los míos.

Y para eso Visual Studio 2013 me ofrece la posibilidad de construir listas de reproducción (playlist) de una muy sencillita.

sábado, 1 de febrero de 2014

Test unitarios de un Controller que devuelve IHttpActionResult

Sigo con el intenso aprendizaje de construir una API REST con ASP.NET Web API, y me encontraba con el problema de que necesitaba poder realizar los test a los fallos que me estaban enviando los desarrolladores de las app que consumen este API.

La parte buena de trabajar con Web API, es que utiliza´el patrón MVC, el cual me permite testear el controlador (incluso la vista si me pusiera), la dificultad es que nunca había testeado el interfaz de  IHttpActionResult.

Pero es bastante sencillo, y me ha mostrado una debilidad de mi formato de mensajes (que ya me habían avisado Ambrin y Julio).

Voy a probar que el resultado de una operación es efectivamente un código de error específico.

Para lo cual tengo una clase Error tal que así:

    public class MensajeDeError
   
{
       
public string Code { get; set; }
       
public string Message { get; set; }
       
public string MessageDetail { get; set; }
       
public string MoreInfo { get; set; }
    }

El Controlador que voy a testear es algo tal que así:

        [HttpPost] public IHttpActionResult PostItem(negociositem item)
        {
           
if (item != null)
            {
               
var accion = new Items();
               
var error = new MensajeDeError();

               
var resultado = accion.AddItem(item, out error);

               
if (error.Code == ObtenError.Sin_error().Code)
                {
return Json(resultado); }
               
else
               
{ return Json(error); }
            }
           
else
           
{
               
return Json(ObtenError.Item_no_valido());
            }
        }

Como creo que se lee fácilmente, lo que hago es intentar persistir un item. Y si tengo algún error, lo que me devuelve (en vez del objeto resultado) un objeto mensaje de error. (Y aquí está la debilidad de devolver dos mensajes diferentes).

¿Cómo pruebo esto? Haciendo un test que fuerce un error, y comprobando que el código de error sea el esperado.

using api.Controllers;
using api.Entidades;
using System.Web.Http.Results;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace api.Controllers.Tests
{
    [
TestClass()]
   
public class ItemsControllerTests
   
{
        [
TestMethod()]
       
public void PostItemTest()
        {
           
var accion = new ItemsController();
           
var item = new negociositem { business_id = 0,
                                                          name =
"borrame",
                                                          description =
"",
                                                          origin = 2, picture =
"" };

           
var resultado = accion.PostItem(item);

           
Assert.AreEqual("503", ((JsonResult<api.MensajeDeError>)resultado).Content.Code);
        }
    }
}

¿Qué es lo importante aquí?

Primero asegurarme que me estoy importando al proyecto de Testing los namespaces adecuados. Es decir, los que contienen los tipos de objeto que voy a usar (Controllers, y Entidades), y el interfaz de respuesta (System.Web.Http.Results).

Segundo (y que vuelve a mostrar la debilidad del formato de respuesta), debo asegurarme de que el tipo de la respuesta sea la esperada. Por ejemplo, si todo hubiese ido bien, no hubiera recibido un tipo MensajeDeError, si no un tipo negociositem… lo cual es incómodo para testear y trabajar con esta api (pero es bueno para reducir el consumo de tráfico ya que devuelve solo lo que necesitas.

A partir de aquí, se me habré el horizonte de poder probar como si estuviera enviando peticiones a la API como cualquier otra APP, y pudiendo hacer test casi de integración.

Espero que sea de utilidad para alguien.

 

 

martes, 16 de julio de 2013

No me sale el namespace del proyecto en los test

Hete aquí una muy buena razón para que MS vuelva a incluir dentro de Visual Studio 2013 la construcción automática de los Test Unitarios y de los proyectos de Test, partiendo de una clase o método.

Hago un proyecto de librería de clases con un solo fichero,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JamonEasy_DAL
{
   
public class OperacionesDAL
   
{
       
public void prueba()
        { }
    }
}

A esto que le añado a mano el proyecto de test, y ni corto ni perezoso le añado la referencia al proyecto padre.

Y aquí llega la sorpresa, al utilizar el using, el intellisense me indica que no existe el espacio de nombre JamonEasy_DAL!!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using JamonEasy_DAL;

namespace JamonEasy_DAL.Test
{
    [
TestClass()]
   
public class OperacionesDALTests
   
{
        [
TestMethod()]
       
public void pruebaTest()
        {
           
Assert.Fail();
        }
    }
}

¿Qué puede estar pasando?

En mi caso la solución ha sido fácil. El proyecto de librería de clases tenía como “target” el framework 4.5.1, y los test se construyen por defecto en 4.5, a secas.

Así, igualando hacia arriba o hacia abajo, se elimina el problema.

P.D. Échale un vistazo mi artículo en GenbetaDev sobre el Unit Test Generator, algo muy recomendable de instalar.

martes, 22 de marzo de 2011

Testing. No metas un Assert en un for…

Haciendo el test de un método que me ordena un DropDownList me encontré que me daba como fallido, a pesar de que visualmente si que comprobaba que ordenaba correctamente.

El código del test es algo así:

        [TestMethod()]
[HostType("ASP.NET")]
[UrlToTest("http://localhost/qclientes/")]
public void ordenarDropDownListEstadosTest()
{
/// Me traigo todos los estados y los cargo en el combo
DropDownList ddlEstados = new DropDownList();
ddlEstados.DataSource = EstadosContactoManager.GetListadoRaices();
ddlEstados.DataValueField = "id";
ddlEstados.DataTextField = "estado";
ddlEstados.DataBind();

DropDownList actual;
int indiceSiguiente = 0;
Boolean estaOrdenado = true;

/// Pruebo el método que ordena el combo por orden alfabético
actual = EstadosContactoManager.ordenarDropDownListEstados(ddlEstados);

Assert.IsNotNull(actual, "Ha devuelto un combo nulo");
Assert.IsTrue(actual.Items.Count > 0, "El número de items es 0");

/// Hago un bucle en donde compruebo que el valor del primer carácter del item sea menor o igual que el siguiente en la colección.
/// Se inicia en uno porque el primer item del combo es el de "Seleccione una opción" y, lógicamente, no está ordenado.
for (int indice = 1; indice < (actual.Items.Count - 1); indice++)
{
if (estaOrdenado)
{
indiceSiguiente = indiceSiguiente >= actual.Items.Count ? indice : indice + 1;
estaOrdenado = (int)actual.Items[indice].Text.ToUpper()[0] <= (int)actual.Items[indiceSiguiente].Text.ToUpper()[0];
}
}
Assert.IsTrue(estaOrdenado, "No está ordenado");
}


Mi primera opción fue meter el Assert.IsTrue dentro del for… pero me encontré que me está dando una excepción del propio Framework de testing. Por lo cual he creado una variable booleana que me hace la comparación a menos que aparezca algo que no está ordenado.



Y esto funciona muy bien.



Editado: El test me fallaba porque si la primera letra es en minúscula y la segunda en mayúscula los códigos ascci no coinciden con el orden visual. Por lo cual ambos caracteres los pongo en mayúscula y me quito el problema. Así mismo he quitado el uso de un substring, ya que le índice [0] me basta.

domingo, 13 de marzo de 2011

Cloud Day 2011–ALM Sessions. Testing Exploratorio.

By Luís Fraile.
073
A Luís lo llevo siguiendo desde hace mucho tiempo. Junto con Rodrigo y Bruno, fueron los tres cantores que me introdujeron el gusanillo del TFS y ALM por allí por finales del 2007, principios del 2008. Y, hasta el momento, a Luís siempre lo había visto mostrando sus enormes conocimientos teóricos y prácticos en el área de gestión del ciclo de vida de proyectos.
 
Luego, con el tiempo y la cercanía, descubrí que es un hombre renacentista. Es decir, sabe prácticamente de todo y de prácticamente todo sabe bien. Por lo cual, y ahora que su nueva empresa es especialista en todo lo relacionado con el testing de aplicaciones, no dudé ni un segundo en irme a escuchar lo que nos iba a enseñar durante dos horas.
 
Me voy a permitir un breve inciso para darle un tirón de orejas a Microsoft en su vertiente de organizador. No se le puede quitar media hora a una ponencia de este estilo. Y menos para saltar de un interesantísimo tema técnico a uno de venta comercial puro. A mi, personalmente, me pareció mal. Un pequeño detalle que no quita valor a un excelente evento pero que, sin este feo detalle, hubiera sido perfecto.
 
Luís inició la ponencia contándonos por encima lo que significa Agile y específicamente Scrum. Para que, partiendo de la filosofía Agil, lleguemos a una automatización y optimización de las labores del testing funcional. Ojo, la charla versaba sobre Tst funcionales. Ese lado tan olvidado del test. O que a tantos les he oído decir que no son recomendables por su fragilidad. Y que a mi, personalmente, me parecen mucho más útiles que una batería de test unitarios.
 
Han sido muchos conceptos conocidos, y muchos a los que me ha abierto los ojos y por ende la curiosidad. Y entre ellos quisiera destacar los siguientes:
 
* En el equipo ideal debería existir el especialista dedicado al testing. Ya que no es una labor sencilla y necesita, además de experiencia, talento. Es curioso como hay demasiados desarrolladores que caen en “Poner al código en el centro de todo” y se piensan que con sus conocimientos basta y sobra para hacer un buen testing.
 
* En mis primeros pasos en el test funcional, lo he atacado desde las herramientas de Visual Studio. CodedUI. Pero debo de echarle una ojeada larga al Test Manager. Que es la herramienta de test. No el pequeño subconjunto que yo estaba utilizando. También desde aquí un tironcito de orejas a Microsoft por sacar la utilidad para modificar CodedUI en un Feature Pack, ya que no hay forma humana de probarlo a menos que tengas una suscripción Ultimate (que es una pasta impensable para una empresa pequeña)
 
* Aún más fuera del alcance de los mortales está el Lab Management que te permite hacer auténticas virguerías al añadirlo a la fuerza de test del Test Manager y el Visual Studio. Y digo que está fuera de los mortales porque hay que montar un pollo de dinero y de infraestructura de aúpa. Y un master para configurarlo… Pero para eso ésta TestHousing (la empresa de Luís).
 
* Con ello accedemos a virguerías como IntelliTrace. Una caja negra (como la de los aviones) que permite hacer un seguimiento exhaustivo de nuestra aplicación en preproducción (en producción no se aconseja por el gran impacto en el rendimiento) y que nos permite hacer una depuración del código publicado. Si, el código publicado, no el que tengo en desarrollo. Descompila el código y te permite hacer depuración como si fuera el de desarrollo!!.
 
* Ante la pregunta de si podíamos obtener un IntelliTrace de una máquina que no fuera de desarrollo, Luís nos comentó que si. Que tienes los servicios TestAgent y TestRunner que permite ejecutar planes de test y obtener ese chorro de información acerca del funcionamiento de la aplicación.
 
* Partiendo de una historia de usuario, se desarrolló un plan de test compuesto a su vez de test funcionales. Poniéndonos la gorra de tester creamos el test funcional que debe pasar la aplicación, localizamos un bug, lo documentamos y se lo pasamos al tfs en forma de workitem para que, poniéndonos la gorra de desarrollador, flipar en colores del detalle de la información de la causa del bug, corregirlo, lanzarlo en nuestra batería de test codeUI y cerrar el bug. Como tester revisar que esté corregido y cerrar el bug.
 
* Todo esto enlazado con integración continua. En donde me he llevado la sorpresa que tengo que ponerme con Team Build ya que ofrece un montón de ventajas en el desarrollo, aunque sea Web. Y, además, me permite utilizar MSDeploy para publicar mis web de una forma mucho más ordenada y efectiva. No como ahora que lo hago con Publish Web.
 
* Para rematar, estas pruebas se automatizan y se introducen automáticamente en una Build. Para que vayas construyendo una batería de pruebas funcionales y de regresión que, en mi opinión, dejan en un dudoso sitio a las pruebas unitarias. Aunque a mi me resulta muy útil las pruebas unitarias para desarrollar a nivel de método/clase (ojo, no es TDD, hago un mix. A veces antes, a veces después).
 
Fuera del contexto de la charla también me demostró con un simple “Ctrl + ,” la potencia oculta de los atajos de teclado, que creo que me tengo que revisar.
 
Por último, Luís ha dado una clase magistral de cómo mantener a un auditorio interesado durante casi dos horas en algo que haría dormir a las piedras si no se tiene el talento y la experiencia como el ponente. Pena que los compromisos comerciales de Microsoft cerrara con demasiada premura esta excelente ponencia.
 
Y aún quedan dos ponencias mas…
 
P.D. He encontrado él vídeo de la sesión en GlobbTV.