December 2008 - Artículos

Testeo unitario para SharePoint: La importancia de llamarse "Test"

Testing es algo que todos los desarrolladores deberíamos hacer, y muy pocos hacen. Por no decir “Testing intensivo y consecuente”, pues los números se reducen a prácticamente cero... si le da curiosidad, revise las estadísticas mostradas en:

Especialmente el segundo vinculo es interesante, aunque por experiencia propia me arriesgaría a decir que los porcentajes de aplicación de testeo son mucho, mucho mas bajos.

Siendo sincero, escribir software es una de las cosas más divertidas para hacer en el mundo (lo digo por deformación profesional, probablemente), pero hacer pruebas para ese mismo software es una de las más aburridas. Y en algunos casos, es simplemente imposible, como lo es hacer pruebas para SharePoint.

Pero para comenzar por el principio, hay que hablar algo sobre testing en general.

El mundo del testing es amplio y ajeno: hay tantos tipos de testeo como tipos de desarrolladores... pero mirándolo desde una perspectiva global, podemos decir que hay:

- “Unit Test” (Prueba unitaria) – verifica que las unidades individuales de código fuente funcionan como se espera. Normalmente la unidad de código más pequeña es una función, método o propiedad.
- “Regression Test” (Pruebas de regresión) – Cuando se modifica algo que ya ha sido probado que funciona (con el Unit Test), es necesario garantizar que sigue funcionando apropiadamente después de algún tiempo: este es el trabajo de Regression Test
- “Integration Test” (Pruebas de Integración) – Cuando todas las unidades (que ya han sido probadas con Unit y Regression Test) se unen para trabajar conjuntamente, es necesario garantizar que todas funcionen como una unidad apropiadamente. Este es el trabajo del Integration Test
- “System Integration Test” (Pruebas de Integración de sistemas) – puede ser visto como una ampliación del anterior: este test garantiza que nuestro sistema (que ya ha sido probado con Unit, Regression e Integration Tests) puede funcionar con otros sistemas externos apropiadamente

En cuanto a metodologías, mis dos hermanas sicólogas me enseñaron que hay tres tipos de pruebas: Black Box, White Box y Grey Box testing (el modelo ha sido tomado “prestado” de la psicología).

- “Black Box Testing” – la prueba no sabe nada sobre cómo funciona internamente el sistema a probar... solamente que si se le entregan algunos parámetros de entrada, deben salir algunos resultados. Black Box Testing le entrega parámetros a una función (correctos e incorrectos) y observa los resultados que la función devuelve
- “White Box Testing” – por el contrario, la prueba conoce perfectamente el funcionamiento interno del sistema a probar, y crea las pruebas basado en el.
- “Grey Box Testing” – ya se imaginaran lo que es, una mezcla de los dos.

Finalmente, es necesario hablar de algo que está de moda, “Test-driven development” (TDD). Esta es una técnica de programación basada en escenarios de prueba o de funcionamiento (Test o User Cases), bastante ligada a metodologías de desarrollo como Agiles, que indica que primero hay que hacer el diseño del software (sus clases, métodos, propiedades y eventos), luego generar las definiciones (el “esqueleto” del código), luego crear los métodos de prueba ANTES que el código mismo, y finalmente, crear el código para rellenar el esqueleto.

Bien, esto es más o menos la parte teórica. Como los desarrolladores de código que somos, ¿Qué es lo importante de todo esto?

  1. Primero que todo, y antes que nada, Unit Test. Unit Test me permite dormir tranquilo, pues me asegura que mi código funciona correctamente y seguirá funcionando después de que lo he modificado (¿se puede usar Unit Test como Regression Test? Esta es una discusión bizantina a la que nunca nadie llega a una conclusión, algo por el estilo a que es mejor CSharp o Visual Basic, o Windows o Linux. Vea por la ejemplo la discusión que surgió en el ultimo PDC al respecto en http://channel9.msdn.com/pdc2008/TL61/).
  2. Como segunda medida, si se está usando (o se quiere usar) TDD, la decisión de usar Black o White Test es importante... o, mejor dicho, si se quiere usar TDD, hay que usar Black Box Testing. Punto. O hay que iniciar una nueva discusión bizantina sobre si es posible iniciar el desarrollo en Black Box y luego continuarlo en White Box, lo que lleva al modelo de Grey Box...

Noten que hasta ahora he intentado no tomar partido por ninguno de los puntos mencionados. Todo porque mi punto es SharePoint, no discusiones teológicas sobre cómo, cuando y donde hacer testeo de software. Pero llegamos a la parte interesante: SharePoint.

Cuando se trata de crear Testeo Unitario para software creado por uno mismo, es decir, en donde se tiene el código fuente, construir las clases de prueba es largo y tedioso, pero es posible de hacer con las herramientas estándar para el efecto (como las que tiene Visual Studio mismo, por ejemplo). Cuando lo que se desea es testear código que utiliza el Modelo de Objetos de otro programa, como ocurre cuando se escribe software para SharePoint o cualquier otro servidor (SQL, Exchange, BizTalk, etc), es necesario “hacerle creer” a nuestro código que esta interactuando con el servidor, pero sin que lo haga en realidad, porque no se desean tener dependencias con él.

Imagínese una situación no tan hipotética: se crea un método que comprueba los derechos de una Librería de SharePoint; si se utiliza una instalación real de SharePoint para hacer las pruebas, es necesario mantener esa configuración por todo el tiempo del desarrollo y mas allá para garantizar que los resultados de las pruebas sean consistentes en el tiempo. Peor aún, todos los desarrolladores del grupo tienen que disponer de la misma instalación para que sus pruebas también sean consistentes entre desarrolladores. Esto es prácticamente imposible de conseguir y, además, muy engorroso. Para solucionar el problema existen diferentes tipos de herramientas que “falsifican” el Modelo de Objetos del servidor (Mockers, Stubbers, etc)

Como ya hemos dicho varias veces Carlos y yo, el problema con SharePoint y Unit Test es que el Modelo de Objetos de SharePoint tiene muchas clases selladas o sin constructor público. Este ha sido el gran problema hasta ahora para poder usar Mockers y Stubbers, pues ellos no saben qué hacer con un objeto sellado o sin constructor público. El posting “Testeo Unitario para SharePoint: acercándose a la respuesta definitiva – parte 1” que escribimos anteriormente comenzó a mostrar cómo se puede iniciar el testeo unitario para SharePoint usando la última versión de TypeMock. Las próximas partes continuaran con la parte práctica de la creación y codificación de las clases de prueba. Pero en esta segunda parte se trata de discutir la importancia de Unit Test, Regression Test, Black y White Box Testing y TDD.

Uno de las características más importantes de TypeMock es la relación intrínseca entre el código de trabajo y el código de testeo, es decir, el fabricante ha escogido por un modelo de “White Box Testing”. Veamos un ejemplo el ejemplo de una función que simplemente imprime los elementos de una Lista de SharePoint:

Código de trabajo:

        public void GetCollection01()
        {
            SPSite mySite = new SPSite("http://wsses");

            using (SPWeb myWeb = mySite.OpenWeb())
            {
                foreach (SPList myList in myWeb.Lists)
                {
                    foreach (SPItem myItem in myList.Items)
                    {
                        Console.WriteLine(mySite.Url + " - " + myWeb.Title + " - " + myList.Title + " - " + myItem.ID.ToString());
                    }
                }
            }
        }

Código de Prueba:
        [TestMethod()]
        public void GetCollection01Test()
        {
            SPWeb fakeWeb = Isolate.Fake.Instance<SPWeb>(Members.ReturnRecursiveFakes);
            SPList fakeList = Isolate.Fake.Instance<SPList>(Members.ReturnRecursiveFakes);
            SPItem fakeItem01 = Isolate.Fake.Instance<SPItem>(Members.ReturnRecursiveFakes);

            using (var recorder = RecorderManager.StartRecording())
            {
                SPSite myFakeSite = new SPSite("");
                recorder.ExpectAndReturn(myFakeSite.Url, "fakeSiteUrl").RepeatAlways(); 
                recorder.ExpectAndReturn(myFakeSite.OpenWeb(), fakeWeb);
            }

            Isolate.WhenCalled(() => fakeWeb.Title).WillReturn("fakeWeb");
            Isolate.WhenCalled(() => fakeWeb.Lists[2].Title).WillReturn("fakeList");
            Isolate.WhenCalled(() => fakeItem01.ID).WillReturn(1);

            Isolate.WhenCalled(() => fakeWeb.Lists[2].Items).WillReturnCollectionValuesOf(new List<SPItem>
               {
                    fakeItem01
               });

            Class1 target = new Class1();
            target.GetCollection01();

            var fakeItemList = fakeWeb.Lists[2].Items;

            foreach (SPItem item in fakeItemList)
            {
                Isolate.Verify.WasCalledWithAnyArguments(() => item.ID);
            }
        }

Para la prueba unitaria se está usando una combinación de “Natural Mocks” y el nuevo “AAA API” de TypeMocks. Observe un par de puntos específicos:

  • Cada objeto “real” necesita un objeto “mockeado”: myWeb -> fakeWeb, myList -> fakeList, etc
  • Para cinco líneas de código de trabajo se necesitan 17 líneas de código de prueba

Esto conlleva las siguientes consecuencias generales:

Para poder crear un objeto “fantasma” (un mock) que sustituya efectivamente al objeto “real” en la clase de trabajo, es necesario conocer explícitamente su construcción. Esto excluye directamente la utilización de TDD: código de prueba debe ser escrito antes del código de trabajo

  • Una consecuencia de esta consecuencia es que el código unitario deberá ser escrito por el desarrollador mismo que está escribiendo el código de trabajo: al final, es él/ella el que sabe que está haciendo. El peligro con esta construcción es que se van a escribir clases de prueba que casi siempre van a pasar el examen... voluntaria o involuntariamente, el desarrollador va a omitir las pruebas que tienen más posibilidades de fallar
  • Una segunda consecuencia de esta consecuencia es que el desarrollador probablemente utilizara más tiempo creando las clases de prueba que las clases de trabajo
  • Por la relación tan estrecha entre código de trabajo y de prueba, cuando se modifica algo en el código de trabajo, hay que modificar también el código de prueba. Es decir, Regression Test es imposible de realizar

El fabricante de TypeMocks está trabajando intensivamente para darle solución a estos problemas, y los primeros resultados van saliendo: ciertas partes del Framework de TypeMocks es capaz de crear mocks para trabajar con Black Box Testing, es decir, entregando un objeto “mockeado” al método de trabajo y revisando los resultados producidos, sin tener conocimientos de su funcionamiento interno.

En cualquier caso, la discusión de si testeo blanco o negro es el mejor, o si Test-Driven Development es realmente valido continuaran hasta el fin de los siglos. Lo importante para nosotros, los que estamos metidos en el lio de hacer que código funcione apropiadamente no son las discusiones teóricas, sino los Frameworks que nos permitan trabajar confortablemente. TypeMocks es hasta el momento lo que más se acerca a una solución viable para hacer testeo de código de SharePoint, así que vale más que la pena de darle por lo menos una mirada e intentar hacerlo funcionar.

Publicado por Carlos Segura con no comments
Archivado en:

Drupal and SharePoint. Dos formas de hacer una tortilla (charla en Navarra)

El próximo día 18 de diciembre tendremos en el Grupo de Usuarios de Navarra la charla (de los huevos y de los CKarlos), Karlos G. Liberal y un servidor hablaremos de algunas de las bondades de nuestras herramientas de trabajo (Drupal y SharePoint).

El magnifico cartel ha sido realizado por nuestros amigos de Sistema Formación.

La Agenda del evento es la siguiente:

La jornada será el jueves, 18 de diciembre
Hora de recepción: 18:00

Centros de Excelencia Software
Salón de actos
Plaza Cein, 1, Polígono Mocholi
Noáin Navarra 31110
España

AGENDA
18:30 - 19:30: Drupal and SharePoint. Dos formas de hacer una tortilla. Los CKarlos.
19:30 - 20:00: Celebración 2º aniversario de NavarraDotNet: zorionak zuri y tarta de cumpleaños
20:00 - 21:00: Drupal and SharePoint. Dos formas de hacer una tortilla. Los CKarlos
21:00 - ... : Cena!

Para apuntarse podéis hacerlos desde este enlace*
http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032393640&Culture=es-ES

Publicado por Carlos Segura con no comments
Archivado en: