14 Jan 2010
Voy a decirlo aquí en alto y con vergüenza: hasta esta semana, no había usado nunca el Code Coverage. Y como ocurre con todas las buenas herramientas, ahora pienso: “¿cómo he podido estar sin esto hasta ahora?”.
Empezar a usarlo es sencillo, aunque tiene una pequeña peculiaridad: sólo funciona cuando los tests se ejecutan, no si se depurar. ¿Qué quiere decir esto? Que a la hora de seleccionar el conjunto de tests que queramos lanzar, deberemos utilizar la opción “Run Selection” en lugar de “Debug Selection”, en la ventana de “Test View”.
Como ya sabemos, el problema de esto es que cualquier punto de depuración que tengamos en el código no va a ejecutarse, pero parece un mal menor comparado con las posibilidades que tiene Code Coverage. Además, uno de los principios de testeo unitario es precisamente evitar la necesidad de depurar el código, así que no hay de qué quejarse.
Para poder ver la pestaña que muestra los resultados de cobertura de código existen dos posibilidades: pulsar el último de los botones que parecen en la ventana de “Test Results” o bien acceder a la opción de menú “Test – Windows – Code Coverage Results”.
Sin embargo, de poco nos servirá esto si no activamos previamente el Code Coverage para que se calculen sus resultados. Esto se configura en el fichero .testrunconfig que existe en la carpeta “Solution Items”.
Una vez abierto, hay pulsar en la opción de “Code Coverage” y seleccionar los assemblies sobre los que vamos a calcular la cobertura de código. Este punto es más importante de lo que podría pensarse, puesto que lo normal será tener dos versiones para cada uno: la versión de Debug y la versión de Release (podemos tener más si existen más configuraciones del proyecto). La clave es que no podemos elegir las dos a la vez, por lo que seleccionemos la que seleccionemos, tendrá que estar “sincronizada” con la configuración actual del proyecto. De lo contrario, tendremos un problema: la cobertura se calculará sobre un assembly que no tiene porqué estar actualizado con los últimos cambios que hemos hecho en el código.
Un ejemplo: digamos que hemos elegido la versión de Debug del assembly, pero tenemos configurado el proyecto en modo Release. Tenemos un 100% de cobertura de código, pero introducimos nuevas líneas en un método y compilamos (en Release). El assembly de Debug, sobre el que se va a pasar la cobertura, no ha cambiado, por lo que nos seguirá marcando 100% de cobertura aún cuando sabemos que no tenemos tests para el código que acabamos de añadir. Puede ser todo un problema, ¿verdad?
Por hoy es suficiente. Otro día, cómo interpretar los resultados y el coloreado del código.
31 Dec 2009
Cuando estaba preparándome la certificación de WCF, descubrí algo que es conveniente tener apuntado, pues puede dar bastantes quebraderos de cabeza: el orden en que aparecen los campos de información en los mensajes WCF una vez serializados. Estas son las reglas:
- Si el contrato hereda de otro tipo, aparecen en primer lugar los elementos de ese tipo base.
- Después, los elementos del propio contrato que no tengan la propiedad Order de DataMemberAttribute, ordenados alfabéticamente.
- Por último, los elementos que tengan la propiedad Orden, según el valor asignado.
Me ha resultado curioso que aparezcan primero los elementos sin la propiedad Order. Seguramente haya una razón que desconozco para que éste sea el comportamiento, pero entiendo que puede llevar a error fácilmente. ¿Por qué? Pues porque si seleccionas un elemento que quieres que vaya primero, y le das la propiedad Order = 1, probablemente, de desconocer estas reglas, esperarás que con esto sea suficiente para que aparezca en primer lugar en el mensaje WCF.
Pero no, será necesario que asignes valores a todos los otros elementos, para que no se antepongan al que has elegido tú, por aquello de no tener propiedad Order.
Por último, destacar que estas reglas aplican también al orden en que aparecen los elementos que añadamos a un MessageContract con el atributo MessageBodyMemberAttribute.
Algún día tengo que buscar porqué la gente de .NET decidió esto así.
31 Dec 2009
Cuando se está en un entorno de desarrollo, es bastante común utilizar certificados “auto-firmados” (self-signed) para bindings que requieran seguridad.
Sin embargo, WCF no acepta este tipo de certificados, lanzando una excepción de tipo SecurityNegotiationException, con un mensaje acompañando del estilo a “Could not establish trust relationship for the SSL/TLS secure channel with authority 'localhost:8732'”. ¿Qué hacer? Es fácil, simplemente hay que “engañar” al cliente para que acepte este certificado que el servidor nos está ofreciendo para realizar la conexión SSL, aunque esté firmado por sí mismo.
Para ello, en el cliente, es necesario introducir el siguiente código:
1: static void Main(string[] args)
2: {
3: using (DemoService.GetHeadersClient proxy = new DemoService.GetHeadersClient())
4: {
5: ServicePointManager.ServerCertificateValidationCallback +=
6: new System.Net.Security.RemoteCertificateValidationCallback(ValidateCertificate);
7:
8: // Do stuff with proxy object
9: }
10: }
11:
12: public static bool ValidateCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors)
13: {
14: return true;
15: }
El método definido será invocado por WCF en el momento de la validación del certificado, asegurándonos que el cliente va a aceptarlo en cualquier caso.
Por supuesto, esto es algo totalmente desaconsejado en cualquier entorno de producción. Pero para salir del paso en desarrollo, viene muy bien.
Respuesta original vista aquí.
31 Dec 2009
Dicen que nunca te acostarás sin aprender algo nuevo. Yo he tenido mi ración diaria con la forma de realizar una petición POST desde .NET. Probablemente sea una simpleza que todo el mundo sabe, pero yo lo desconocía.
El proceso es bastante intuitivo, salvo en la forma de añadir parámetros a la petición, que a mí me ha dejado algo más sorprendido. Pasos:
- Instanciar una URI con la dirección a la que se quiere hacer la petición, pero sin parámetros.
- Crear el objeto Request. Castearlo directamente a HttpWebRequest, puesto que el Create, aunque devuelva un WebRequest, en realidad es un objeto HttpWebRequest (que es un subtitpo de WebRequest).
- Configurar la request, indicando que se va a usar POST (obligatorio), el content-type (opcional), la longitud (obligatorio) y la versión del protocolo HTTP (opcional).
- Obtener un steam de la petición. Se va a añadir los parámetros como si fueran bytes, que al fin de cuentas es el contenido de la petición.
- Terminamos haciendo una llamada a GetResponse para obtener la respuesta.
El código de todo este proceso sería algo parecido a lo siguiente:
1: HttpWebRequest httpRequest =
2: HttpWebRequest.Create("http://direccion.com/pagina") as HttpWebRequest;
3: httpRequest.Method = "POST";
4: httpRequest.ProtocolVersion = HttpVersion.Version11;
5: // Parameters es un string que contiene todos los parametros en
6: // formato param1=value¶m2=¶m3=value
7: httpRequest.ContentLength = Encoding.ASCII.GetByteCount(parameters);
8: httpRequest.ContentType = "application/x-www-form-urlencoded";
9:
10: using (Stream requestStream = httpRequest.GetRequestStream())
11: {
12: byte[] parametersBuffer = Encoding.ASCII.GetBytes(parameters);
13: requestStream.Write(parametersBuffer, 0, parametersBuffer.Length);
14: }
15: WebResponse httpResponse = httpRequest.GetResponse();
01 Dec 2009
Muchas veces necesitamos que un assembly esté en el GAC para no estar preocupados de incluirlo en cada proyecto. Simplemente, lo seleccionamos de la ventana “Add Reference” de Visual Studio, y somos felices con ello. Sin embargo, esta semana pasada me surgió la necesidad de añadir un assembly al GAC por mí mismo.
No es que sea demasiado difícil, basta con copiarlo a c:windowsassembly. Hasta un tecnicoless podría hacerlo. Sin embargo, no apareció mágicamente en la ventana de Add Reference. ¿Qué había hecho mal? ¿Qué me faltaba? Buceando un poco por Internet encontré a un tipo explicando cómo hacerlo de 3 formas distintas.
Huelga decir que elegí la más sencilla: copiar mi assembly a C:Program FilesMicrosoft Visual Studio 9.0Common7IDEPublicAssemblies
Rearrancar el Visual Studio fue suficiente para ver mi assembly en la pestaña .NET. ¿Fácil no?