Buscar este blog

miércoles, 30 de marzo de 2011

Validando esquemas xml con .Net Framework

Uno de los objetivos de los esquemas xml (archivos .xsd) es poder validar que un archivo xml cumpla con las reglas que se especifican en el esquema, .Net tiene el API necesaria para realizar esta validación y es muy sencillo.
Consideremos el siguiente esquema:

   1:  <?xml version="1.0" standalone="yes"?>
   2:  <xs:schema id="Peliculas"
   3:                       targetNamespace="ProbadorConsola"
   4:                       xmlns:xs="http://www.w3.org/2001/XMLSchema"
   5:                       xmlns="ProbadorConsola"
   6:                       elementFormDefault="qualified">
   7:    <xs:element name="Peliculas">
   8:      <xs:complexType>
   9:        <xs:choice minOccurs="0" maxOccurs="unbounded">
  10:          <xs:element name="Pelicula">
  11:            <xs:complexType>
  12:              <xs:sequence>
  13:                <xs:element name="Titulo" type="xs:string" minOccurs="0" />
  14:                <xs:element name="Director" type="xs:string" minOccurs="0" />
  15:                <xs:element name="Estrenado" type="xs:string" minOccurs="0" />
  16:                <xs:element name="Actores" minOccurs="0" maxOccurs="unbounded">
  17:                  <xs:complexType>
  18:                    <xs:sequence>
  19:                      <xs:element name="Actor" minOccurs="0" maxOccurs="unbounded">
  20:                        <xs:complexType>
  21:                          <xs:sequence>
  22:                            <xs:element name="Nombre" type="xs:string" minOccurs="0" />
  23:                            <xs:element name="Nacimiento" type="xs:string" minOccurs="0" />
  24:                            <xs:element name="Roles" minOccurs="0" maxOccurs="unbounded">
  25:                              <xs:complexType>
  26:                                <xs:sequence>
  27:                                  <xs:element name="Rol" minOccurs="0" maxOccurs="unbounded">
  28:                                    <xs:complexType>
  29:                                      <xs:sequence>
  30:                                        <xs:element name="NombrePelicula" type="xs:string" minOccurs="0" />
  31:                                        <xs:element name="NombreRol" type="xs:string" minOccurs="0" />
  32:                                      </xs:sequence>
  33:                                    </xs:complexType>
  34:                                  </xs:element>
  35:                                </xs:sequence>
  36:                              </xs:complexType>
  37:                            </xs:element>
  38:                          </xs:sequence>
  39:                        </xs:complexType>
  40:                      </xs:element>
  41:                    </xs:sequence>
  42:                  </xs:complexType>
  43:                </xs:element>
  44:              </xs:sequence>
  45:            </xs:complexType>
  46:          </xs:element>
  47:        </xs:choice>
  48:      </xs:complexType>
  49:    </xs:element>
  50:  </xs:schema>

Y el contenido xml que queremos validar:

   1:  <Peliculas xmlns="ProbadorConsola">
   2:      <Pelicula>
   3:      <Titulo>Mazinger</Titulo>
   4:      <Director>Jackie Chan</Director>
   5:      <Estrenado>1975-03-19T00:00:00</Estrenado>
   6:      <Actores>
   7:        <Actor>
   8:          <Nombre>John Wayne</Nombre>
   9:          <Nacimiento>1915-10-23T00:00:00</Nacimiento>
  10:          <Roles>
  11:            <Rol>
  12:              <NombrePelicula>Mazinger</NombrePelicula>
  13:              <NombreRol>Estrella</NombreRol>
  14:            </Rol>
  15:          </Roles>
  16:        </Actor>
  17:      </Actores>
  18:    </Pelicula>
  19:  </Peliculas>

Lo primero que debemos hacer es validar que el documento contenga el espacio de nombres del esquema si no lo contiene la validación fallara diciéndonos que el documento es valido aun cuando en realidad no cumpla las reglas del esquema.
El código para encontrar el espacio de nombres (c#):

   1:  XDocument peliculas = XDocument.Load("peliculas.xml");
   2:  XPathNavigator nav = peliculas.CreateNavigator();
   3:  nav.MoveToFollowing(XPathNodeType.Element);
   4:  IDictionary<string, string> ns
   5:      = nav.GetNamespacesInScope(XmlNamespaceScope.All);
   6:  bool schemaFound = false;
   7:  foreach(KeyValuePair<string, string> namespaces in ns) {
   8:      if(namespaces.Value.CompareTo("ProbadorConsola") == 0)
   9:          schemaFound = true;
  10:  }
  11:  if(!schemaFound) {
  12:      Console.WriteLine("Esquema no encontrado");
  13:      return;
  14:  }
Ahora si podemos proceder a validar el documento con el esquema que puede estar en un archivo local o en Internet:

   1:  XmlSchemaSet schema = new XmlSchemaSet();
   2:  schema.Add("ProbadorConsola", "peliculas.xsd");
   3:  peliculas.Validate(schema, null);
   4:  Console.WriteLine("Esquema valido");
   5:  Console.ReadLine();

Hacemos notar que si utilizas Linq a XSD todo esto lo hace en una sola linea de código al cargar el documento.

Para aprender más sobre el uso de XML en .Net Framework visita:
Lista de artículos acerca del uso de XML en .Net Framework

sábado, 26 de marzo de 2011

Instalar Linq a XSD

En una entrada anterior ya vimos lo que se puede hacer con Linq a XSD pero dejamos el proceso de instalación pendiente ya que es un poco complicado y merece una entrada independiente.
Linq a XSD es muy útil y no deberíamos detenernos en su uso debido a las pocas complicaciones que tiene su instalación sobre todo tomando en cuenta que es un proyecto de Microsoft y probablemente se incluya en versiones futuras de Visual Studio.
Bueno lo primero es descargarlo desde el proyecto de Linq a XSD en Codeplex y colocar los archivos descargados en una carpeta preferentemente dentro de la carpeta de nuestra solución, en nuestro ejemplo se colocara en la carpeta Components\LinqToXsd\bin en la raíz de nuestra solución y añadimos los archivos en una carpeta de solución solo para recordarnos donde están y no es un paso obligatorio.
Ahora abrimos las propiedades del proyecto en que vamos a usarlo y en la pestaña Build Events en el recuadro Pre-build event command line colocamos el siguiente texto:

SET LINQTOXSDBINDIR=$(SolutionDir)Components\LinqToXsd\bin

Cuidando que la ruta apunte a donde pusimos los archivos.


Ahora necesitamos modificar el archivo csproj de la solución (Linq a XSD solo funciona en C-Sharp, pero puedes hacer una DLL que después utilizaras en VB.Net), para esto descargamos la solución, en el explorador de la solución escogemos el proyecto que estamos usando, click derecho y Unload Project, click derecho y Edit proyecto.csproj.
Vamos al final del archivo y después del cierre del último elemento <propertygroup> ponemos este código:

   1:  <PropertyGroup>
   2:      <LinqToXsdBinDir Condition="'$(LinqToXsdBinDir)' == ''">$(SolutionDir)Components\LinqToXsd\bin</LinqToXsdBinDir>
   3:  </PropertyGroup>

Nótese que al pegar el código Visual Studio lo formatea poniéndole lineas nuevas alrededor de la ruta, debemos modificar esto de tal forma que la quede igual que en el código de ejemplo de lo contrario tendremos errores. A continuación muestro la forma en que NO debe quedar la modificación

   1:  <PropertyGroup>
   2:      <LinqToXsdBinDir Condition="'$(LinqToXsdBinDir)' == ''">
   3:          $(SolutionDir)Components\LinqToXsd\bin
   4:      </LinqToXsdBinDir>
   5:  </PropertyGroup>

Falta introducir otro código en el mismo archivo, también al final del archivo después de el cierre del último elemento <import> colocamos el siguiente código:

   1:  <Import Project="$(LinqToXsdBinDir)\LinqToXsd.targets" />

Listo recargamos la solución y al archivo .xsd para el que queremos crear las clases le cambiamos el Build Action a LinqToXsdSchema compilamos y se nos generan las clases que necesitamos, es necesario notar que las clases se encuentran en el espacio de nombres indicado en el atributo targetNamespace del esquema xml (.xsd) y no en el de nuestro proyecto por lo que debemos buscar las clases en ese espacio de nombres.

Para aprender más sobre Linq visita:
Lista de artículos acerca de Linq

Para aprender más sobre el uso de XML en .Net Framework visita:
Lista de artículos acerca del uso de XML en .Net Framework

viernes, 18 de marzo de 2011

Cobertura de código (Code Coverage) con pruebas unitarias de Visual Studio

Una de las funciones que tiene los proyectos de pruebas de Visual Studio es la Cobertura de Código o Code Coverage en ingles, esta función nos permite saber que porcentaje del código de nuestro proyecto estamos probando lo cual es muy importante pues puede haber errores en el código que no estamos probando y esta función nos da una idea de que pruebas nos faltan por escribir.

Para habilitar la cobertura de código previo requisito es que tengamos una versión de Visual Studio que tenga soporte para proyectos de prueba, al crear nuestro proyecto de prueba Visual Studio crea automáticamente un archivo llamado LocalTestRun.testrunconfig en una carperta Elementos de la solución (Solution Items) directamente bajo la solución para habilitar la cobertura de código hacemos doble click en este archivo y nos aparecerá la ventana de configuración de las pruebas en esta ventana escogemos la sección Cobertura de Código y nos aparece una lista con las dll's y ejecutables que produce nuestra solución debemos marcar los elementos para los que queremos habilitar la cobertura de código aplicamos los cambios cerramos y listo ya tenemos habilitada la cobertura de código en nuestras pruebas.


Para obtener los resultados ejecutamos las pruebas que queremos analizar y abrimos el panel Resultado de Cobertura de Código (Code Coverage Results) aquí vemos una lista que nos muestra detalle los porcentajes de código que estamos probando pudiendo expandir la lista hasta saber exactamente que parte del código se probo en que porcentaje.


En la imagen podemos ver que solo se probo el 4 por ciento del código con lo cual sabemos que nos falta mucho por probar, por supuesto es un ejemplo solo demostrativo.

Para aprender más acerca de las pruebas unitarias con .Net Framework visita:
Lista de artículos acerca de pruebas unitarias con .Net Framework

miércoles, 16 de marzo de 2011

Integrar NUnit a Visual Studio

Hay varias formas de integrar NUnit a Visual Studio, aquí mostrare la más sencilla y la que me parece la más conveniente.
Siguiendo las instrucciones del sitio de NUnit agregamos una herramienta personalizada a Visual Studio y le agregamos los parámetros necesarios para ejecutar NUnit en el proyecto actual estos datos son:

Titulo: NUnit
Comando: C:\Program Files\NUnit 2.5.1\bin\net-2.0\nunit.exe
ajustando la ruta a donde tenemos instalado NUnit
Argumentos: $(ProjectDir)$(ProjectFileName)
Directorio Inicial: $(ProjectDir)bin/Debug/



Eso es todo seleccionamos en el editor un archivo que este en un proyecto de pruebas NUnit y en el menú de herramientas seleccionamos NUnit y se abrira NUnit usando el proyecto de pruebas seleccionado, nótese que tiene que estar abierto y activo en el editor algún archivo que pertenezca a un proyecto de pruebas de NUnit de lo contrario nos marcara un error.

La otra opción es mucho mejor ya que integra los proyectos de pruebas de NUnit con la interfaz de Visual Studio sin necesidad de abrir el ejecutable de NUnit y mostrando los resultados dentro de la pantalla de Visual Studio, el requisito es que tengamos una versión de Visual Studio que soporte proyectos de prueba.
Esto se logra usando el componente NUnitForVS que podemos bajar de CodePlex y funciona para las versiones 2008 y 2010 de Visual Studio.
Después de instalar el complemento tenemos que modificar los proyectos de NUnit en nuestras soluciones lo que debemos hacer es descargar el proyecto de la solución (Unload Project desde el explorador de soluciones) y editar el archivo csproj tenemos que añadir la siguientes lineas:

<projecttypeguids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</projecttypeguids>

al final de la primer sección <propertygroup> que encontremos en el archivo.
Después de esto ya estamos listos para ejecutar nuestras pruebas abrimos la ventana Vista de Pruebas (Test View) y encontraremos nuestras de NUnit mezcladas con las pruebas de Visual Studio (si es que tenemos alguna) e identificadas por un icono de una N al pricipio:


Ejecutamos las pruebas y obtenemos los resultados en el panel de resultados de las pruebas:


Para aprender más acerca de las pruebas unitarias con .Net Framework visita:
Lista de artículos acerca de pruebas unitarias con .Net Framework

martes, 8 de marzo de 2011

Linq a XSD: leyendo xml con tipos

Como hemos comentado en una entrada anterior es muy fácil usar xml con Linq en .Net, pues bien es posible usarlo aun mas fácilmente usando Linq a Xsd que es un proyecto de Microsoft disponible en CodePlex y que nos permite crear una estructura de clases a partir de un esquema de xml que representa el contenido de nuestro xml, obviamente el requisito es que tengamos o creemos un esquema xml para poder usar esta característica. Recordemos que en una entrada anterior vimos como crear esquemas con herramientas disponibles libremente.

Instalar esta herramienta es un poco complicado por lo que en esta entrada solo dare una breve introducción a lo que se puede hacer con esta herramienta y en otra entrada incluire otros ejemplos incluyendo el procedimiento de instalación.

Lo primero es tener a la mano nuestro esquema consideremos este xsd:


   1:  <?xml version="1.0" standalone="yes"?>
   2:  <xs:schema id="Peliculas"
   3:                       targetNamespace="ProbadorConsola"
   4:                       xmlns:xs="http://www.w3.org/2001/XMLSchema"
   5:                       xmlns="ProbadorConsola"
   6:                       elementFormDefault="qualified">
   7:    <xs:element name="Peliculas">
   8:      <xs:complexType>
   9:        <xs:choice minOccurs="0" maxOccurs="unbounded">
  10:          <xs:element name="Pelicula">
  11:            <xs:complexType>
  12:              <xs:sequence>
  13:                <xs:element name="Titulo" type="xs:string" minOccurs="0" />
  14:                <xs:element name="Director" type="xs:string" minOccurs="0" />
  15:                <xs:element name="Estrenado" type="xs:string" minOccurs="0" />
  16:                <xs:element name="Actores" minOccurs="0" maxOccurs="unbounded">
  17:                  <xs:complexType>
  18:                    <xs:sequence>
  19:                      <xs:element name="Actor" minOccurs="0" maxOccurs="unbounded">
  20:                        <xs:complexType>
  21:                          <xs:sequence>
  22:                            <xs:element name="Nombre" type="xs:string" minOccurs="0" />
  23:                            <xs:element name="Nacimiento" type="xs:string" minOccurs="0" />
  24:                            <xs:element name="Roles" minOccurs="0" maxOccurs="unbounded">
  25:                              <xs:complexType>
  26:                                <xs:sequence>
  27:                                  <xs:element name="Rol" minOccurs="0" maxOccurs="unbounded">
  28:                                    <xs:complexType>
  29:                                      <xs:sequence>
  30:                                        <xs:element name="NombrePelicula" type="xs:string" minOccurs="0" />
  31:                                        <xs:element name="NombreRol" type="xs:string" minOccurs="0" />
  32:                                      </xs:sequence>
  33:                                    </xs:complexType>
  34:                                  </xs:element>
  35:                                </xs:sequence>
  36:                              </xs:complexType>
  37:                            </xs:element>
  38:                          </xs:sequence>
  39:                        </xs:complexType>
  40:                      </xs:element>
  41:                    </xs:sequence>
  42:                  </xs:complexType>
  43:                </xs:element>
  44:              </xs:sequence>
  45:            </xs:complexType>
  46:          </xs:element>
  47:        </xs:choice>
  48:      </xs:complexType>
  49:    </xs:element>
  50:  </xs:schema>

Y después el archivo xml que vamos a utilizar:


   1:  <?xml version="1.0"?>
   2:  <Peliculas xmlns="ProbadorConsola">
   3:    <Pelicula>
   4:      <Titulo>Mazinger</Titulo>
   5:      <Director>Jackie chan</Director>
   6:      <Estrenado>1975-03-19T00:00:00</Estrenado>
   7:      <Actores>
   8:        <Actor>
   9:          <Nombre>John Wayne</Nombre>
  10:          <Nacimiento>1915-10-23T00:00:00</Nacimiento>
  11:          <Roles>
  12:            <Rol>
  13:              <NombrePelicula>Mazinger</NombrePelicula>
  14:              <NombreRol>Estrella</NombreRol>
  15:            </Rol>
  16:          </Roles>
  17:        </Actor>
  18:      </Actores>
  19:    </Pelicula>
  20:    <Pelicula>
  21:      <Titulo>Terminator</Titulo>
  22:      <Director>James Cameron</Director>
  23:      <Estrenado>1985-02-14T00:00:00</Estrenado>
  24:      <Actores>
  25:        <Actor>
  26:          <Nombre>Arnold</Nombre>
  27:          <Nacimiento>1953-10-11T00:00:00</Nacimiento>
  28:          <Roles>
  29:            <Rol>
  30:              <NombrePelicula>Terminator</NombrePelicula>
  31:              <NombreRol>Protagonista</NombreRol>
  32:            </Rol>
  33:            <Rol>
  34:              <NombrePelicula>Terminator</NombrePelicula>
  35:              <NombreRol>Enemigo</NombreRol>
  36:            </Rol>
  37:          </Roles>
  38:        </Actor>
  39:        <Actor>
  40:          <Nombre>Linda Hamilton</Nombre>
  41:          <Nacimiento>1972-08-12T00:00:00</Nacimiento>
  42:          <Roles>
  43:            <Rol>
  44:              <NombrePelicula>Terminator</NombrePelicula>
  45:              <NombreRol>Protagonista</NombreRol>
  46:            </Rol>
  47:            <Rol>
  48:              <NombrePelicula>Terminator</NombrePelicula>
  49:              <NombreRol>Perseguida</NombreRol>
  50:            </Rol>
  51:          </Roles>
  52:        </Actor>
  53:      </Actores>
  54:    </Pelicula>
  55:  </Peliculas>

Linq a XSD nos genera una jerarquía de clases que nos permite manejar el xml usando datos tipeados con soporte de Intellisense y comprobación por parte del compilador, por ejemplo para listar los datos de todos los actores:


   1:  Peliculas peliculas = Peliculas.Load("peliculas.bak.xml");
   2:  var actores = from p in peliculas.Pelicula
   3:                from a in p.Actores
   4:                from actor in a.Actor
   5:                select actor;
   6:  Console.WriteLine("Todos los actores");
   7:  foreach(var actor in actores) {
   8:      Console.Out.WriteLine("Nombre: " + actor.Nombre);
   9:      Console.Out.WriteLine("Fecha de nacimiento: " + actor.Nacimiento);
  10:  }

En conclusion Linq a XSD es un complemento muy útil para el manejo de XML en .Net Framework.
Hay que tener en cuenta que el proyecto a Marzo del 2011 aún esta en etapa Beta y es mejor probar bien nuestro código para evitar errores inesperados, como sea el proyecto es muy útil y es probable que posteriormente sea incluido como parte del .Net Framework.

Para aprender más sobre Linq visita:
Lista de artículos acerca de Linq

Para aprender más sobre el uso de XML en .Net Framework visita:
Lista de artículos acerca del uso de XML en .Net Framework