Esecuzione parallela di Unit Test in Visual Studio 2010

Print Content | More

Molto probabilmente ne avranno parlato in tanti, ma scopro solo ora che in Visual Studio 2010 è possibile eseguire più Unit Test contemporaneamente se si ha a disposizione una o più CPU MultiCore; ma partiamo con ordine e vediamo come nasce questa esigenza e in quali casi tale approccio può aiutarci.
Dato il continuo aumentare dei test in Dexter, alcuni dei quali impiegano un tempo piuttosto alto (es: gli Smock Test, che verificano il funzionamento di tutte le skin e dei metodi asincroni), mi sono chiesto se era possibile far sì che l’esecuzione di tutti questi test non fosse seriale ma parallela, in modo da ridurre il tempo di esecuzione. Fortunatamente “sbingando” un po’ ho trovato questo interessantissimo post che spiega come la cosa sia fattibile con Visual Studio 2010.

I test sono una cosa seria :), e prima di scegliere un approccio del genere è necessario sapere che l’esecuzione parallela dei test richiede che alcune regole siano rispettate, quindi è bene sapere che essa:

  • è utilizzabile solo in macchine multi Core/CPU;
  • richiede che tutti i test siano Thread Safe;
  • è utilizzabile solo per gli Unit Test (quindi gli Smock Test non ne trarrebbero beneficio);
  • è utilizzabile solo per i test in esecuzione sulla propria macchina;
  • richiede che i Data Adapter siano disabilitati;

Per tutta questa serie di motivi questa opportunità non è attiva di default, e quindi è necessario andare specificare che tutte le regole sopra elencate sono state rispettate e che vogliamo eseguire più test in parallelo.

Per prima cosa è necessario andare a modificare la configurazione dei nostri test e disabilitare i “Data Adapter”; per far ciò è sufficiente fare doppio Click sul file “.testsetting” presente all’interno della nostra solutions: a questo punto dovrebbe aprirsi una finestra come la seguente, dove dobbiamo disabilitare tutte le checkbox presenti all’interno della scheda “Data and Diagnostics”:

image

Completato questo step è ora necessario modificare nuovamente lo stesso file, ma tramite l’editorXML, in quanto l’opzione che andremo ad impostare non è configurabile tramite la UI presente in Visual Studio.
Quindi click con il destro sullo stesso file e selezione della voce “Open With”, ed a quel punto scelta della voce “XML (text) Editor”; da qui in poi è possibile andare a cambiare la configurazione dei test e modificare il nodo Execution, specificando l’attributo “parallelTestCount” ed impostandogli come valore il numero di Core/CPU che si intende utilizzare per l’esecuzione dei test (impostando 0 come valore, sarà il sistema a stabile il numero di Core/CPU da utilizzare).

A questo punto siamo abili ed arruolati per eseguire UnitTest in parallelo.
VS2010 Rulez!

Ciauz


Visual Studio 2010 , Unit Test

0 comments

Alcuni problemi con l’AntiForgeryToken in ASP.NET MVC 2

Print Content | More

È un po’ che ho “in canna” questo post, ma l’ultimo periodo è stato veramente intenso e non mi ha concesso molto tempo per poter postare.

L’argomento in questione è l’utilizzo dell’attributo (o l’helper) AntiForgeryToken sul porting di applicazioni MVC2, che può causare non pochi problemi in fase di deploy di applicazioni distribuite.

Nello specifico si rischia di incappare in una serie di errori 500 come quello mostrato di seguito:

[InvalidCastException: Unable to cast object of type 'System.Web.UI.Triplet' to type 'System.Object[]'.]
   System.Web.Mvc.AntiForgeryDataSerializer.Deserialize(String serializedToken) +104

[HttpAntiForgeryException (0x80004005): A required anti-forgery token was not supplied or was invalid.]
   System.Web.Mvc.AntiForgeryDataSerializer.Deserialize(String serializedToken) +368
   System.Web.Mvc.HtmlHelper.GetAntiForgeryTokenAndSetCookie(String salt, String domain, String path) +209
   System.Web.Mvc.HtmlHelper.AntiForgeryToken(String salt, String domain, String path) +16
   System.Web.Mvc.HtmlHelper.AntiForgeryToken() +10
  <snip>

L’eccezione si verifica su tutti gli utenti collegati; ma facciamo un passo indietro e cerchiamo di capire quali fattori possono determinare un problema di questo genere.

Per prima cosa il problema si riscontra solo su applicazioni che sono state aggiornate alla versione 2 di ASP.NET MVC (quelle nate da questa versione rimangono estranee al problema) e, nello specifico, in una farm in cui non tutte le applicazioni sono state aggiornate -(quindi una situazione ibrida, stessa applicazione ma su alcuni server in MVC1 e su alcuni su MVC2); per complicare la situazione, e nel caso replicarla, è necessario che il balancer in fronte ai server web sia configurato in Round Robin, e che quindi l’utente, ad ogni richiesta, possa esser rimbalzato da un server ad un altro.

Come potete vedere la casistica è molto ristretta, ma la fortuna sicuramente non è dalla mia parte ed ovviamente ci sono incappato in pieno.

In questo post James Crowley spiega nel dettaglio la problematica.

Be careful!
Ciauz


MVC , Exception , Security , Farm

0 comments

ForEach in un IEnumerable<T>

Print Content | More

Linq è senza ombra di dubbio una delle features più belle introdotte da Microsoft in .NET negli ultimi anni (dopo i Generics); sicuramente anche gli Extension Methods hanno il loro fascino agevolando lo sviluppatore nella scrittura del codice. Purtroppo una cosa che mi manca in Linq (ma in realtà è un extension method) è il ForEach per IEnumerable<T>. In effetti c’è la possibilità di utilizzarlo per IList<T> e per le array, ma non per IEnumerable<T>.
Stufo di scrivere il foreach ogni volta, ho deciso di realizzarmi un’extension method che risolvesse il problema :).

Lo snippet seguente mostra la realizzazione:

/// <summary>
/// Eaches the specified enumeration.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="enumeration">The enumeration.</param>
/// <param name="action">The action.</param>
public static void ForEach <T> ( this IEnumerable <T> enumeration , Action <T> action )
{
    Ensure.That ( enumeration ).IsNotNull ( );

    foreach ( T item in enumeration )
        action ( item );
}

Il suo UnitTest (sempre utilizzando SharpTestEx):

[TestMethod]
public void eachTest_with_null_object_shold_throw_argumentNullException()
{
    var mockService = MockRepository.GenerateStrictMock<IFakeClass>();
    ActionAssert.Throws<ArgumentNullException>(() => ((IEnumerable<string>)null).ForEach(x => mockService.FakeMethod("testValue")));
}

[TestMethod]
public void eachTest_with_valid_object()
{
    IEnumerable<string> values = new List<string> { "testValue1", "testValue2", "testValue3" };

    var mockService = MockRepository.GenerateStub <IFakeClass>();

    values.ForEach(mockService.FakeMethod);

    var calls = mockService.GetArgumentsForCallsMadeOn(obj => obj.FakeMethod(null));

    calls [ 0 ] [ 0 ].Should ( ).Be.EqualTo ( "testValue1" );
    calls [ 1 ] [ 0 ].Should ( ).Be.EqualTo ( "testValue2" );
    calls [ 2 ] [ 0 ].Should ( ).Be.EqualTo ( "testValue3" );
}

 

Ciauz


C# , Linq , Extension Methods

4 comments

Utilizzare l’AntiXss Library per l’AutoEncode di ASP.NET / MVC2 con il .NET Framework 4.0

Print Content | More

Con il .NET Framework 4.0 è stato introdotto l’AutoEncode per i codeblocks di ASP.NET/MVC, come già detto qui; proprio in quel post concludevo dicendo:

Sarebbe bello poter specificare un provider per cambiare il sistema di encoding, e magari anche sostituire l’HtmlEncode della classe HttpUtility con quello della Anti-XSS.

ed ho scoperto da poco che la cosa è realmente fattibile.

Per realizzare ciò il lavoro è piuttosto semplice, sono sufficienti pochi passaggi per poter estendere l’HtmlEncode offerto dalla classe HttpUtility con quello più affidabile offerto dalla AntiXss Library.

Per prima cosa è necessario creare una classe che eredita da System.Web.Util.HttpEncoder e che effettua l’override degli opportuni metodi, sostituendo ed implementando l’HtmlEnoding con l’AntiXss Library, come mostrato di seguito:

public class AutoEncodeWithAntiXss : HttpEncoder
{
    protected override void HtmlEncode(string value, TextWriter output)
    {
        output.Write(AntiXss.HtmlEncode(value));
    }

    protected override void HtmlAttributeEncode(string value, TextWriter output)
    {
        output.Write(AntiXss.HtmlAttributeEncode(value));
    }
}

Come ultimo step è necessario registrare la nostra classe nel web.config e, dal quel momento in poi, tutto ciò che utilizza l’autoencode introdotto con ASP.NET 4.0 utilizzerà la nostra classe.

<system.web>
    <httpRuntime encoderType="Imperugo.Web.Test.AutoEncode.AntiXSS.AutoEncodeWithAntiXss, Imperugo.Web.Test.AutoEncode.AntiXSS"/>

La classe System.Web.Util.HttpEncoder permette di effettuare l’ovveride di altri metodi, come l’HtmlDecode, ma l’AntiXss Library non supporta l’HtmlDecode; per questo motivo non è stato effettuato l’override.

Ciauz


ASP.NET 4.0 , MVC , Security

0 comments

QMatteoQ è online

Print Content | More

Il buon Matteo, mio collega in Gaia, ha aperto un blog che potete trovare all’indirizzo qmatteoq.tostring.it (ovviamente gira su dexter): chi è interessato al mobile, quindi IPhone, IPad, Windows Phone etc., non può non seguirlo! Un MUST!

Un mega in bocca al lupo per questa sua nuova avventura.

Ciauz


Mobile , Friends

0 comments

Unit Test con SharpTestEx

Print Content | More

Ultimamente, lavorando in Dexter, ho deciso di metter su un po’ di test; diciamo pure che le buone intenzioni ci sono, e come prima cosa ho deciso di testare tutto ciò che di nuovo introduco (al momento ho messo solo 108 test, ma spero aumentino velocemente). Ovviamente primo test primo “problema” :). Come prima cosa avevo la necessità di testare un metodo tipo il seguente:

public class Foo
{
    public void TestMethod(string value1, string value2, string value3)
    {
        if (string.IsNullOrEmpty(value1))
            throw new ArgumentNullException("value1");

        if (string.IsNullOrEmpty(value2))
            throw new ArgumentNullException("value2");

        if (string.IsNullOrEmpty(value3))
            throw new ArgumentNullException("value3");

        //DO SOMETHING
    }
}

ed il primo test era una cosa tipo questa:

[TestMethod()]
[ExpectedException(typeof(ArgumentNullException))]
public void TestMethodTest()
{
    Foo foo = new Foo();
    foo.TestMethod(null,null,null);
}

Il problema era legato alle eccezioni, nello specifico volevo verificare che, nel caso i parametri fossero nulli, venisse sollevata l’oppurtuna ArgumentNullException. Detto così nessun problema, basta inserire l’attributo ExpectedException (come mostrato nel codice precedente) ed il gioco è fatto. Però la cosa che non mi piace è che, ipoteticamente, io potrei non avere la certezza che l’eccezione è stata sollevata per il primo, il secondo o il terzo parametro (nel caso fossero tutti e tre nulli) e, per esserne sicuro, devo verificare il ParameterName dell’eccezione.
Purtroppo l’attributo di MSTest non permette di specificarlo, così ho avuto tre idee:

  • Metto un try/catch nel test e verifico manualmente il ParameterName;
  • Creo un attributo custom che permette di specificare l’eventuale parametro;
  • Chiamo Gian Maria che sicuramente ha affrontato il problema;

Sono bastati 5 secondi e la terza opzione si è concretizzata e, su suggerimento del buon Alkampfer, ho deciso di provare SharpTestEx del buon Fabio Maulo. Devo dire che la prima impressione è ottima: l’utilizzo Fluent è molto comodo, in più lo stesso Framework può essere utilizzato non solo con MSTest, ma anche con NUnit, xUnit, MbUnit.
Ovviamente il consiglio di Gian Maria non poteva che essere ottimo, ed il problema si è risolto molto velocemente:

[TestMethod()]
public void TestMethodTest2()
{
    Foo foo = new Foo();
    ActionAssert.Throws<ArgumentNullException>(() => foo.TestMethod("prova", null, "prova2"))
                            .ParamName
                            .Should ( )
                            .Be
                            .EqualTo("value2");
}

Molto probabilmente SharpTextEx sarà il mio Framework di testing per un po’, anche se mi riservo di provare TypeMock per effettuare UnitTest sulle WebForms.
Ciauz


Unit Test , SharpTestEx

2 comments

Migration done!

Print Content | More

Se state leggendo questo post vuol dire che la miagrazione da WebHost4Life a ASPNix è andata a buon fine ed i DNS si sono propagati. Purtroppo un cambio necessario, dovuto ad una qualità che andava sempre di più sparendo. Personalmente ho avuto modo di vedere cosa hanno combinato a Lorenzo (migrazione da Sql2000 a Sql2008 su un db con una Collation differente col il conseguente problema dei dati rovinati all’interno del database, il tutto senza dire nulla all’utente) ed ho letto quanto accaduto a Markino (vedi qui, qui ). Prima che ciò accadesse anche a me, ho deciso di levare le tende (la preview della migrazione non augurava nulla di buono neanche per il mio blog).

Oltre ai vari problema, la cosa che mi ha spinto di più a migrare è stato il totale silenzio ed il far nulla da parte loro. Ormai sono 4gg che Lorenzo è stato migrato e, ad oggi, loro non hanno ancora risposto al ticket e fatto nulla per risolvere il problema.
Così, su consiglio del buon Markino, ho deciso di migrare a ASPNix con un bel risparmi economico; per ora sembra essere andato tutto liscio ed il sito è up & running.

Speriamo bene per il futuro :)

Ciauz


OT , Provider

5 comments

Un Resource Manager molto fluent per migliorare le performance

Print Content | More

Ormai, al giorno d’oggi, se non si sviluppa un qualcosa che offra un utilizzo Fluent allora vuol dire che il codice non è figo :D. Ovviamene in Dexter non potevamo rimanere indietro, per cui, per seguire questa “moda”, ho deciso di sviluppare un Resource Manager per effettuare il combine ed il minifier dei javascript e dei css.

Proprio osservando la mia skin mi rendo conto di avere un numero piuttosto alto di includes al suo interno (css del sito, css del codehightlither, shadowbox, etc), e la stessa cosa vale per i js (in realtà sono anche di più dei css). Già in passato (vedi qui) avevo parlato dei vantaggi che si hanno nel ridurre al minimo le chiamate del browser verso il client, ma purtroppo l’approccio mostrato in quel post non era utilizzabile in ASP.NET MVC.

Il goal che mi ero proposto era creare un qualcosa di molto semplice che permettesse di accorpare il numero di files js/css in un unico file e di restituire quest’ultimo effettuando un minify (quindi rimuovendo gli spazi inutili), mettendo in cache il riusultato, con dipendenza sui files in uso.

Ovviamente mi sono dovuto munire di alcuni strumenti che mi rendessero più agevoli alcune operazioni come il minify. Su consiglio di Alessandro, ho deciso di appoggiarmi alla libreria offerta da Yahoo, che svolge il suo lavoro egregiamente. Per il resto, con un paio di handlers, alcune interfacce, una classe ed alcuni extension methods ho raggiunto questo risultato:

<%= ResourceManager.Js()
        .Combine()
        .Minify()
        .Add(SkinJs("codeHighlither/shCore.js"))
        .Add(SkinJs("codeHighlither/shBrushCSharp.js"))
        .Add(SkinJs("codeHighlither/shBrushXml.js"))
        .Add(SkinJs("XFNHighlighter.js"))
        .Add(SkinJs("jquery.cookie.js"))
        .Add(SkinJs("jquery.highlight-3.yui.js"))
        .Add(SkinJs("customFunction.js"))
        .Add(SkinJs("xVal.jquery.validate.js"))
        .Add(SkinJs("shadowbox.js"))
        .Render()
%>

<%= ResourceManager.Css()
        .Combine()
        .Minify()
        .Add(SkinCss("Site.css"))
        .Add(SkinCss("XFNHighlighter.css"))
        .Add(SkinCss("shCore.css"))
        .Add(SkinCss("shThemeDefault.css"))
        .Add(SkinCss("shadowbox.css"))
        .Add(SkinCss("CodeSnippets.css"))
        .Render()
%>

A pagina renderizzata si ha una chiamata all’handler in cui i files da comprimere vengono passati in querystring (ho dovuto comprimere il risultato per evitare di eccedere nella lunghezza massima utilizzabile da una querystring), che svolgerà il resto del lavoro.

La cosa che mi è piaciuta di più è che, con questa classe, anche se non si vuole effettuare né il combine né il minify, quindi renderizzare i semplici tag per i css e js come nelle normali pagine, il risultato è più comodo e veloce; di fatto il seguente snippet:

<%= ResourceManager.Js()
        .DoNotCombine()
        .DoNotMinify()
        .Add(SkinJs("codeHighlither/shCore.js"))
        .Add(SkinJs("codeHighlither/shBrushCSharp.js"))
        .Render()
%>

renderizza il seguente markup:

<script src="/codeHighlither/shCore.js" type="text/javascript"></script>
<script src="/codeHighlither/shBrushCSharp.js" type="text/javascript"></script>

Giusto per aggiungere un po’ di numeri al post, nella mia skin sono riuscito ad accorpare 9 files javascript in un un’unico file, riducendo il peso da 79kb a 60kb; inoltre, accorpando 6 files css, ho ottenuto una riduzione quasi del 30% (53kb contro i 38kb del minify).

Un paio di screenshot per mostrare il fantaggio tratto da tale approccio.

notCombined

Combined

A breve il codice sorgente sia dell’interfaccia fluent che degli httphandler per il minify.

Stay tuned.


Performances , MVC , Ottimizzazione , Dexter

0 comments

dexter su MVC 2.0 :)

Print Content | More

Ho approfittato del recente rilascio e della possibilità di utilizzare ASP.NET MVC 2.0 su Visual Studio RC per effettuare un po’ di refactoring del repository di Dexter e migrarlo alla versione 2.0 di MVC.

Per chi segue lo sviluppo del codice la vecchia trunk è stata rinomina in “trunk (mvc 1.0)” e la considero come deprecata, non ci saranno sviluppi sopra. Il lavoro si è spostato su una branch (che poi è la nuova trunk) che gira su asp.net mvc 2.
Il porting è stato semplicissimo, basta utilizzare l’apposito tool (lo trovate qui) e, nel caso di dexter, è stato necessario modificare un solo metodo (causa nuovo overload) per il controllerbase.

Una nota da segnalare sono i progetti di Testing, che Visual Studio 2010 converte al Framwework 4.0 e non permette il reverse. Quindi per questi progetti è necessario aprire la solution di VS 2010.

La semplicità di questo porting mostra la buona base che c’è su questo prodotto. Il prossimo step per dexter sarà rimuovere tutti i Frameworks e le implementazioni aggiunte alla versione 1.0 di mvc, per colmare alcune mancanze della vecchia versione (come la validazione client side).

Ah, dimenticavo, www.tostring.it gira su mvc 2.0 :)

Ciauz


MVC , Dexter , ASP.NET

1 comments

Utilizzare ASP.NET MVC 2.0 con Visual Studio 2010 RC

Print Content | More

Anche se l’installer della versione RTM di ASP.NET MVC 2.0 è per Visual Studio 2008, esiste ugualmente un modo per utilizzare ASP.NET MVC 2 con Visual Studio 2010 RC.

Questo post di Shiju Varghese spiega come fare.

Enjoy MVC on VS2010 RC :)


ASP.NET , MVC , Visual Studio 2010

0 comments