viernes, 18 de enero de 2013

Pruebas unitarias con SharePoint Emulator Package

No si ustedes hayan notado el mes pasado (con todas las fiestas que había) que el equipo de Visual Studio anuncio el paquete de SharePoint Emulators de Visual Studio 2012 para SharePoint 2010.

De entrada este paquete solo aplica para SharePoint 2010 y utilizándolo en Visual Studio 2012. Es comprensible que este paquete solo aplique para SharePoint 2010, dado el poco tiempo que lleva SharePoint 2013 liberado, además de que la finalidad del emulador es poder probar código de servidor, mismo que Microsoft desalienta escribir para SharePoint 2013.

Este paquete se puede instalar a través de NuGet. Solo tienen que buscarlo y aparece dentro de los resultados.

  
En el pasado había sido bastante difícil aislar los componentes SharePoint de una solución para realizar pruebas unitarias, debido a que estos componentes dependen enormemente de SharePoint, es decir, para poder realizar la ejecución de pruebas de esos componentes era necesario tener instalado SharePoint.
 
SharePoint Emulators Package nos permite crear pruebas unitarias y ejecutarlas sin tener instalado un ambiente de SharePoint, este paquete se basa en el concepto de Shims de Microsoft Fakes para crear un contexto (un conjunto de Shims) en memoria de los objetos más comunes dentro de la API de SharePoint. Con lo que, para crear una prueba unitaria que utiliza objetos de la API de SharePoint lo único que debe hacer es encerrar el código que estamos probando dentro de un SharePoint Emulator Scope.

[TestMethod]
public void CreateList()
{
	using (SharePointEmulationScope scope = new SharePointEmulationScope(Microsoft.QualityTools.Testing.Emulators.EmulationMode.Enabled))
	{
		using (SPSite site = new SPSite("http://UrldePrueba/"))
		{
			using (SPWeb web = site.OpenWeb())
			{
				Assert.IsNotNull(web);

				//Definiendo la lista
				Guid listId = site.RootWeb.Lists.Add(listName, listName, SPListTemplateType.GenericList);
				SPList list = site.RootWeb.Lists[listId];
				Assert.IsNotNull(list);
				Assert.AreEqual(list.Title, listName, "Bad list name!");

				//agregando los campos a la lista
				list.Fields.Add("Code", SPFieldType.Number, true);
				list.Fields.Add("Name", SPFieldType.Text, true);
				list.Fields.Add("Description", SPFieldType.Text, true);

				//agregando dos nuevos elemento a la lista
				SPListItem item1 = list.Items.Add();
				item1["Code"] = 1;
				item1["Name"] = "West";
				item1["Description"] = "West Region";
				item1.Update();

				SPListItem item2 = list.Items.Add();
				item2["Code"] = 1;
				item2["Name"] = "East";
				item2["Description"] = "East Region";
				item2.Update();

				Assert.AreEqual(list.ItemCount, 2, "Bad number of items");
			}
		}
	}
}


Como mencionaba antes, este paquete solo contiene los Shims para los objetos de uso más común dentro de la API de SharePoint, por lo que habrá casos es los que al hacer uso de ciertos métodos o propiedades, que devuelven un tipo de objeto que no tiene su correspondiente Shim dentro del emulador,  obtendremos excepciones de tipo NotSupportedException, como por ejemplo al intentar utilizar el método GetItems de un objeto SPList, que devuelve un objeto de tipo SPListItemCollection.


El siguiente código muestra el método que se está probando, en la línea 17 está la llamada al método GetItems que lanzará la excepción.
public string GetNameByCode(string listName, SPWeb web, int code)
{
	SPList list = web.Lists[listName];

	var listQuery = new SPQuery
	{
		Query = String.Format(
			"" +
			"" +
			"" +
			"{0}" +
			"" +
			"", code)
	};

	string name = string.Empty;
	foreach (SPListItem item in list.GetItems(listQuery))
	{
		name = item["Name"].ToString();
	}

	return name;
}


Lo genial de esto, es que es posible inyectar Shims al Emulador para los tipos no soportados, como por ejemplo para SPListItemCollection, de la forma tradicional, es decir usando Shims, como se aprecia de las líneas 41 a la 50
[TestMethod]
public void SearchItemById()
{
	int searchById = 2;

	using (SharePointEmulationScope scope = new SharePointEmulationScope(Microsoft.QualityTools.Testing.Emulators.EmulationMode.Enabled))
	{
		using (SPSite site = new SPSite("http://UrldePrueba/"))
		{
			using (SPWeb web = site.OpenWeb())
			{
				Assert.IsNotNull(web);

				//Definiendo la lista
				Guid listId = site.RootWeb.Lists.Add(listName, listName, SPListTemplateType.GenericList);
				SPList list = site.RootWeb.Lists[listId];
				Assert.IsNotNull(list);
				Assert.AreEqual(list.Title, listName, "Bad list name!");

				//agregando los campos a la lista
				list.Fields.Add("Code", SPFieldType.Number, true);
				list.Fields.Add("Name", SPFieldType.Text, true);
				list.Fields.Add("Description", SPFieldType.Text, true);

				//agregando dos nuevos elemento a la lista
				SPListItem item1 = list.Items.Add();
				item1["Code"] = 1;
				item1["Name"] = "West";
				item1["Description"] = "West Region";
				item1.Update();

				SPListItem item2 = list.Items.Add();
				item2["Code"] = 2;
				item2["Name"] = "East";
				item2["Description"] = "East Region";
				item2.Update();

				Assert.AreEqual(list.ItemCount, 2, "Bad number of items");

				//Agregamos el Shimp para el objeto SPListItemCollection
				if (scope.EmulationMode == EmulationMode.Enabled)
				{
					var fakeList = new ShimSPList(list);
					fakeList.GetItemsSPQuery = (query) =>
					{
						var shim = new ShimSPListItemCollection();
						shim.Bind(new[] { list.Items[0], list.Items[1] });
						return shim.Instance;
					};
				}

				RegionGateway gateway = new RegionGateway();

				//Ahora al realizar la llamada al metodo GetNameByCode, no se lanzara la excepcion
				string result = gateway.GetNameByCode(listName, site.RootWeb, searchById);
				Assert.AreNotEqual(string.Empty, result, true, "Search Failed!");


				Region searchItem = gateway.GetRegionById(listName, web, 1);
				Assert.IsNotNull(searchItem);
				Assert.AreEqual("West", searchItem.Name, true);
			}
		}
	}
}

Sin duda alguna un importante paquete que debiéramos usar desde ya para las pruebas unitarias de nuestro código. Ahora lo importante sería preguntar para cuando este paquete estará disponible para SharePoint 2013.

Por último les comparto el proyecto de Visual Studio para que vean el código y puedan analizarlo mejor.


Referencias

Happy Code!

0 comentarios:

Etiquetas

SharePoint 2010 (38) Microsoft (32) Desarrollo SharePoint (31) Gerardo Reyes Ortiz (27) SharePoint (20) SharePoint 2013 (18) Errores SharePoint (12) México (10) PowerShell (9) Silverlight (8) Visio Services (7) Features (6) MVP (6) Silverlight 3 (6) WebCast (6) Workflows (6) Configuracion SharePoint 2010 (5) D.F. (5) API REST (4) Configuracion SharePoint 2010; (4) Troubleshooting (4) Visual Studio 2010 (4) Visual studio (4) WSS (4) Web parts (4) Apps (3) Comunidad SharePoint (3) Configuración SharePoint 2013 (3) ODATA (3) SharePoint Server (3) SharePoint; Instalación SharePoint; Troubleshooting; Search Service (3) Silverlight 3.0 (3) Silverlight Toolkit (3) WebParts (3) javascript (3) jquery (3) Eventos SharePoint (2) Office 2010 (2) PeoplePicker (2) REST (2) SQL Server (2) Scripting (2) Search Service Application (2) SharePoint Designer (2) UPA (2) UPS (2) Workflows SharePoint (2) host header (2) Apps Development (1) Big Bang (1) CAS (1) CSOM (1) Codeplex (1) CompartiMOSS (1) Configuracion SharePoint 2010; Errores SharePoint (1) Configuracion SharePoint 2010; SharePoint 2010 (1) Custom Actions (1) Custom Editor Parts (1) Delegate Controls (1) Deployment (1) DisableLoopbackCheck (1) Document Library (1) Entrevista (1) Examenes de Certificación (1) Extract WSP (1) FBA (1) FS4SP (1) Fakes (1) Fast Search Server 2010 For SharePoint (1) Fiddler (1) HTTP.SYS (1) HTTPS (1) JSON (1) Language Pack's (1) Latam (1) MAXDOP (1) MCSM (1) MSExpertos (1) MVC (1) Microsoft México (1) Microsoft; Codeplex; Screencast; (1) My Sites (1) SQL Server 2012 (1) SQL Server Reporting Services (1) Screencast (1) Screencast; (1) Service Applications (1) Service Pack (1) SharePoint 2007 (1) SharePoint 2010 SP 1 (1) SharePoint API (1) SharePoint Conference (1) SharePoint Emulators (1) SharePoint Farm (1) SharePoint Health Analyzer (1) SharePoint Magazine (1) SharePoint Online (1) SharePoint Search (1) SharePoint Test (1) SharePoint; Desarrollo SharePoint (1) Shims (1) Simposio (1) Simposio Latinoamericano (1) SkyDrive Pro (1) Soporte Microsoft (1) Templates (1) Tip (1) VSeWSS (1) Virtual Machine (1) Visual Studio 2012 (1) WCF (1) WSS; IIS 7 (1) Web API (1) Web Content Management (1) Web Services (1) Windows 8 (1) Windows Live ID (1) Xml (1) appcmd (1) iOS (1) jqGrid (1) onload function (1)