Ir al contenido principal

Primeros pasos en Enigma Software Labs

En pocas palabras: vamos a probar y estresar distintas soluciones de software para un mismo problema, en busca de realidades matemáticas.

Para ello, lo primero que necesitamos en averiguar el modo de publicar código aquí en Blogger. Para ello voy a usar un sistema súper sencillo y eficiente. Ahí va un ejemplo de código C#

        private void frmMonitor_Load(object sender, EventArgs e)
        {
            TreeNode _tr = new TreeNode("SQL Server Tips");
            TreeNode _tr2 = new TreeNode("C# Code");

            treeCatalogo.Nodes.Add(_tr);
            treeCatalogo.Nodes.Add(_tr2);

            //splitContainer.Panel1.Focus();
            //lstMonitor.Focus();
        }

Hilarante ¿verdad?  hilite.me lo hace posible.

Bien, paso 2, fácil y sencillo: vamos a crear una plataforma de testeo para C# en una bonita solución que compartiré en el repositorio GIT, para disfrute de todos.

Enigma Software - ZM LABS

Como posteriormente me divertiré implementando un bonito y potente buscador de pruebas, voy a dar un primer paso muy sencillo, que es categorizar los test.

En el front usaremos un TreeView que cargará de forma recursiva las categoría y los test de cada categoría

        public void GetCategories()
        {
            treeCatalogo.Nodes.Clear();

            List<Categories> _lstcat = _test_functions.getCategories();

            //rellenamos el tree view
            foreach (Categories _cat in _lstcat.Where(ct => ct.categorie_dad == null))
            {
                TreeNode _trprincipal = new TreeNode(_cat.categorie);

                //cargamos los hijos
                foreach (Categories _catsub in _lstcat.Where(c => c.categorie_dad != null && c.categorie_dad.id == _cat.id))
                {
                    GetCategorieChildrensAndTests(ref _trprincipal, _catsub, _lstcat);
                }

                //no cargamos tests en las categorías principales (pq no debe haber)
                //si fuera necesario lo haríamos aquí

                objects.treeElement _treeElem = new objects.treeElement()
                {
                    ElemType = objects.enumElemType.Categorie
                };

                _trprincipal.Tag = _treeElem;
                treeCatalogo.Nodes.Add(_trprincipal);
            };

            treeCatalogo.ExpandAll();
        }

        public void GetCategorieChildrensAndTests(ref TreeNode _trprincipal, Categories _catsub, List<Categories> _lstcat)
        {
            TreeNode _hijo = new TreeNode(_catsub.categorie);

            objects.treeElement _treeElem = new objects.treeElement()
            {
                ElemType = objects.enumElemType.Categorie
            };

            _hijo.Tag = _treeElem;

            //cargamos los hijos
            foreach (Categories _catsubsub in _lstcat.Where(c => c.categorie_dad != null && c.categorie_dad.id == _catsub.id))
            {
                GetCategorieChildrensAndTests(ref _hijo, _catsubsub, _lstcat);
            }

            //cargamos los test de la categoría actual
            foreach (test_object _test in _lst_tests.Where(ct => ct.categorie.id == _catsub.id))
            {
                objects.treeElement _treeTestElem = new objects.treeElement()
                {
                    ElemType = objects.enumElemType.Test,
                    TestObject = _test
                };

                TreeNode _treetest = new TreeNode(_test.test);
                _treetest.Tag = _treeTestElem;
                _hijo.Nodes.Add(_treetest);
            }

            _trprincipal.Nodes.Add(_hijo);
        }

Puesto que los nodos del TreeView pueden ser de tipo "categoría" o de tipo "test", alimento la propiedad TAG con la siguiente clase:

namespace ZmLabsMonitor.objects
{
    public enum enumElemType { Categorie, Test }

    public class treeElement
    {
        public enumElemType ElemType;
        public test_object TestObject;
    }
}

Ahora empiezo a desarrollar la plataforma para lanzar test. En esta parte hay bastante margen de sofisticación. Vamos a hacerlo de menos a más.

Observen el proyecto ZmLabsBusiness:


En la carpeta "tests" iremos dejando la ejecución de los distintos test, los cuales están previamente definidos.

De modo genérico la clase Test_Types nos devolverá el objeto de negocio necesario para la ejecución del test seleccionado en el TreeView:

namespace ZmLabsBusiness
{
    public static class test_types
    {
        public enum enumTestTypes
        {
            test1_multithreading_sleep_performance
        }

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

            switch (_type)
            {
                case enumTestTypes.test1_multithreading_sleep_performance:

                    res = new test1_multithreading_sleep_performance(_functions);
                    break;
            }

            return res;
        } 
    }
}

        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);

                    test_types.enumTestTypes _type = (test_types.enumTestTypes)Enum.Parse(typeof(test_types.enumTestTypes),
                                                                                          _treeelem.TestObject.str_test_type);

                    _treeelem.TestObject.execution.business_object.TYPE = _treeelem.TestObject.str_test_type;
                    _treeelem.TestObject.execution.business_object.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);
                }
                else
                {
                    splitContainer.Panel2.Controls.Clear();
                }
            }
        }

Ahora disponemos de toda la información necesaria para lanzar una ejecución de cualquier test.

        private void cmdPlay_Click(object sender, EventArgs e)
        {
            test_types.enumTestTypes _type = (test_types.enumTestTypes)
                                             Enum.Parse(typeof(test_types.enumTestTypes), _testobject.execution.business_object.TYPE);

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

                    var _objNeg = (test1_multithreading_sleep_performance)_testobject.execution.business_object.OBJ;

                    _objNeg.Start();
                    break;
            }

        }

Nótese que estoy presuponiendo que los test no tienen parámetros de entrada. Esto será motivo de divertimentos en un futuro próximo. Ya les adelanto que los cambio a realizar andarán por la clase ExecutionProperties

namespace ZmLabsObjects
{
    public class test_object
    {
        public Int64 id;
        public string test;
        public string short_desc;
        public string long_desc;
        public string url_blog;
        public string url_git;
        public string str_test_type;

        public Categories categorie = new Categories();
        public ExecutionProperties execution = new ExecutionProperties();
    }

    public class Categories
    {
        public int id;
        public string categorie;

        public Categories categorie_dad;
    }

    public class ExecutionProperties
    {
        public DateTime dtBegin;
        public DateTime dtEnd;

        public List<TestCases> testcases = new List<TestCases>();

        public List<string> log;

        public BusinessObject business_object = new BusinessObject();
    }

    public class TestCases
    {
        public Int64 id;
        public string Function;
        public string Description;
        public DateTime dtBegin;
        public DateTime dtEnd;
    }

    public class BusinessObject
    {
        public Object OBJ;
        public string TYPE;
    }
}

Al terminar la ejecución del test los resultados se grabarán en base de datos. Las funciones relacionadas con los test las vamos codificando en la clase Test_Functions

    public class test_functions : test_object 
    {
        public List<Categories> getCategories()
        {
            List<Categories> res = new List<Categories>();

            try
            {
                res = data_tests.getCategories();
            }
            catch (Exception ex)
            {

            }

            return res;
        }

        public bool TestRecord(TestCases _testcase)
        {
            bool res;

            try
            {
                res = data_tests.InsertExecution(_testcase);
            }
            catch (Exception ex)
            {
                return false;
            }

            return res;
        }

        public List<test_object> getTests()
        {
            List<test_object> res = new List<test_object>();

            try
            {
                res = data_tests.getTests(); 
            }
            catch (Exception ex)
            {

            }

            return res;
        }

        #region TestObject

        public void SetTestObject(test_object _testobject)
        {
            this.id = _testobject.id;
            this.short_desc = _testobject.short_desc;
            this.long_desc = _testobject.long_desc;
            this.str_test_type = _testobject.str_test_type;

            this.url_blog = _testobject.url_blog;
            this.url_git = _testobject.url_git;

            this.categorie = _testobject.categorie;
            this.execution = _testobject.execution;
            this.test = _testobject.test;

        }

        #endregion
    }

Como no puede ser de otra manera, iremos haciendo pruebas de Bases de Datos, y de gestión de datos en general, y de SQL Server en particular.

De momento, la información maestra de los test, y los resultados de las ejecuciones quedarán consolidados en un modelito relacional muy sencillo (por ahora)

¡ Terminado! En muy poco tiempo hemos desarrollado una plataforma de testeo básica. Recuerden dejar sus comentarios. Si encuentran algo mejorable no duden que lo mejoraremos.

Asimismo, si disponen Uds. de un problema digno de ser testeado, lo implementaremos y publicaremos.

No olviden visitar nuestra recién creada cuenta de Instagram @enigma_csharp_labs  y compartir con nosotros todas sus inquietudes.

Salud y prosperidad.



Comentarios

Entradas populares de este blog

Test 3: ¿Son eficientes los ORMs?

Bienvenidos amigos. Me complace anunciar que por fin estrenamos la categoría " SQL Server Tips ", y lo hacemos por todo lo alto, entrando de lleno en un aspecto altamente polémico entre programadores. ¿Es eficiente un ORM en los accesos a datos? Ya conocen la filosofía de nuestros Tests, no vamos a teorizar demasiado, pero sí una pequeña base va a ser necesaria para conseguir una buena respuesta a nuestra pregunta. He leído un interesante  artículo de nuestros súper amigos de Deloitte ( cuando usar ORM ) argumentando que el uso o no de un ORM hay que decidirlo en relación a la complejidad de nuestro modelo de datos, y al rendimiento que requeriremos en nuestras soluciones, pero, ¿cuándo no deseamos el mejor rendimiento para nuestro software? Lo cierto es que, como ya hemos visto, el ORM facilita mucho las cosas, aporta claridad al código, de eso no cabe duda, pero, ¿es eficiente? He ahí la cuestión. Sobre este asunto vamos a poner a funcionar nuestros apreciados Test. C

Proyecto GEOW. Implementando el patrón CQRS. 2ª parte

En el anterior post ( Proyecto GEOW. Implementando el patrón CQRS ) nos adentramos en el funcionamiento del proyecto GEOW que nos va a servir de base para implementar un patrón arquitectónico, CQRS , pensado para dar respuesta a sistemas con alta exigencia de lecturas y escrituras simultáneas. Para ello hemos creado una interfaz gráfica con una serie de figuras geométricas en movimiento. Ahora vamos a ir a la parte de EL DATO. Cada vez que uno de estos cuadrados cambia de posición envía una trama con sus propias características, y sus nuevas coordenadas. Cada uno de los cuadrados realiza un movimiento cada 300 milisegundos, y he llegado a probar con hasta unas 700 figuras. En estos niveles el software empieza a sufrir, pero más la parte gráfica. Aparentemente el sistema de grabación de coordenadas se mantiene en buena forma. Vamos a ver, precisamente, este sistema de grabación: Grabando lotes de coordenadas en BBDD En el objeto PointObj que representa cada una de las figuras, en el

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ó