Hoy me ha tocado añadir UnitTests a un proyecto ya empezado, por lo que no he podido usar TDD.
Buscando he encontrado una macro que genera el equeleto de las pruebas basado en el codigo actual.
http://www.pcisys.net/~gweakliem/Gordon/UnitTesting.html
Otro web con buenas utilidades para .NET
http://www.sliver.com/dotnet/index.aspx
Esta entrada en el blog de Iván da un buen resumen de lo que se puede hacer y como con Code Access Security
dotNet Reflector es una gran herramienta para examinar el contenido de Assemblies. Como dicen en inglés "a must tool"
Se puede encontrar en : http://www.aisto.com/roeder/dotnet/
Desde que uso SharpReader ya no navego buscando noticias ;-)
Los feeds a los que estoy suscrito están aqui (formato SharpReader). este formato se puede importar directamente
El repositorio de los ejemplos que acabo empaquetando sigue siendo mi workspace en GotDotNet
Hasta ahora pensaba que a los programadores Web se les llamaba Webberos
pero parece ser que el último término que aceptamos es: Pagineros
Al final siempre que me pongo acabo liandome.
Despues de tener la macro funcionando, me di cuenta de que estaria bien poder
configurar un par de parametros, como la versión de NUnit, o si se quiere usar
el runner GUI o de consola.
Asi que manos a la obra:
el TODO LIST:
1) Mostrar un Formulario desde una Macro
2) Acceder a las propiedades de configuración desde la Macro
3) Pones Nombres a las clases resultantes
4) Ejecutar la Macro desde el Formulario
5) Probar con varios proyectos en una solución.
Solutions
1) Lo más sencillo, crear un Formulario con VB.NET,
copiar y pegar en el proyecto de Macros.
En el punto de entrada de la Macro:
ConfUI = New NUnitProjectConfigUI ConfUI.ShowDialog()
Con esto ya tenemos accesible al form desde la Macro.
Los datos de localización de los binarios de NUNit los dejamos como constantes en un Modulo.
Public Const BASE_PATH As String = "c:\Program Files\NUnit " Public Const NUNIT_FX As String = "\bin\nunit.framework.dll" Public Const REF_ID As String = "nunit.framework" Public Const CONSOLE_RUNNER As String = "\bin\nunit-console.exe" Public Const GUI_RUNNER As String = "\bin\nunit-gui.exe"
2) Definimos las propiedas publicas que necesitamos desde la Macro
Public WriteOnly Property CurrentProject() As String Public ReadOnly Property NUnitFxPath() As String Public ReadOnly Property CurrentRunner() As String Public ReadOnly Property StartArgsPrefix() As String
La implementación de estas propiedades se basa en los controles seleccionados en
el Formulario (para más detalle ver fichero adjunto).
3) Ahora que ya tenemos unas cuantas clases es el momento de pensar de nuevo
los nombres (suelo cambiar el nombre de las clases, funciones y parametros tres
o cuatro veces antes de encontrar la definitiva)
Public Module NUnitProjectEnabler
Public Module NUnitConstants
Friend Class NUnitProjectConfigUI
Inherits System.Windows.Forms.Form
4) Ejecutar una función en NUnitProjectEnabler
desde el formulario NUnitProjectConfigUI implicaba tener una referencia
a la macro desde el UI, esto es crear un Dependecia entre el Form y la
macro, cosa poco recomendable.
Para evitar esta dependencia se han definido dos delegates de forma
que el módulo NUnitProjectEnabler, despues de instanciar el formulario NUnitProjectConfigUI
decide que función se debe ejecutar en respuesta a un click del usuario.
Friend Delegate Sub ConfigureProjectDelegate() 'NUnitProjectConfigUI Public ConfHandler As ConfigureProjectDelegate Public ResetHandler As ConfigureProjectDelegateNUnitProjectEnabler
ConfUI.ConfHandler = New ConfigureProjectDelegate(AddressOf EnableProject)
ConfUI.ResetHandler = New ConfigureProjectDelegate(AddressOf ResetProject)
5) Este punto es donde me he quedado, todavia no he entendido muy bien el modelo
de objetos de EnvDTE, asi que de momento se queda en la lista, y se usara el proyecto
seleccionado antes de ejecutar la macro.
Ahora el 95 (%) del código que escribo está acompañado de PruebasUnitarias.
Esto significa que cada vez que quiero (ejecutar, depurar, probar..) tengo varias opciones.
1)Abrir NUnit, cargar el assembly y RunTests !
2)Pegarme al proceso con DebugProcess de VS
3) configurar el proyecto para que al ejecutar arranque NUnit.
Esta ultima es la que hago más amenudo, asi que harto de repetir
la misma tarea una y otra vez he decido hacer una macro:
Imports EnvDTE Imports System.Diagnostics Imports VSLangProjPublic Module NUnitProjectEnabler
Private CurrentProject As VSProject
Private Const NUNIT_PATH As String = "c:\Program Files\NUnit V2.0\bin\nunit.framework.dll"
Private Const NUNITGUI_PATH As String = "c:\Program Files\NUnit V2.0\bin\nunit-gui.exe"Private Sub setTargetProject()
CurrentProject = DTE.ActiveSolutionProjects(0).Object
End Sub
Private Sub AddNUnitRef()
CurrentProject.References.Add(NUNIT_PATH)
End SubPrivate Sub SetDebugProperties()
Dim assemblyName As EnvDTE.Property = CType(CurrentProject.Project.Properties.Item("AssemblyName"), EnvDTE.Property)
Dim configProps As Properties = CurrentProject.Project.ConfigurationManager.ActiveConfiguration.Properties
With configProps
.Item("StartAction").Value = prjStartAction.prjStartActionProgram
.Item("StartProgram").Value = NUNITGUI_PATH
.Item("StartArguments").Value = "/assembly:" + assemblyName.Value + ".dll"
End WithEnd Sub
Public Sub EnableProject()
setTargetProject()
AddNUnitRef()
SetDebugProperties()
End Sub
End Module
como veis las rutas estan puestas a "capon"..
El libro de ADO.NET más útil que conozco
···Microsoft® ADO.NET (Core Reference)
Los ejemplos son claros y van al grano, el autor se propone escenarios bastante reales y muy ilustrativos,
fundamental el capitulo acerca de conflictos de actualización.
El parser XML con el que estoy más familiarizado sigue siendo MSXML, sorprendente ¿no?
Tiene una explicación, en .NET vemos XML en todos sitios (ficheros de configuración, DataSets, esquemas...)
pero siempre encuntras unas clases que te abstraen de la tediosa tarea de masticar el XML.
Hoy ha sido el primer día que me he visto en la necesidad de consultar un stream XML, ha costado un
poco, sobre todo por que los Namespaces que definian el documento.
El documento:
Obtener el contenido del nodo faultcode con MSXML es tan sencillo como
Public Function parseSoapFault(xml as String) as String ···Dim doc as new MSXML.DOMDocument ···Dim node as MSXML.IXMLNode ···doc.loadXml(xml) ···node = selectSingleNode("/soap:Envelope/soap:Body/soap:Fault/faultcode") ...parseSoapFault = node.value End Public
Lo que no me gusta de este método es que necesito guardar todo el DOM en memoria,
igual que si fuese a modificar el documento, con System.Xml tenemos otra alternativa,
que se basa en usar la clase XPathNavigator para poder cargar el DOM en modo
sólo lectura. Además en vez de trabajar con strings cargamos el documento
directamente desde un Stream. Este el código resultante:
public static string parseSoapFault(Stream responseStream) { string result = String.Empty; XPathDocument doc = new XPathDocument(responseStream); XPathNavigator nav = doc.CreateNavigator(); XPathExpression expr = nav.Compile("/soap:Envelope/soap:Body/soap:Fault/faultcode"); XmlNamespaceManager context = new XmlNamespaceManager(nav.NameTable); context.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/"); expr.SetContext(context); XPathNodeIterator iter = nav.Select(expr); iter.MoveNext(); result = iter.Current.Value; responseStream.Close(); return result; }
Dando una vuelta por la blogosfera me he econtrado con este artículo,
no estoy de acuerdo 100% pero es un buen principio.
Los principios del Programador
otros blogs relacionados con la programación en español:
Si, aunque poca gente lo sepa, JavaScript soporta algo parecido a la programación orientada a objetos.
Se pueden hacer clases, implementar jerarquias e incluso polimorfismo.
function Employee () { this.name = ""; this.dept = "general"; } function Manager () { this.reports = []; } Manager.prototype = new Employee;function WorkerBee () {
this.projects = [];
}
WorkerBee.prototype = new Employee;
extraido del mejor artículo que conozco (de Netscape):
Details of the Object Model