TFS2008 Proposito del año

Mi buen amigo Rodrigo me dice: «A ver si jubilas NUnit y te pasas a Team System«. Bien, ese es mi propósito para el año entrante.

Jubilar NUnit, CruiseControl, RedMine y mi querido Subversion. En cuanto salga Windows Server 2008, y Team System 2008 será lo primero que haga, remodelar mi pequeña y barata infraestructura.

Como decía actualmente estoy usando lo siguiente en un modesto Pentium 4, con 512Mb de Ram que hace las labores de mini-servidor en casa.

Pruebas unitarias: MbUnit y NUnit
Integración Continua: CruiseControl.Net y CruiseControl.rb
Cobertura de código: NCover
Construcción: Nant
Repositorio de código: Subversion
Gestión de proyectos: RedMine

Una infraestructura de coste 0, versátil y potente, que me permite hacer prácticamente de todo.

Si, tal vez no esté todo integrado ni disponga de un entorno unificado, pero no se le ha resistido prácticamente nada. Herramientas con las que he pasado horas y horas de esas noches desveladas en que el proceso de automatizar tareas se convierte casi en  una experiencia religiosa, “ala Enrique Iglesias” si, descubriendo el infinito… herramientas que han dejado el listón muy arriba, que por el momento me hacen dudar si TFS estará a la altura, si llegará a cautivarme como lo han hecho mis queridas compañeras…

Incluida la última en llegar que ha sido RedMine, para aquellos que no la conozcan, es un gestor de proyectos, escrito en Ruby por Jean-Philippe Lang y es uno de los proyectos más activos dentro de la comunidad de Ruby.  

Con RedMine, se pueden gestionar diversos proyectos de toda índole, aunque está basado en Ruby, yo por ejemplo lo uso para gestionar proyectos  .Net, permite que varias personas trabajen en el mismo equipo, planificar objetivos, seguimiento de incidencias, gestión de la documentación del proyecto mediante Wiki, Foros, integración con distintos repositorios de datos (Subversion, CVS, Mercurial, Bazaar y Dracs), autentificación por LDAP etc…

Yo incluso lo tengo personalizado (lo bueno de poder tocar el código) para que me muestre en la página principal de los proyectos información sobre la últimas compilaciones, información que proviene del CruiseControl.

También, modifique el visor del repositorio para poder mostrar código c# con la sintaxis coloreada, para que gestionar documentación sobre los frameworks, ver informes sobre cobertura etc… en fin, pueden ser pijadas para algunos, en fin echaré de menos todas esas horas editando archivos XML, encadenando procesos y generando informes…   

Prometo contar mis experiencias religiosas con TFS el año que viene…

SharePoint – Pruebas Unitarias (3)

Alguien me ha recordado que empecé a escribir sobre el tema de las pruebas
unitarias y finalmente no termine… o por lo menos no conté algunas de las
prácticas que uso… cierto.

Parte 1Parte 2

Básicamente la técnica que uso habitualmente consiste en aprovisionar un
sitio de forma automática. Y ¿Cómo se aprovisiona un sitio automáticamente?,
pues de la manera más sencilla posible. Usando Plantillas.

Provisión – Escenario de Pruebas

De modo que tengo distintas plantillas pre cargadas con listas, bibliotecas
de documentos, páginas etc… algunas incluyendo contenido, archivos, elementos de
las listas y un montón de cosas.

Es sencillísimo crear estos escenarios y pueden ser simples, incluyendo uno ó
unos pocos elementos ó complejos incluyendo una jerarquía de de sitios, en cuyo
caso crearemos una plantilla por cada sitio para más tarde reconstruir una
jerarquía de sitios determinada.

Después usamos un ayudante en nuestras pruebas para aprovisionar nuestros
sitios, un ejemplo de un aprovisionador de sitios  básico sería algo como
esto, he recortado algunas cosas …

public class SPProvisioningHelper
{
private const string DefaultWebName = "TestSite";
private readonly Dictionary<string, SPWeb> _webs;

private SPSite _site;
private string _urlTestSite;

public SPProvisioningHelper()
{
_webs = new Dictionary<string, SPWeb>();
UrlTestSite = "http://enjendro/unittests/";
}

// Url del sitio de pruebas public string UrlTestSite
{
get { return _urlTestSite; }
set { _urlTestSite = value; }
}

// Coleccion de sitios sobre la que estamos trabajando public SPSite Site
{
get { return _site; }
}

// Una web determianda public SPWeb GetWeb(string name)
{
return _webs[name];
}

// Provisiona una web vacia colgada de parentUrl // Pruebas rápidas y de creación de elementos public void WebProvisioning(string parentUrl)
{
_webs.Add(DefaultWebName, CreateWeb(DefaultWebName, parentUrl, string.Empty));
}

// Crea una web public void WebProvisioning(string name, string parentUrl)
{
_webs.Add(name, CreateWeb(name, parentUrl, string.Empty));
}

// Crea una web basada en una plantilla public void WebProvisioning(string name, string parentUrl, string template)
{
_webs.Add(name, CreateWeb(name, parentUrl, template));
}

// Crea las webs (hace el trabajo duro) private SPWeb CreateWeb(string title, string parentUrl, string template)
{
Trace.WriteLine(string.Format("Creating test web {0} at {1}", title, parentUrl));

_site = new SPSite(UrlTestSite + parentUrl);
SPWeb web = _site.OpenWeb();
SPWeb newWeb;

// Stop if (web == null)
{
throw new SPException(string.Format("Can´t open SharePoint Site in: {0}", _site.Url));
}

// Si existe lo borramos if (web.Webs[title].Exists)
{
RecursiveDeleteWebs(web.Webs[title]);
web.Webs[title].Delete();
}

// Web vacio if (template.Equals(string.Empty))
{
newWeb = web.Webs.Add(title);
}
else { // web basado en plantilla personalizada try
{
SPWebTemplateCollection webTemplateCollection;
webTemplateCollection = _site.GetCustomWebTemplates((uint) web.Locale.LCID);

SPWebTemplate webTemplate = webTemplateCollection[template];

newWeb = web.Webs.Add(title,
title,
string.Empty,
(uint) web.Locale.LCID,
webTemplate,
true,
false);
}
// web basado en plantilla no personalizada catch (ArgumentException)
{
newWeb = web.Webs.Add(title,
title,
string.Empty,
(uint) web.Locale.LCID,
template,
true,
false);
}
}

Trace.WriteLine(string.Format("Created web {0} at {1}", newWeb.Title, newWeb.Url));

return newWeb;
}

// Limpieza public void Clean()
{
DeleteWebs();
// Disposes } // Elimina las webs private void DeleteWebs()
{
foreach (SPWeb web in _webs.Values)
{
RecursiveDeleteWebs(web);
}
}

// Elimina todo recursivamente private void RecursiveDeleteWebs(SPWeb parentWeb)
{
// ... } }

Pruebas

Después en nuestras pruebas podemos inicializar los distintos escenarios, veamos un ejemplo usando el
aprovisionador anterior

[TestFixture]
public class Tests
{
// El ayudante private SPProvisioningHelper provisioningHelper;

[TestFixtureSetUp]
public void Setup()
{
// Incializamos el ayudante provisioningHelper = new SPProvisioningHelper();

// Ejemplos // Aprovisionamos p1 desde una plantilla nuestra provisioningHelper.WebProvisioning("p1", "P1", "Plantilla1.stp");

// jerarquia provisioningHelper.WebProvisioning("p1", string.Empty);

// p1/p1a -> sitio de grupo provisioningHelper.WebProvisioning("p1a", "p1", "STS");

// p1/p1b -> un blog provisioningHelper.WebProvisioning("p1b", "p1", "Blog");

// p1/p1a/p1a1 -> un wiki provisioningHelper.WebProvisioning("p1a1", "p1/p1a", "Wiki");

// p1/p1a/p1a1/p1a11 -> sitio en blanco provisioningHelper.WebProvisioning("p1a11", "p1/p1a/p1a1");

}

// Una prueba simple [Test] public void GetCurrentUserName()
{
string expectedUser = WindowsIdentity.GetCurrent().Name;

SPUser user = provisioningHelper.GetWeb("p1").CurrentUser;

string userName = user.LoginName;

Trace.WriteLine(string.Format("Expected: {0} User: {1}", expectedUser, userName));
Assert.IsTrue(expectedUser.Equals(userName,StringComparison.OrdinalIgnoreCase));
}

// Limpieza [TestFixtureTearDown] public void TearDown()
{
provisioningHelper.Clean();
}
}

Esto es básicamente, desde luego como ocurre con todos los sistemas que deben
ser aprovisionados, estos llevan su tiempo, en cualquier caso tampoco me parece
tanto y además hay unos estupendos quad core relativamente baratos así que no es
escusa para no tener una máquina de pruebas.

Mal dia – backing up is sexy!

Buff, un mes sin escribir nada. La verdad es que le mes pasado ha sido terriblemente duro, en cuanto a trabajo se refiere, además de las dos semanas que me he pasado por el sur de España Sevilla, Córdoba, Málaga y  por Madrid, después a mi regreso me he encontrado con algún que otro desastre y un montón de trabajo acumulado.

Mal día….

El caso es que el viernes por la noche mientras realizaba copias de seguridad de mi portátil, (je, hace un par de días volví a ver el episodio de “Sexo en New York” -Sex and the city- My Motherboard My shelf)

“Always backup and keep it remote – no matter how lucky you feel! And yes – backing up is sexy!”

Me he desesperado con Windows Vista, y la velocidad de copiado de archivos en red. (Y eso que tengo el SP1 RC)

Tras pasar un buen rato el sábado por la mañana buscando por internet, me he encontrado con algunas cosas interesantes como

http://www.technoblogo.com/2007/02/12/Windows+Vista+Tip+3++Slow+Network+Issues.aspx
http://support.microsoft.com/default.aspx/kb/931770/en-us

y otras poco mil entradas que he probado sin mucho éxito…

Después he tratado de activar el 802.11 n que tiene el Linksys RT300N que uso en casa, ya que no me había dado cuenta que el portátil que uso ahora (Compaq 8510p) lleva una tarjeta de red 802.11 n la Intel 4965AGN , esto ha sido el colmo.

Tras perder tres horas no ha habido manera de que detecte el protocolo N (de las Narices) he actualizado firmwares, drivers he cambiado prácticamente todo lo cambiable y probado todo lo probado sin fortuna alguna… incluido el cambio de seguridad WPA2-AES que parece ser es necesario para que se detecte el N, (tras el cual dos de los equipos de casa han dejado de funcionar tienen todavía el XP, lo que me ha llevado a instalar el KB893357, que activa la compatibilidad WPA2, já, pues en mis equipos las tarjetas deben ser muy viejas por qué no lo soportan. )

En ese momento he recordado ese extracto que suele leer Chema Alonso, sobre la configuración de una tarjeta Wifi en Linux, y me he empezado a partir de risa, de pura desesperación .. Así que he optado por abrir unas cervezas .. y hacer de esto una experiencia cuando menos amena …

Finalmente he optado por soltar el disco (es un IOMEGA home network con Ethernet, que tengo conectado al router) y conectarlo por USB a mi portátil, que poco glamur …

De modo que he empezado a copiar los archivos, pero cuando han llegado la Maquinas virtuales …. me he topado con la limitación de copiar archivos de más de 4Gb (fat32) … a ver que alguien me lo explique, hasta ahora copiando archivos por red SMB no había tenido problemas para copiar archivos de más de 4Gb  – No lo entiendo –

De modo que ni corto ni perezoso, decido hacer un convert a NTFS, por si acaso miro en la web de IOMEGA, no vaya a ser que no sea adecuado…

Las recomendaciones típicas de que si pasas a NTFS no podrás volver a FAT32 etc … que no podré usarlo con Linux, Windows 98 o Mac  etc…
De modo que adelante .. (Le llevo casi una hora .. ya que tenía el 50% ocupado) y después lo deje copiando archivos mientras veía una peli.

Más tarde, lo desconecte del USB, lo volví a conectar a la LAN y descanse feliz a pensando de que mis datos estaban a salvo …

“– backing up is sexy!” yeahhh

Bueno, resulta que más tarde he tratado de conectarme por SMB para buscar unos documentos que tenia archivados y HORROR … mi disco ha desaparecido … intento entrar en la parte de administración y ohhh sorpresa … no entra…
 
Tal vez se les haya pasado algún tipo de recomendación en las instrucciones a los señores de IOMEGA.

Bueno, por el momento no he tenido tiempo para ver qué diablos ha pasado exactamente de modo que ya os contaré como termina la historia, por el momento sospecho que el software del firmware no reconoce NTFS. En cualquier caso, podrian publicar el firmware como hacen los señores de Linksys …. 

Ah no estoy excesivamente preocupado ya que de las cosas importantes guardo siempre una copia ó dos en CD ó DVD.

Pero si me he sentido un poco identificado con Carrie …

Desde luego un mal día … but remember “– backing up is sexy!”