Testeo unitario de cubos OLAP

En Internet no se encuentran muchas páginas sobre cómo testear un cubo OLAP… probablemente, como en toda tecnología “emergente”, cada uno se las arregle como pueda y pocas cosas estén ampliamente extendidas. Sin embargo, con el resto de tecnologías “más convencionales” todo el mundo tiene una opinión formada sobre el testeo unitario o el “test driven development” (generalmente para bien). ¿Se pueden conciliar ambos terminos? ¿Puedo escribir “unit tests” para mis cubos OLAP?


La respuesta es “SIN DUDA”. El mundo del Business Intelligence puede beneficiarse en gran manera del testeo unitario, gracias a lo que se conoce como “Data Driven Unit Test”. ¿De qué va esto?


Analicemos las siguientes sentencias SQL y MDX, lanzadas respectivamente contra la base de datos “Adventure Works” y el cubo de Analysis Services correspondiente:




  • SELECT Production.Product.ProductNumber AS Product, 
        SUM(Sales.SalesOrderDetail.OrderQty) AS Quantity
    FROM Sales.SalesOrderDetail, Production.Product
    WHERE Sales.SalesOrderDetail.ProductID = Production.Product.ProductID
    GROUP BY Production.Product.ProductNumber
    ORDER BY Product ASC



  • SELECT NON EMPTY [Product].[Product Key].[Product Key] ON ROWS,
        [Measures].[Order Quantity]
    ON COLUMNS
    FROM
    [Adventure Works]


Si las ejecutamos, ambas producen resultados similares… una sobre el sistema OLTP y la otra sobre el sistema OLAP. Vaya, empezamos a entender… ¡si ambos sistemas producen resultados similares, eso debe significar que nuestro sistema OLAP funciona correctamente! Eso es el Data Driven Unit Testing, y nos vendrá de miedo para probar nuestros cubos. Recordemos que el escenario habitual en un desarrollo de BI será partir de un sistema existente, así que… ¿qué mejor prueba de que nuestro sistema funciona, que demostrar que devuelve los mismos resultados que el sistema de partida?. Cuantos más cruces de dimensiones comparemos con salidas del sistema OLTP, mejor será nuestra batería de tests.


Es difícil, por no decir imposible, tener una cobertura del 100% del cubo, pero como se suele decir, testear algo es infinitamente mejor que no testear.


Data Driven Unit Test en Visual Studio Team System


Para realizar testeo unitario guiado por datos, tenemos que partir de una tabla de base de datos en la que tendremos almacenado cada uno de nuestros juegos de pruebas. En el ejemplo que he puesto, si no disponemos de tabla, tendremos que crear una vista.



  • CREATE VIEW Test.vOrderQuantityPerProductKey AS
    SELECT
    Production.Product.ProductNumber AS Product,
    SUM(Sales.SalesOrderDetail.OrderQty) AS Quantity
    FROM Sales.SalesOrderDetail, Production.Product
    WHERE Sales.SalesOrderDetail.ProductID = Production.Product.ProductID
    GROUP BY Production.Product.ProductNumber

Este es el punto que menos me gusta, tener que partir obligatoriamente de una tabla accedida mediante OleDB y no poder partir de una sentencia SQL… pero bueno, sigamos a lo nuestro. Nos ponemos las botas de programar, nuestra música favorita, y creamos un nuevo proyecto de tipo “Test Project”.



Visual Studio creará por nosotros una clase de test, con un método de test. Tendremos que indicar que el método de test es “Data Driven”, para eso, editamos las propiedades del test e indicamos:



  • Data Connection String: Cadena de conexión a nuestra base de datos.

  • Data Table Name: El nombre de la tabla donde se encuentran los valores a probar, junto con los resultados esperados.

  • Data Access Method: Squential. Con esto indicamos que se deberá probar secuencialmente con todos y cada uno de los valores de la tabla.



Como resultado de la edición de estas tres propiedades, Visual Studio decorará nuestro método de test con un atributo DataSource, señal clara de que nuestro test es guiado por datos.


        [DataSource(“System.Data.SqlClient”,
            “Data Source=.;Initial Catalog=AdventureWorks;Integrated Security=True”,
            “Test.vOrderQuantityPerProductKey”,
            DataAccessMethod.Sequential),
            TestMethod()]


Rematando la faena: escritura del test


Escribir el test unitario es sencillo… lo primero que tenemos que hacer es tener una propiedad de tipo TestContext, llamada TestContext. En esta propiedad, Visual Studio nos irá dejando el contexto de cada test, es decir, en nuestro caso, los valores para cada uno de los juegos de prueba.


        private TestContext _myTestContext;


        public TestContext TestContext
        {
            get { return _myTestContext; }
            set { _myTestContext = value; }
        }


Lo siguiente es escribir el test:



        public void OrderQuantityPerProductKeyTestMethod()
        {
            // Construimos la sentencia MDX para el producto actual, y obtenemos la cantidad del cubo.
            String mdxQuery = “SELECT [Measures].[Order Quantity] ON COLUMNS ”  
                              + “FROM [Adventure Works] WHERE [Product].[Product Key].[“
                              + TestContext.DataRow[“Product”]
                              + “]”;
            AdomdCommand mdxQueryCommand = new AdomdCommand(mdxQuery, _adomdConnection);
            CellSet cubeResult = mdxQueryCommand.ExecuteCellSet();


            // Comparamos el resultado del cubo, con el resultado de la base de datos.
            int result = (int)cubeResult.Cells[0].Value;
            int expected = (int)TestContext.DataRow[“Quantity”];
            Assert.AreEqual(expected, result, 16);


        }


Como veis, me limito a ejecutar una sentencia MDX que me devuelva de los cubos OLAP el valor equivalente al del juego de ensayo. Para obtener el juego de ensayo, leo del diccionario “DataRow” del TestContext cada una de las columnas de mi tabla de pruebas, y por último pruebo con un Assert que los resultados del cubo sean los esperados.


La invocación de Assert.AreEqual tiene un tercer parámetro que vale 16… ¿qué significa?


Este parámetro, es el “delta” de la función. Muchas veces, cuando metemos datos en un cubo por medio de un ETL, durante el proceso de limpieza se pierde precisión en los datos. Como resultado de la limpieza, los valores extraidos de la base de datos OLTP y OLAP podrían no coincidir… pues bien, el “delta”, es la desviación que toleraremos en nuestra prueba (en este caso, +/- 16 enteros). Podéis descargaros el proyecto completo que he adjuntado a este post, y experimentar todo lo que queráis (por ejemplo, probad a bajar el valor del delta y observad qué pasa…).


Despidiendo el post


Hemos visto cómo los test unitarios no están de más en el mundo de la inteligencia de negocios… y recordad que tal y cómo dice SCRUM, un proyecto no está terminado mientras no esté probado.


Happy testing!

2 comentarios en “Testeo unitario de cubos OLAP”

  1. Gorka, ¿has probado si Visual Studio Team System for Dabatase Professionals tiene algo que facilite el testeo unatario de cubos?

    Para testeo unitario de procedimientos almacenados hace una muy buena labor.

  2. No he tenido la suerte de poder probar TS for Database Professionals, pero de lo que he leido no se me ha ocurrido nada que se pueda aprovechar en el desarrollo de cubos OLAP. La capacidad de testeo unitario que le han añadido, permite testear procedimientos almacenados usando T-SQL. La verdad es que la idea es aplicable a los cubos, pero el lenguaje a usar sería el MDX, que por lo que veo no está soportado. De todas formas os dejo un enlace a la MSDN donde podréis ver qué ofrece este nuevo Visual Studio:

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs05/html/tedbpro.asp

    La idea del artículo de testear los procedimientos almacenados usando wrappers, por supuesto, es aplicable a los cubos (para testear “calculated measures”, “KPI”s… etc) pero para eso basta con una suite de testeo unitario “convencional”. Habrá que esperar a la próxima versión…

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *