Ir al contenido principal

Primeros ajustes en la plataforma de testeo


Ya tenía muchas ganas de poner a prueba nuestra recién desarrollada plataforma para Test, pero me di cuenta de que necesitaba unos cuantos ajustes antes de ponerla en marcha.

Os recuerdo que todo el código está disponible en Enigma Software - ZM LABS

He habilitado un menú en las ramas secundarias del TreeView para grabar un nuevo test:


Para que solo se despliegue en las ramas secundarias de tipo "Categoría" programo el evento Opening del Menú:

        private void contextMenuArbol_Opening(object sender, CancelEventArgs e)
        {
            if (treeCatalogo.SelectedNode != null)
            {
                objects.treeElement _treeelem = (objects.treeElement)treeCatalogo.SelectedNode.Tag;

                if (_treeelem.ElemType == objects.enumElemType.Categorie && _treeelem.Categorie.categorie_dad != null)
                {
                    e.Cancel = false;
                }
                else
                {
                    e.Cancel = true;
                }
            }
        }

Menú que conduce a la grabación de un nuevo test:


En el campo Clase hemos de dar el mismo nombre que tendrá la clase de negocio que ejecute el test:


Al seleccionar un test mostramos una pantalla con la información del mismo, desde la cual podremos lanzar la ejecución. ¿Cómo? Llegamos a la parte más bonita.


A la pantalla de la imagen le pasamos ya la información necesaria para ello, recogida en la propiedad TAG del nodo seleccionado:

        private void treeCatalogo_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (treeCatalogo.SelectedNode != null)
            {
                objects.treeElement _treeelem = (objects.treeElement)treeCatalogo.SelectedNode.Tag;

                if (_treeelem.ElemType == objects.enumElemType.Test)
                {
                    _pantalla_actual = enumPantalla.TestInfo;

                    _test_functions.SetTestObject(_treeelem.TestObject);

                    try
                    {
                        enumTestTypes _type = (enumTestTypes)Enum.Parse(typeof(enumTestTypes),
                                                                        _treeelem.TestObject.classname);
                         
                        _treeelem.TestObject.execution.ClassName = _treeelem.TestObject.classname;
                        _treeelem.TestObject.execution.TestType = _type;

                        _treeelem.TestObject.execution.OBJ = test_types.GetObject(_test_functions, _type);

                        _ctrl_test_info = new controls.usrctrl_testinfo(_treeelem.TestObject);

                        splitContainer.Panel2.Controls.Clear();
                        splitContainer.Panel2.Controls.Add(_ctrl_test_info);
                    }
                    catch (Exception ex)
                    {
                        splitContainer.Panel2.Controls.Clear();
                    }
                }
                else
                {
                    splitContainer.Panel2.Controls.Clear();
                }
            }
        }

La clave para después poder ejecutar esta clase se encuentra en la propiedad execution.OBJ

_treeelem.TestObject.execution.OBJ = test_types.GetObject(_test_functions, _type);

Permítanme enseñarles el código de la clase test_types que contiene el método GetObject,
ya que este es el que devuelve un objeto de negocio adecuado al Test seleccionado.



    public static class test_types
    {
        public class mensajes
        {
            public Guid id;
            public string mensaje;
            public bool leido;
        }

        public enum enumEstadoProceso { Parado, Ejecutando, Finalizado, Erroneo }

        public static Object GetObject(test_functions _functions, ZmLabsObjects.enumTestTypes _type)
        {
            Object res = new Object();

            switch (_type)
            {
                case ZmLabsObjects.enumTestTypes.test1_multithreading_sleep_performance:

                    res = new test1_multithreading_sleep_performance(_functions);
                    break;
            }

            return res;
        }
    }

Muy importante señalar que en próximas publicaciones iremos aplicando significativas mejoras sobre el código que hoy les estoy mostrando. No pretende ésta ser una plataforma estática, sino una excusa para ir evolucionando y aprendiendo siempre de la mano de Uds. queridos lectores.

Al pulsar el botón PLAY en el formulario cargamos un control de usuario, que será el que ejecute la clase de negocio, y muestre los mensajes que la propia clase vaya generando.

    public partial class usrctrl_monitorlist : UserControl
    {
        public static test_functions _testobject;
        public static test_types.enumEstadoProceso _estadoProceso;

        public usrctrl_monitorlist()
        {
            InitializeComponent();
        }

        public void Activate(test_functions p_testobject)
        {
            _testobject = p_testobject;
            _estadoProceso = test_types.enumEstadoProceso.Parado;

            Thread _th = new Thread(() => HiloNegocio());
            _th.Start();

            Thread.Sleep(3000);

            timerControl.Enabled = true;
        }

        private void timerControl_Tick(object sender, EventArgs e)
        {
            List<test_types.mensajes> lstMensajes = new List<test_types.mensajes>();

            switch (_testobject.execution.TestType)
            {
                case enumTestTypes.test1_multithreading_sleep_performance:

                    var obj = (test1_multithreading_sleep_performance)_testobject.execution.OBJ;

                    _estadoProceso = obj.Estado;
                    lstMensajes = obj.Mensajes.Where(msg => msg.leido == false).ToList();

                    foreach (var msg in lstMensajes)
                    {
                        obj.SetMsgLeido(msg.id);
                    } 

                    break;
            }

            if (_estadoProceso == test_types.enumEstadoProceso.Ejecutando)
            {
                foreach (var msg in lstMensajes)
                {
                    ListViewItem lstIt = new ListViewItem(msg.mensaje);
                    lstMonitor.Items.Add(lstIt);
                }
            }
            else if (_estadoProceso == test_types.enumEstadoProceso.Finalizado)
            {
                timerControl.Enabled = false;

                //última lectura de mensajes
                foreach (var msg in lstMensajes)
                {
                    ListViewItem lstIt = new ListViewItem(msg.mensaje);
                    lstMonitor.Items.Add(lstIt);
                }
            }
        }

        public static void HiloNegocio()
        {
            switch (_testobject.execution.TestType)
            {
                case enumTestTypes.test1_multithreading_sleep_performance:

                    var obj = (test1_multithreading_sleep_performance)_testobject.execution.OBJ;
                    obj.Start();

                    break;
            }
        }
    }

Con estas mejoras sobre la plataforma ya podemos ir generando y ejecutando los TEST.

En el próximo POST   ¡¡por fin podremos ver la primera ejecución!!





Comentarios

Entradas populares de este blog

Unit Testing

Como programador, he aprehendido la importancia de los test unitarios por la vía del dolor. Por la vía de los mantenimientos de software que se van volviendo más y más inmantenibles día tras día, por la vía de corregir un error con urgencia, subirlo a un entorno de producción habiendo hecho las pruebas funcionales justas, y totalmente orientadas a probar la parte que se ha modificado, para darme cuenta -también dolorosamente- que la corrección del error produce otro error en algún otro punto de la solución, que obliga a revertir el cambio, corregir de nuevo con la presión del negocio en aumento, y subir la corrección de la corrección con los dedos cruzados y las rodillas temblorosas, a sabiendas de que ningún mecanismo me garantiza que no vuelva a pasar lo mismo. Sencillamente no se pueden repetir manualmente todas las pruebas, todas las casuísticas que pudieran haberse visto afectadas por el cambio. Cuesta un poco entender el test unitario como una inversión, pero cuando por fin ...

Trazabilidad y control de errores - 2ª parte: trazabilidad estructurada

En esta nueva entrega de la publicación  Trazabilidad y control de errores vamos a centrarnos en el que es quizá el más interesante aspecto de la trazabilidad.  Structured Logging es la técnica que nos permitirá realizar análisis automatizados de nuestra trazabilidad, mediante software de detección de eventos. En la primera parte de la publicación incorporamos a nuestra plataforma de test Open Source la librería NLog , y configuramos la generación de dos ficheros de texto plano para trazas, uno para dejar la información de los posibles errores no controlados, y otro para los avisos, o warnings . Además asociamos la consola para crear trazas de información para la depuración. Hoy vamos a configurar la creación de un tercer fichero, que almacenará igualmente información de los errores, pero en este caso guardará la información no en texto plano, sino estructurada, con notación JSON que después podría ser procesada. Para este fin NLOG nos proporciona el JSON Layout . Vamos a ...

Test 1: Multithreading vs Singlethreading

¡¡ Bien !! Después de unos cuantos arreglos, ya tenemos disponible el primer TEST para nuestra plataforma. Puesto que me gustaría mediante este blog interactuar con las entradas de Stackoverflow , para este primer test he seleccionado este interesante tema:  multithreading slower than singlethreading Y para introducirnos en la filosofía de los TEST, no es mi intención impartir una conferencia sobre este asunto, sino simplemente implementar las casuísticas que nos interesa evaluar, y medir los rendimientos. Vamos a ello. En primer lugar grabamos en BBDD (a través del recién desarrollado interfaz) el test, y los testcases . La cosa quedaría así: A nivel programático, debemos definir una clase cuyo nombre se corresponda con el campo "Clase" del Test. Y tantos métodos como "Casos" asociemos al test, haciendo igualmente coincidir los nombres. En este punto les recuerdo que pueden descargar el proyecto íntegro en  EnigmaLABS - GitHub Para que la comparació...