<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Extreme Programming</title>
        <link>http://blogs.ugidotnet.org/AntonioGanci/category/2123.aspx</link>
        <description>Extreme Programming</description>
        <language>it-IT</language>
        <copyright>Antonio Ganci</copyright>
        <managingEditor>ugog91@yahoo.it</managingEditor>
        <generator>Subtext Version 1.9.5.176</generator>
        <item>
            <title>Come scrivere uno unit test per controllare l'accesso esclusivo ad una risorsa condivisa da diversi thread</title>
            <link>http://blogs.ugidotnet.org/AntonioGanci/archive/2008/08/17/93727.aspx</link>
            <description>&lt;p&gt;Nel mio precedente &lt;a href="http://blogs.ugidotnet.org/AntonioGanci/archive/2008/06/06/92951.aspx"&gt;post&lt;/a&gt;   ho affrontato il problema di come sviluppare usando il TDD un'applicazione multithreading.  &lt;/p&gt;
&lt;p&gt;   In questo post, cercherò di approfondire su come testare la sincronizzazione per l'accesso ad una risorsa condivisa.  &lt;/p&gt;
&lt;p&gt;   L'obiettivo che voglio raggiungere è scrivere un test che fallisca se non applico un meccanismo di sincronizzazione    (in questo caso la lock) per l'accesso alla risorsa e abbia successo quando viene introdotta       la sincronizzazione.   Il fatto che il test abbia successo deve essere sistematico e non deve esserci nessun elemento di casualità       come l'ordine di schedulazione la velocità del processore.  &lt;/p&gt;
&lt;p&gt;   Vediamo di descrivere lo scenario. La risorsa condivisa è il Broker la cui responsabilità è quella di immettere sul   mercato azionario un ordine di acquisto o vendita di azioni. La classe Broker implementa la seguente interfaccia:  &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 0%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;pre style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;interface&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;IBroker&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;    {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;PlaceOrder&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;Order&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;order&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;    }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;  La classe Order che non riporterò contiene i dati necessari per immettere l'ordine come il prezzo, la quantità di azioni, ecc. &lt;/p&gt;
&lt;p&gt;  L'ultimo elemento di questo scenario è la classe OrderThread, la sua responsabilità è quella di eseguire il metodo PlaceOrder  in un thread creato da lei. &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 0%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;pre style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;class&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;OrderThread&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;    {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;private&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;readonly&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;IBroker&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;_broker&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;private&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;readonly&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Order&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;_order&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;OrderThread&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;IBroker&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;broker&lt;/span&gt;, &lt;span style="color: rgb(199, 199, 241);"&gt;Order&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;order&lt;/span&gt;)&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;_broker&lt;/span&gt; = &lt;span style="color: rgb(254, 241, 169);"&gt;broker&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;_order&lt;/span&gt; = &lt;span style="color: rgb(254, 241, 169);"&gt;order&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        }&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Start&lt;/span&gt;()&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;PlaceOrder&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Start&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        }&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;private&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;PlaceOrder&lt;/span&gt;()&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;_broker&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;PlaceOrder&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;_order&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        }&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;    }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;  Come si può notare alla chiamata PlaceOrder non viene usato nessun meccanismo di sincronizzazione. Quindi due istanze  di OrderThread che utilizzino lo stesso broker potrebbero chiamare contemporaneamente il metodo PlaceOrder dando  luogo ad una &lt;a href="http://it.wikipedia.org/wiki/Race_condition"&gt;race condition&lt;/a&gt;.  Vogliamo scrivere un test che abbia successo se la race condition non possa      verificarsi e fallisca altrimenti. &lt;/p&gt;
&lt;p&gt;  Per ottenere il risultato scriviamo un'implementazione dell'interfaccia IBroker pilotabile dal nostro test che ci  permetta di simulare lo scenario in cui due OrderThread cerchino di chiamare contemporaneamente il metodo PlaceOrder. &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 0%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;pre style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;class&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;SleepingBroker&lt;/span&gt; : &lt;span style="color: rgb(199, 199, 241);"&gt;IBroker&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;    {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;readonly&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;ManualResetEvent&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;_resetEvent&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;ManualResetEvent&lt;/span&gt;(&lt;span style="color: rgb(128, 128, 192);"&gt;false&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;int&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;CallingPlaceOrderCount&lt;/span&gt; { &lt;span style="color: rgb(128, 128, 192);"&gt;get&lt;/span&gt;; &lt;span style="color: rgb(128, 128, 192);"&gt;set&lt;/span&gt;;}&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;PlaceOrder&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;Order&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;order&lt;/span&gt;)&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;CallingPlaceOrderCount&lt;/span&gt;++;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;_resetEvent&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;WaitOne&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;CallingPlaceOrderCount&lt;/span&gt;--;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        }&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;WakeUp&lt;/span&gt;()&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;_resetEvent&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Set&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        }&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;    }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;  Il metodo SleepingBroker.PlaceOrder ci permette di far durare la chiamata a PlaceOrder il tempo necessario   per creare una race condition.  Se il valore della property CallingPlaceOrderCount è maggiore di uno significa che più di un trade sta usando il Broker e  quindi il test deve fallire. &lt;/p&gt;
&lt;p&gt;  Proviamo a questo punto a scrivere il test: &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 0%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;pre style="margin: 0px;"&gt;        [&lt;span style="color: rgb(199, 199, 241);"&gt;Test&lt;/span&gt;]&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Access_To_The_Broker_Should_Be_Synchronized&lt;/span&gt;()&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(199, 199, 241);"&gt;Order&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;order1&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Order&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(199, 199, 241);"&gt;Order&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;order2&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Order&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(199, 199, 241);"&gt;SleepingBroker&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;broker&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;SleepingBroker&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(199, 199, 241);"&gt;OrderThread&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;thread1&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;OrderThread&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;broker&lt;/span&gt;, &lt;span style="color: rgb(254, 241, 169);"&gt;order1&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(199, 199, 241);"&gt;OrderThread&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;thread2&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;OrderThread&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;broker&lt;/span&gt;, &lt;span style="color: rgb(254, 241, 169);"&gt;order2&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;thread1&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Start&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;thread2&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Start&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(199, 199, 241);"&gt;Assert&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;AreEqual&lt;/span&gt;(1, &lt;span style="color: rgb(254, 241, 169);"&gt;broker&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;CallingPlaceOrderCount&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;broker&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;WakeUp&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;  In questo test abbiamo creato due OrderThread che utilizzano lo stesso Broker (in questo caso SleepingBroker).  I due thread vengono fatti partire e controlliamo che effettivamente solo uno sia all'interno del metodo PlaceOrder. &lt;/p&gt;
&lt;p&gt;  Il test apparentemente corretto in realtà &lt;strong&gt;contiene un errore concettuale&lt;/strong&gt;. L'errore è che potrebbe fallire  o avere successo in maniera del tutto casuale perchè dipende dalla velocità di creazione ed esecuzione dei thread al momento  in cui si fa la Assert. &lt;/p&gt;
&lt;p&gt;  Il valore di CallingPlaceOrderCount potrebbe quindi essere 0, 1 oppure due. Zero nel caso in cui entrambi i thread siano  stati creati ma al momento della Assert la chiamata a PlaceOrder non sia ancora avvenuta. Uno nel caso che uno dei due  sia entrato nella PlaceOrder. Due nel caso in cui entrambi siano nella PlaceOrder. &lt;/p&gt;
&lt;p&gt;  Per come abbiamo scritto il test questo non è determinabile. Quindi modifichiamolo sincronizzandoci nel modo corretto.  Per far questo ci viene in aiuto la property &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.threadstate.aspx"&gt;ThreadState&lt;/a&gt;,  nel caso in cui il valore è impostato su WaitSleepJoin come descritto nella MSDN: &lt;/p&gt;
&lt;p&gt; &lt;cite&gt;The thread is blocked. This could be the result of calling Thread..::.Sleep or Thread..::.Join,  of requesting a lock — for example, by calling Monitor..::.Enter or Monitor..::.Wait — or of waiting on a thread  synchronization object such as ManualResetEvent. &lt;/cite&gt; &lt;/p&gt;
&lt;p&gt;  Quindi se entrambi i thread sono in WaitSleepJoin siamo sicuri di poter eseguire la Assert su CallingPlaceOrderCount  nel momento corretto. &lt;/p&gt;
&lt;p&gt;  Per controllare lo stato del thread Aggiungiamo la Property IsWaiting alla classe OrderThread. &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 0%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;pre style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;class&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;OrderThread&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;    {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;private&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;readonly&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;IBroker&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;_broker&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;private&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;readonly&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Order&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;_order&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;private&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;_thread&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;OrderThread&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;IBroker&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;broker&lt;/span&gt;, &lt;span style="color: rgb(199, 199, 241);"&gt;Order&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;order&lt;/span&gt;)&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;_broker&lt;/span&gt; = &lt;span style="color: rgb(254, 241, 169);"&gt;broker&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;_order&lt;/span&gt; = &lt;span style="color: rgb(254, 241, 169);"&gt;order&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        }&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;bool&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;IsWaiting&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(128, 128, 192);"&gt;get&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;                &lt;span style="color: rgb(128, 128, 192);"&gt;if&lt;/span&gt; (&lt;span style="color: rgb(254, 241, 169);"&gt;_thread&lt;/span&gt; == &lt;span style="color: rgb(128, 128, 192);"&gt;null&lt;/span&gt;)&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;                {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;                    &lt;span style="color: rgb(128, 128, 192);"&gt;return&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;false&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;                }&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;                &lt;span style="color: rgb(128, 128, 192);"&gt;return&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;_thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;ThreadState&lt;/span&gt; == &lt;span style="color: rgb(199, 199, 241);"&gt;ThreadState&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;WaitSleepJoin&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            }&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        }&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Start&lt;/span&gt;()&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;_thread&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;PlaceOrder&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;_thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Start&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        }&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;private&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;PlaceOrder&lt;/span&gt;()&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;_broker&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;PlaceOrder&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;_order&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        }&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;    }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;  Quindi ora aggiungiamo il codice nel test che attenda che per entrambi i Thread IsWaiting sia a true. &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 0%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;pre style="margin: 0px;"&gt;        [&lt;span style="color: rgb(199, 199, 241);"&gt;Test&lt;/span&gt;]&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Access_To_The_Broker_Should_Be_Synchronized&lt;/span&gt;()&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(199, 199, 241);"&gt;Order&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;order1&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Order&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(199, 199, 241);"&gt;Order&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;order2&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Order&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(199, 199, 241);"&gt;SleepingBroker&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;broker&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;SleepingBroker&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(199, 199, 241);"&gt;OrderThread&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;thread1&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;OrderThread&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;broker&lt;/span&gt;, &lt;span style="color: rgb(254, 241, 169);"&gt;order1&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(199, 199, 241);"&gt;OrderThread&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;thread2&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;OrderThread&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;broker&lt;/span&gt;, &lt;span style="color: rgb(254, 241, 169);"&gt;order2&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;thread1&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Start&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;thread2&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Start&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(128, 128, 192);"&gt;while&lt;/span&gt;(!&lt;span style="color: rgb(254, 241, 169);"&gt;thread1&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;IsWaiting&lt;/span&gt; || !&lt;span style="color: rgb(254, 241, 169);"&gt;thread2&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;IsWaiting&lt;/span&gt;)&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;                &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Sleep&lt;/span&gt;(0);&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            }&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(199, 199, 241);"&gt;Assert&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;AreEqual&lt;/span&gt;(1, &lt;span style="color: rgb(254, 241, 169);"&gt;broker&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;CallingPlaceOrderCount&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt; &lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;broker&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;WakeUp&lt;/span&gt;();&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;     In questo modo abbiamo tolto l'elemento di casualità spiegato prima. Se non      modifichiamo il codice della classe OrderThread il test fallirà in modo      sistematico:&lt;/p&gt;
&lt;p style="font-family: 'Courier New',Courier,monospace;"&gt;         TestCase 'OrderThreadTests.Access_To_The_Broker_Should_Be_Synchronized' failed:          Equal assertion failed: [[1]]!=[[2]] &lt;/p&gt;
&lt;p&gt;  Aggiungiamo a questo punto la lock prima della chiamata di PlaceOrder nella classe OrderThread: &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 0%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;pre style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;private&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;PlaceOrder&lt;/span&gt;()&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            &lt;span style="color: rgb(128, 128, 192);"&gt;lock&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;_broker&lt;/span&gt;)&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            {&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;                &lt;span style="color: rgb(254, 241, 169);"&gt;_broker&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;PlaceOrder&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;_order&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;            }&lt;/pre&gt;
&lt;pre style="margin: 0px;"&gt;        }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;  Proviamo ora a lanciare nuovamente il test ed ecco finalmente la conferma che i due thread sono  sincronizzati: &lt;/p&gt;
&lt;p&gt;     &lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;Found 1 tests&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New',Courier,monospace;"&gt;[success] OrderThreadTests.Access_To_The_Broker_Should_Be_Synchronized     &lt;/span&gt; &lt;/p&gt;
&lt;p&gt;  Il motivo per cui il test passa è che in questo caso sono entrambi in waiting ma uno è all'interno del metodo     PlaceOrder mentre l'altro è fermo sulla lock. &lt;/p&gt;
&lt;p&gt;         L'esempio che ho fatto si può adattare facilmente anche ad altri scenari, in          quanto cambieranno gli attori, ma i concetti sono gli stessi.&lt;/p&gt;
&lt;p&gt;         Feedback?&lt;/p&gt;&lt;img src="http://blogs.ugidotnet.org/AntonioGanci/aggbug/93727.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Antonio Ganci</dc:creator>
            <guid>http://blogs.ugidotnet.org/AntonioGanci/archive/2008/08/17/93727.aspx</guid>
            <pubDate>Sun, 17 Aug 2008 10:46:26 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/AntonioGanci/comments/93727.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/AntonioGanci/archive/2008/08/17/93727.aspx#feedback</comments>
            <slash:comments>12</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/AntonioGanci/comments/commentRss/93727.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/AntonioGanci/services/trackbacks/93727.aspx</trackback:ping>
        </item>
        <item>
            <title>Usare il Test Driven Development per progettare applicazioni multithreading - Un esempio concreto</title>
            <link>http://blogs.ugidotnet.org/AntonioGanci/archive/2008/06/06/92951.aspx</link>
            <description>&lt;p&gt;   Il multithreading aggiunge complessità al design di un'applicazione.      Occorre prestare attenzione alle differenti problematiche legate alla       sincronizzazione, race condition, ecc.&lt;/p&gt;
&lt;p&gt;   In questi giorni sto realizzando un'applicazione in cui devo salvare dei messaggi di log    su un database e per non rallentare il chiamante la scrittura sul database avviene in modo   asincrono.  &lt;/p&gt;
&lt;p&gt;   Voglio realizzare questa funzionalità in       &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;TDD&lt;/a&gt; e riporto qui i passi che ho effettuato e la soluzione   trovata. Per ogni test scriverò prima il codice del test, introducendo classi e metodi necessari a       descrivere lo scenario che sto testando, successivamente scriverò       l'implementazione minima per far compilare il test ed infine modificherò il       codice per farlo passare.&lt;/p&gt;
&lt;p&gt;   Partiamo dal LogWriter:  &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 50%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;interface&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;ILogWriter&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Write&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt; }&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;     L'implementazione concreta di questa interfaccia salva sul database i dati contenuti      nella classe Log.  La classe che realizzerò in TDD deve chiamare in modo asincrono il metodo Write. &lt;/p&gt;
&lt;p&gt;     Non utilizzerò librerie di mocking e scriverò delle classi         &lt;a href="http://martinfowler.com/articles/mocksArentStubs.html"&gt;stub&lt;/a&gt; che      simuleranno i vari scenari da testare; questo renderà più semplice      la comprensione del codice. Il primo stub che useremo conta quante      volte viene chiamato il metodo Write e salva l'ultimo parametro con cui è stato      chiamato:&lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 50%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(128, 128, 192);"&gt;class&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;LogWriterForTest&lt;/span&gt; : &lt;span style="color: rgb(199, 199, 241);"&gt;ILogWriter&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;int&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;WriteCallCount&lt;/span&gt; = 0;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Log&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;null&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Write&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(254, 241, 169);"&gt;WriteCallCount&lt;/span&gt;++;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(254, 241, 169);"&gt;Log&lt;/span&gt; = &lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p style="margin: 0px;"&gt; &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;Il test controlla che quando viene accodato un log              viene chiamato il metodo Write:&lt;/p&gt;
&lt;p style="margin: 0px;"&gt; &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 50%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt; &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;[&lt;span style="color: rgb(199, 199, 241);"&gt;Test&lt;/span&gt;]&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;When_Enqueue_A_Log_The_LogWriter_Is_Invoked&lt;/span&gt;()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(199, 199, 241);"&gt;LogWriterForTest&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;LogWriterForTest&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(199, 199, 241);"&gt;LogThread&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;LogThread&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Enqueue&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(199, 199, 241);"&gt;Assert&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;AreEqual&lt;/span&gt;(1, &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;WriteCallCount&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(199, 199, 241);"&gt;Assert&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;AreEqual&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;, &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Log&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Per far passare il test non è necessario che il metodo Enqueue chiami il metodo          Write in modo asincrono, questo sarà compito del prossimo test. Questo concetto          è importante nel TDD e lo ribadisco: &lt;strong&gt;scrivere solo il codice indispensabile a          far passare il test anche se non contiene ancora le funzionalità che          effettivamente ci servono&lt;/strong&gt;. Questo ci consente di ridurre al minimo la          complessità del codice e dell'architettura e di arrivare alla soluzione in modo          incrementale.      &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Il primo passo da fare ora è quello di scrivere il codice minimo per compilare,          ma che non basta per far passare il test:&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;      &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 50%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;             &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;class&lt;/span&gt;             &lt;span style="color: rgb(199, 199, 241);"&gt;LogThread&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;             {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;             LogThread&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;ILogWriter&lt;/span&gt;             &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;              &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;             void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Enqueue&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;             }&lt;/p&gt;
&lt;/div&gt;
&lt;p style="margin: 0px;"&gt;      &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Se eseguo ora il test ottengo il messaggio: Expected: 1 But was: 0, in quanto          il metodo Write non è stato chiamato; aggiungiamo quindi la chiamata:&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 50%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;             &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;class&lt;/span&gt;             &lt;span style="color: rgb(199, 199, 241);"&gt;LogThread&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;             {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     &lt;span style="color: rgb(128, 128, 192);"&gt;private&lt;/span&gt;             &lt;span style="color: rgb(128, 128, 192);"&gt;readonly&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;             ILogWriter&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;_writer&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;              &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;             LogThread&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;ILogWriter&lt;/span&gt;             &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         &lt;span style="color: rgb(254, 241, 169);"&gt;_writer&lt;/span&gt; =             &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;              &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;             void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Enqueue&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         &lt;span style="color: rgb(254, 241, 169);"&gt;_writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Write&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;             }&lt;/p&gt;
&lt;/div&gt;
&lt;p style="margin: 0px;"&gt;      &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     Rilanciamo il test che passa con successo.&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     Passiamo al prossimo scenario: quando viene chiamata la Write il metodo Enqueue      la esegue in modo asincrono. Ci serve un meccanismo di sincronizzazione che ci      permetta di bloccare il metodo write e sbloccarlo successivamente con un      comando; creiamo a questo scopo un nuovo stub:&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;      &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 50%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;         &lt;span style="color: rgb(128, 128, 192);"&gt;class&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;             ManualResetLogWriter&lt;/span&gt; : &lt;span style="color: rgb(199, 199, 241);"&gt;ILogWriter&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;             {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;             int&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;WritingCount&lt;/span&gt; = 0;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;             Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Log&lt;/span&gt; =             &lt;span style="color: rgb(128, 128, 192);"&gt;null&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;             readonly&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;ManualResetEvent&lt;/span&gt;             &lt;span style="color: rgb(254, 241, 169);"&gt;ResetEvent&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;             new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;ManualResetEvent&lt;/span&gt;(&lt;span style="color: rgb(128, 128, 192);"&gt;false&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;             void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Write&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         &lt;span style="color: rgb(254, 241, 169);"&gt;WritingCount&lt;/span&gt;++;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         &lt;span style="color: rgb(254, 241, 169);"&gt;Log&lt;/span&gt; =             &lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         &lt;span style="color: rgb(254, 241, 169);"&gt;ResetEvent&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;WaitOne&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                &lt;span class="style1"&gt; WritingCount--;&lt;/span&gt; &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;             }&lt;/p&gt;
&lt;/div&gt;
&lt;p style="margin: 0px;"&gt;              &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;             Quando chiamiamo il metodo Write del ManualResetLogWriter l'esecuzione si blocca              sull'istruzione ResetEvent.WaitOne() fin quando da un altro thread non viene              chiamato il metodo Set della classe del framework .NET             &lt;a href="http://msdn.microsoft.com/it-it/library/system.threading.manualresetevent(VS.80).aspx"&gt;ManualResetEvent&lt;/a&gt;.&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;             La classe ManualResetLogWriter è utile nel prossimo test, in cui voglio              verificare che le chiamate al metodo Write avvengono in modo asincrono. Sarà              necessario modificare il metodo Enqueue affinché invochi il metodo write in un              theread dedicato, evitando così che l'esecuzione dell'Enqueue si blocchi              sull'istruzione WaitOne. Verifichiamolo:&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;              &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 50%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;             [&lt;span style="color: rgb(199, 199, 241);"&gt;Test&lt;/span&gt;]&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;             &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt;             &lt;span style="color: rgb(254, 241, 169);"&gt;The_Calls_To_The_Writer_Are_Asynchronous&lt;/span&gt;()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;             {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     &lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;             log&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt;             &lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     &lt;span style="color: rgb(199, 199, 241);"&gt;ManualResetLogWriter&lt;/span&gt;             &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt;             &lt;span style="color: rgb(199, 199, 241);"&gt;ManualResetLogWriter&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     &lt;span style="color: rgb(199, 199, 241);"&gt;LogThread&lt;/span&gt;             &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt;             &lt;span style="color: rgb(199, 199, 241);"&gt;LogThread&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Enqueue&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;while&lt;/span&gt;&lt;span style="color: rgb(254, 241, 169);"&gt;&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;WriteCallCount &lt;/span&gt;&lt;span style="color: rgb(254, 241, 169);"&gt;&lt;/span&gt;&lt;span style="color: rgb(254, 241, 169);"&gt;&lt;/span&gt;== 0&lt;span style="color: rgb(254, 241, 169);"&gt;&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;       &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Sleep&lt;/span&gt;(0);  &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    }&lt;br /&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt; &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     &lt;span style="color: rgb(199, 199, 241);"&gt;Assert&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;AreEqual&lt;/span&gt;(1, &lt;span style="color: rgb(254, 241, 169);"&gt;             writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;WriteCallCount&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;ResetEvent&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Set&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(199, 199, 241);"&gt;Assert&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;AreEqual&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;,             &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Log&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;             }&lt;/p&gt;
&lt;/div&gt;
&lt;p style="margin: 0px;"&gt;      &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;     Se eseguiamo il test con l'implementazione attuale della Enqueue vediamo che il      test si blocca sull'istruzione: thread.Enqueue(log). Modifichiamo il codice in modo da far passare questo      secondo test:&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 50%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;class&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;LogThread&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;private&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;readonly&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;ILogWriter&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;_writer&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt; &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;LogThread&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;ILogWriter&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(254, 241, 169);"&gt;_writer&lt;/span&gt; = &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt; &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;   &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Enqueue&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt;(&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;delegate&lt;/span&gt;()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;_writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Write&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        });&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Start&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Per maggiore compattezza del codice la chiamata _writer.Write(log) è stata fatta          all'interno di un         &lt;a href="http://msdn.microsoft.com/en-us/library/0yw3tz5k(VS.80).aspx"&gt;anonymous          method&lt;/a&gt;.&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;          Rieseguiamo il test che ora passa. &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                 Chiaramente non abbiamo ancora finito, perchè due          thread in contemporanea potrebbero eseguire la Write creando una         &lt;a href="http://it.wikipedia.org/wiki/Race_condition"&gt;Race Condition&lt;/a&gt; (o          corsa critica in italiano).&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Il prossimo test si occuperà proprio di testare che non ci sia una race          condition, cioè dobbiamo creare uno scenario in cui il test fallisce          nel caso in cui più thread eseguono contemporaneamente il metodo Write. Scriviamo il          test e poi commentiamolo un pezzo per volta:&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 50%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;[&lt;span style="color: rgb(199, 199, 241);"&gt;Test&lt;/span&gt;]&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Two_Logs_Enqueued_Are_Served_One_At_Time&lt;/span&gt;()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(199, 199, 241);"&gt;ManualResetLogWriter&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;ManualResetLogWriter&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(199, 199, 241);"&gt;LogThread&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;LogThread&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt; &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;log1&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Enqueue&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;log1&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;while&lt;/span&gt; (&lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;WritingCount&lt;/span&gt; &amp;lt; 1)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Sleep&lt;/span&gt;(0);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt; &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;log2&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Enqueue&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;log2&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;while&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt;.&lt;span class="style1"&gt;RunningThreadCount&lt;/span&gt; &amp;lt; 2)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Sleep&lt;/span&gt;(0);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt; &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(199, 199, 241);"&gt;Assert&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;AreEqual&lt;/span&gt;(1, &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;WritingCount&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt; &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;ResetEvent&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Set&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;while&lt;/span&gt; (&lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;WritingCount&lt;/span&gt; &amp;gt; 0)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Sleep&lt;/span&gt;(0);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Nel codice del test precedente ho usato più volte la chiamata Thread.Sleep(0),          il metodo Sleep interrompe il thread corrente per x millisecondi, se invece          viene passato zero si permette al thread corrente di essere sospeso; questo per          evitare di bloccare il PC con CPU al 100% nel caso in cui il test si blocchi in          uno dei cicli while.&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Il primo ciclo while attende che il primo thread sia fermo all'istruzione          ResetEvent.WaitOne del ManualResetLogWriter.&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Viene successivamente accodato il secondo log (variabile log2); ci serve quindi          un meccanismo che mi permetta di verificare che i thread in esecuzione siano          effettivamente due. Per questo scopo introduciamo, per ora solo nel codice del test, la          property RunningThreadCount ed aspettiamo che raggiunga il valore 2.&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Segue la Assert la quale assume che ci sia un solo thread in scrittura mentra          l'altro è in attesa (ricordo che lo scopo é quello di far si che il metodo          Write venga eseguito in mutua esclusione).&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Il test termina sbloccando la Write tramite l'istruzione writer.ResetEvent.Set()          ed infine attendiamo che entrambi i thread siano terminati.&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Aggiungiamo la property RunningThreadCount alla classe LogThread:&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 50%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;class&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;LogThread&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;private&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;readonly&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;ILogWriter&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;_writer&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;private&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;int&lt;/span&gt;     &lt;span style="color: rgb(254, 241, 169);"&gt;_&lt;span class="style1"&gt;runningThreadCount&lt;/span&gt;&lt;/span&gt; = 0;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt; &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;LogThread&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;ILogWriter&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(254, 241, 169);"&gt;_writer&lt;/span&gt; = &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt; &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;int&lt;/span&gt;     &lt;span class="style1"&gt;RunningThreadCount&lt;/span&gt; { &lt;span style="color: rgb(128, 128, 192);"&gt;get&lt;/span&gt; { &lt;span style="color: rgb(128, 128, 192);"&gt;return&lt;/span&gt;     &lt;span style="color: rgb(254, 241, 169);"&gt;_&lt;/span&gt;&lt;span class="style1"&gt;runningThreadCount&lt;/span&gt;; } }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt; &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Enqueue&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt;(&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;delegate&lt;/span&gt;()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                 &lt;span class="style1"&gt;_runningThreadCount&lt;/span&gt;++;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;_writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Write&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                 &lt;span class="style1"&gt;_runningThreadCount&lt;/span&gt;--;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        });&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Start&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Eseguendo il test si nota che la assert fallisce in quanto tutte e due i          thread eseguono il metodo Write. Dobbiamo ora inserire un meccanismo di          sincronizzazione, useremo l'istruzione lock:&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 50%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Enqueue&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt;(&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;delegate&lt;/span&gt;()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                 &lt;span class="style1"&gt;_runningThreadCount&lt;/span&gt;++;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;            &lt;span style="color: rgb(128, 128, 192);"&gt;lock&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;_writer&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;            {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                &lt;span style="color: rgb(254, 241, 169);"&gt;_writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Write&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;            }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                 &lt;span class="style1"&gt;_runningThreadCount&lt;/span&gt;--;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        });&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Start&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    }&lt;/p&gt;
&lt;/div&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Ora rilanciamo il test il quale passerà con successo.&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         &lt;em&gt;A qualcuno potrà sembrare strano che sia stata aggiunta la property          RunningThreadCount, in quanto viene usata solo dal test. Questa pratica però è          piuttosto comune nel TDD e capita spesso che queste funzionalità, aggiunte solo          per poter testare la classe, tornino utili in seguito anche nel codice di          produzione.&lt;/em&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Se il metodo Write sollevasse un'eccezione la property RunningThreadCount non verrebbe          decrementata. Creiamo un nuovo stub il quale sollevi un eccezione:&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 50%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(128, 128, 192);"&gt;class &lt;/span&gt;&lt;span style="color: rgb(199, 199, 241);"&gt;ExceptionRaiseLogWriter&lt;/span&gt; : &lt;span style="color: rgb(199, 199, 241);"&gt;ILogWriter&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;bool&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;IsWriting&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;false&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Write&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(254, 241, 169);"&gt;IsWriting&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;true&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;throw&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;ArgumentException&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p style="margin: 0px;"&gt; &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;Ed il test che verifichi che effettivamente venga              descrementata la property:&lt;/p&gt;
&lt;p style="margin: 0px;"&gt; &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 50%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;When_The_Writer_Throws_An_Exception_The_QueueLength_Is_Decreased&lt;/span&gt;()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(199, 199, 241);"&gt;ExceptionRaiseLogWriter&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;ExceptionRaiseLogWriter&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(199, 199, 241);"&gt;LogThread&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;LogThread&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Enqueue&lt;/span&gt;(&lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt;());&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;while&lt;/span&gt;(!&lt;span style="color: rgb(254, 241, 169);"&gt;writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;IsWriting&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Sleep&lt;/span&gt;(0);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    &lt;span style="color: rgb(128, 128, 192);"&gt;while&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt;.&lt;span class="style1"&gt;RunningThreadCount&lt;/span&gt; &amp;gt; 0)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Sleep&lt;/span&gt;(0);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;    }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Proviamo ad eseguirlo: il test si blocca all'interno          dell'ultimo while.&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Per far passare il test aggiungiamo un try / finally al metodo Enqueue della          classe LogThread:&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;div style="background: rgb(24, 24, 24) none repeat scroll 0% 50%; font-family: Consolas; font-size: 12pt; color: rgb(224, 224, 224); -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;        &lt;span style="color: rgb(128, 128, 192);"&gt;public&lt;/span&gt; &lt;span style="color: rgb(128, 128, 192);"&gt;void&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;Enqueue&lt;/span&gt;(&lt;span style="color: rgb(199, 199, 241);"&gt;Log&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;            &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt; &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt; = &lt;span style="color: rgb(128, 128, 192);"&gt;new&lt;/span&gt; &lt;span style="color: rgb(199, 199, 241);"&gt;Thread&lt;/span&gt;(&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;            &lt;span style="color: rgb(128, 128, 192);"&gt;delegate&lt;/span&gt;()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;            {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                      &lt;span class="style1"&gt;_runningThreadCount&lt;/span&gt;++;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                &lt;span style="color: rgb(128, 128, 192);"&gt;try&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                    &lt;span style="color: rgb(128, 128, 192);"&gt;lock&lt;/span&gt; (&lt;span style="color: rgb(254, 241, 169);"&gt;_writer&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                    {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                        &lt;span style="color: rgb(254, 241, 169);"&gt;_writer&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Write&lt;/span&gt;(&lt;span style="color: rgb(254, 241, 169);"&gt;log&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                    }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                &lt;span style="color: rgb(128, 128, 192);"&gt;finally&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                          &lt;span class="style1"&gt;_runningThreadCount&lt;/span&gt;--;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;                }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;            });&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;            &lt;span style="color: rgb(254, 241, 169);"&gt;thread&lt;/span&gt;.&lt;span style="color: rgb(254, 241, 169);"&gt;Start&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;        }&lt;/p&gt;
&lt;/div&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         A questo punto anche questo test è a posto. &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Mancano ancora altre cose, come la          gestione delle eccezioni, ecc. ma credo che il modo di procedere ora sia chiaro. &lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Un altro test interessante da sviluppare è quello relativo alla gestione delle          richieste secondo una politica &lt;a href="http://it.wikipedia.org/wiki/FIFO"&gt;FIFO&lt;/a&gt;          mediante una coda, vale a dire che la          prima richiesta accodata sia effettivamente la prima ad essere eseguita, mentre          nell'implentazione derivata dai test finora scritti l'ordine di scrittura          dipende da quale thread viene sbloccato prima e quindi non è deterministico.&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;         Se avete suggerimenti, consigli o segnalazioni di errori scrivetemeli nei          commenti.&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;          &lt;/p&gt;&lt;img src="http://blogs.ugidotnet.org/AntonioGanci/aggbug/92951.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Antonio Ganci</dc:creator>
            <guid>http://blogs.ugidotnet.org/AntonioGanci/archive/2008/06/06/92951.aspx</guid>
            <pubDate>Fri, 06 Jun 2008 11:29:09 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/AntonioGanci/comments/92951.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/AntonioGanci/archive/2008/06/06/92951.aspx#feedback</comments>
            <slash:comments>14</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/AntonioGanci/comments/commentRss/92951.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/AntonioGanci/services/trackbacks/92951.aspx</trackback:ping>
        </item>
        <item>
            <title>Un esempio concreto di sviluppo di una GUI in TDD: La gestione dei pulsanti OK e Cancel (Parte prima)</title>
            <link>http://blogs.ugidotnet.org/AntonioGanci/archive/2007/03/07/MVPPartIV.aspx</link>
            <description>Continua l'implentazione del Model View Presenter utilizzando il TDD (Test Driven Development), in questi post affronteremo la gestione del click sui pulsanti Ok e Cancel.&lt;img src="http://blogs.ugidotnet.org/AntonioGanci/aggbug/72467.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Antonio Ganci</dc:creator>
            <guid>http://blogs.ugidotnet.org/AntonioGanci/archive/2007/03/07/MVPPartIV.aspx</guid>
            <pubDate>Wed, 07 Mar 2007 08:17:00 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/AntonioGanci/comments/72467.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/AntonioGanci/archive/2007/03/07/MVPPartIV.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/AntonioGanci/comments/commentRss/72467.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/AntonioGanci/services/trackbacks/72467.aspx</trackback:ping>
        </item>
        <item>
            <title>Un esempio concreto di sviluppo di una GUI in TDD (Terza ed ultima parte)</title>
            <link>http://blogs.ugidotnet.org/AntonioGanci/archive/2007/03/04/MVPPart3.aspx</link>
            <description>Ecco la terza ed ultima parte di un caso reale di implementazione di MVP in .NET tramite il TDD&lt;img src="http://blogs.ugidotnet.org/AntonioGanci/aggbug/72290.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Antonio Ganci</dc:creator>
            <guid>http://blogs.ugidotnet.org/AntonioGanci/archive/2007/03/04/MVPPart3.aspx</guid>
            <pubDate>Sun, 04 Mar 2007 14:35:00 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/AntonioGanci/comments/72290.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/AntonioGanci/archive/2007/03/04/MVPPart3.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/AntonioGanci/comments/commentRss/72290.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/AntonioGanci/services/trackbacks/72290.aspx</trackback:ping>
        </item>
        <item>
            <title>Un esempio concreto di sviluppo di una GUI in TDD (Seconda parte)</title>
            <link>http://blogs.ugidotnet.org/AntonioGanci/archive/2007/03/03/MVPPart2.aspx</link>
            <description>La continuazione del post su una implementazione concreta del model view presenter tramite la tecnica del TDD&lt;img src="http://blogs.ugidotnet.org/AntonioGanci/aggbug/72253.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Antonio Ganci</dc:creator>
            <guid>http://blogs.ugidotnet.org/AntonioGanci/archive/2007/03/03/MVPPart2.aspx</guid>
            <pubDate>Sat, 03 Mar 2007 10:33:00 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/AntonioGanci/comments/72253.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/AntonioGanci/archive/2007/03/03/MVPPart2.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/AntonioGanci/comments/commentRss/72253.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/AntonioGanci/services/trackbacks/72253.aspx</trackback:ping>
        </item>
        <item>
            <title>Un esempio concreto di sviluppo di una GUI in TDD</title>
            <link>http://blogs.ugidotnet.org/AntonioGanci/archive/2007/03/02/72175.aspx</link>
            <description>&lt;P&gt;Per comprendere meglio i concetti esposti in questo post consiglio prima la visione del seguente &lt;A href="http://www.testing.com/cgi-bin/blog/2007/01/05#wireframe2"&gt;webcast&lt;/A&gt;, la lettura degli articoli che avevo segnalato nel precente &lt;A href="http://blogs.ugidotnet.org/antonioganci/archive/2007/02/03/69686.aspx"&gt;post&lt;/A&gt; ed infine consiglio l'ascolto dell'ottimo &lt;A href="http://www.guisa.org/files/folders/architecture_days_2006/entry246.aspx"&gt;webcast&lt;/A&gt; di &lt;A href="http://blogs.ugidotnet.org/corrado"&gt;Corrado Cavalli&lt;/A&gt; scaricabile da &lt;A href="http://www.guisa.org/"&gt;guisa&lt;/A&gt;. &lt;/P&gt;
&lt;P&gt;Per prima cosa vediamo uno screen shot della user interface che vogliamo sviluppare in TDD: &lt;/P&gt;
&lt;P&gt;&lt;IMG alt="form screen shot" src="/images/blogs_ugidotnet_org/antonioganci/1890/o_ScreenShot001.jpg"&gt; &lt;/P&gt;
&lt;P&gt;La form precedente serve per selezionare un titolo del mercato azionario (nel dominio utente chiamato symbol), permettendo di scegliere se aggiungerlo ad uno dei chart correntemente visualizzati o crearne uno nuovo. In una finestra si possono visualizzare pi&amp;#249; chart ognuno contenente uno o pi&amp;#249; titoli.&lt;/P&gt;
&lt;P&gt;A questo punto entrano in gioco tre attori: il model, il presenter e la view. Iniziamo vedendo lo schema delle dipendenze tra le tre classi: &lt;/P&gt;
&lt;P&gt;&lt;IMG alt=mvp src="/images/blogs_ugidotnet_org/antonioganci/1890/o_MVP.jpg"&gt; &lt;/P&gt;
&lt;P&gt;Il presenter contiene un riferimento al model e alla view, mentre il model e la view comunicano con il presenter tramite eventi. &lt;/P&gt;
&lt;P&gt;La view &amp;#232; la nostra form ed in generale la user interface, il model usa gli oggetti di business o di dominio e non sa nulla di user interface, mentre il presenter &amp;#232; la colla tra i due mondi cio&amp;#232; trasforma le informazioni degli oggetti di dominio in una forma visualizzabile facilmente dalla user interface. &lt;/P&gt;
&lt;P&gt;Iniziamo a sviluppare in TDD il presenter; per poterlo testare agevolmente facciamo in modo che dipendenda da due interfacce una che verr&amp;#224; implementata dal model e l'altra dalla view. &lt;/P&gt;
&lt;P&gt;Per non scrivermi a mano degli stub user&amp;#242; il framework &lt;A href="http://www.ayende.com/projects/rhino-mocks.aspx"&gt;Rhino Mocks&lt;/A&gt; (maggiori informazioni nel post di &lt;A href="http://blogs.ugidotnet.org/papo/"&gt;papo&lt;/A&gt; e nel mio precedente). &lt;/P&gt;
&lt;P&gt;Il primo test che scriveremo riguarda il riempimento della combobox con i nomi dei symboli. Questa informazione verr&amp;#224; fornita dal model tramite un evento, vediamo il sequence diagram: &lt;/P&gt;
&lt;P&gt;&lt;IMG alt="SymbolNameListChanged Sequence Diagram" src="/images/blogs_ugidotnet_org/antonioganci/1890/o_SymbolNamesChangedSequenceDiagram.jpg"&gt; &lt;/P&gt;
&lt;P&gt;In pratica quando nel model viene chiamato il metodo SetSymbolNameList viene segnalato l'evento SymbolNameListChanged a cui il presenter &amp;#232; sottoscritto; e nell'event handler viene chiamata la vista in modo che venga riempita la combobox. &lt;/P&gt;
&lt;P&gt;Iniziamo ad impostare la classe di test SelectSymbolPresenterTests: &lt;/P&gt;
&lt;DIV style="FONT-SIZE: 10pt; BACKGROUND: #181818; COLOR: #e0e0e0; FONT-FAMILY: Courier New"&gt;
&lt;P style="MARGIN: 0px"&gt;&lt;SPAN style="COLOR: #8080c0"&gt;using&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;MbUnit&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;Framework&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&lt;SPAN style="COLOR: #8080c0"&gt;using&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;Rhino&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;Mocks&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&lt;SPAN style="COLOR: #8080c0"&gt;using&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;Rhino&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;Mocks&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;Interfaces&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt; &lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&lt;SPAN style="COLOR: #8080c0"&gt;namespace&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;PresenterFirstExample&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;{&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;    [&lt;SPAN style="COLOR: #c7c7f1"&gt;TestFixture&lt;/SPAN&gt;]&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;    &lt;SPAN style="COLOR: #8080c0"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #8080c0"&gt;class&lt;/SPAN&gt; &lt;SPAN style="COLOR: #c7c7f1"&gt;SelectSymbolPresenterTests&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;    {&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        &lt;SPAN style="COLOR: #8080c0"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #c7c7f1"&gt;MockRepository&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;_mocks&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        &lt;SPAN style="COLOR: #8080c0"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #c7c7f1"&gt;ISelectSymbolModel&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;_model&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        &lt;SPAN style="COLOR: #8080c0"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #c7c7f1"&gt;ISelectSymbolView&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;_view&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt; &lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        [&lt;SPAN style="COLOR: #c7c7f1"&gt;SetUp&lt;/SPAN&gt;]&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        &lt;SPAN style="COLOR: #8080c0"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #8080c0"&gt;void&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;SetUp&lt;/SPAN&gt;()&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        {&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;            &lt;SPAN style="COLOR: #fef1a9"&gt;_mocks&lt;/SPAN&gt; = &lt;SPAN style="COLOR: #8080c0"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #c7c7f1"&gt;MockRepository&lt;/SPAN&gt;();&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;            &lt;SPAN style="COLOR: #fef1a9"&gt;_model&lt;/SPAN&gt; = &lt;SPAN style="COLOR: #fef1a9"&gt;_mocks&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;CreateMock&lt;/SPAN&gt;&lt;&lt;SPAN style="COLOR: #c7c7f1"&gt;ISelectSymbolModel&lt;/SPAN&gt;&gt;();&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;            &lt;SPAN style="COLOR: #fef1a9"&gt;_view&lt;/SPAN&gt; = &lt;SPAN style="COLOR: #fef1a9"&gt;_mocks&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;CreateMock&lt;/SPAN&gt;&lt;&lt;SPAN style="COLOR: #c7c7f1"&gt;ISelectSymbolView&lt;/SPAN&gt;&gt;();&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        }    &lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt; &lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        [&lt;SPAN style="COLOR: #c7c7f1"&gt;TearDown&lt;/SPAN&gt;]&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        &lt;SPAN style="COLOR: #8080c0"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #8080c0"&gt;void&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;TearDown&lt;/SPAN&gt;()&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        {&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;            &lt;SPAN style="COLOR: #fef1a9"&gt;_mocks&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;VerifyAll&lt;/SPAN&gt;();&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        }&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt; &lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        [&lt;SPAN style="COLOR: #c7c7f1"&gt;Test&lt;/SPAN&gt;]&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        &lt;SPAN style="COLOR: #8080c0"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #8080c0"&gt;void&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;WhenTheModelFiresTheSymbolListChangedThePresenterCallsTheViewToFillTheList&lt;/SPAN&gt;()&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        {&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        }&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;    }&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;}&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;Il framework usato &amp;#232; MbUnit, ma la conversione ad altri framework (NUnit, Microsoft Quality Tools) non &amp;#232; un grosso problema. &lt;/P&gt;
&lt;P&gt;Il presenter dipende da due interfacce (ISelectSymbolModel e ISelectSymbolView) quindi nel momento in cui scriviamo il test non esiste ancora la form e potrebbe anche non esistere ancora il business layer. &lt;/P&gt;
&lt;P&gt;Questo porta dei grossi vantaggi perch&amp;#232; progettando il sistema come se questi due attori non esistessero rende semplice la loro modifica o sostituzione, es: se anzich&amp;#232; una form la view dovesse cambiare in una pagina web l'unica cosa da cambiare &amp;#232; l'implementazione concreta dell'interfaccia ISelectSymbolView, stesso discorso se anzich&amp;#232; una combobox dovessimo usare un DataGrid. &lt;/P&gt;
&lt;P&gt;Il nome del test &amp;#232; un p&amp;#242; lungo ma &amp;#232; importante dargli un nome che indichi chiaramente cosa vogliamo testare piuttosto che quello che fa il test. Mi spiego meglio: se il test che abbiamo scritto fallisce leggendo il nome del test si deve essere in grado di capire senza guardare il codice al suo interno cosa del nostro sistema non funziona pi&amp;#249; correttamente. &lt;/P&gt;
&lt;P&gt;La prima cosa che vogliamo testare &amp;#232; che il presenter si sottoscriva all'evento del model, per ottenere questo risultato aggiungiamo al metodo SetUp il seguente codice: &lt;/P&gt;
&lt;DIV style="FONT-SIZE: 10pt; BACKGROUND: #181818; COLOR: #e0e0e0; FONT-FAMILY: Courier New"&gt;
&lt;P style="MARGIN: 0px"&gt;&lt;SPAN style="COLOR: gray"&gt;    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #fef1a9"&gt;_model&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;SymbolNameListChanged&lt;/SPAN&gt; += &lt;SPAN style="COLOR: #8080c0"&gt;null&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&lt;SPAN style="COLOR: gray"&gt;    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #fef1a9"&gt;_symbolNameListChangedRaiser&lt;/SPAN&gt; = &lt;SPAN style="COLOR: #c7c7f1"&gt;LastCall&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;Repeat&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;Once&lt;/SPAN&gt;().&lt;SPAN style="COLOR: #fef1a9"&gt;IgnoreArguments&lt;/SPAN&gt;().&lt;SPAN style="COLOR: #fef1a9"&gt;GetEventRaiser&lt;/SPAN&gt;();&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;Le due righe di codice precedenti possono sembrare un p&amp;#242; strane, ma &amp;#232; il modo con cui si controlla con rhino mocks se ci si &amp;#232; sottoscritti ad un evento; la variabile _symbolNameListChangedRaiser &amp;#232; di tipo IEventRaiser e verr&amp;#224; usata nel metodo di test per simulare l'evento. &lt;/P&gt;
&lt;P&gt;Per far compilare il codice precedente creiamo il model: &lt;/P&gt;
&lt;DIV style="FONT-SIZE: 10pt; BACKGROUND: #181818; COLOR: #e0e0e0; FONT-FAMILY: Courier New"&gt;
&lt;P style="MARGIN: 0px"&gt;&lt;SPAN style="COLOR: #8080c0"&gt;using&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;System&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt; &lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&lt;SPAN style="COLOR: #8080c0"&gt;namespace&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;PresenterFirstExample&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;{&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;    &lt;SPAN style="COLOR: #8080c0"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #8080c0"&gt;interface&lt;/SPAN&gt; &lt;SPAN style="COLOR: #c7c7f1"&gt;ISelectSymbolModel&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;    {&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        &lt;SPAN style="COLOR: #8080c0"&gt;event&lt;/SPAN&gt; &lt;SPAN style="COLOR: #c7c7f1"&gt;EventHandler&lt;/SPAN&gt;&lt;&lt;SPAN style="COLOR: #c7c7f1"&gt;StringListEventArgs&lt;/SPAN&gt;&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;SymbolNameListChanged&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;    }&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;}&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;La classe StringListEventArgs: &lt;/P&gt;
&lt;DIV style="FONT-SIZE: 10pt; BACKGROUND: #181818; COLOR: #e0e0e0; FONT-FAMILY: Courier New"&gt;
&lt;P style="MARGIN: 0px"&gt;&lt;SPAN style="COLOR: #8080c0"&gt;using&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;System&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt; &lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&lt;SPAN style="COLOR: #8080c0"&gt;namespace&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;PresenterFirstExample&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;{&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;    &lt;SPAN style="COLOR: #8080c0"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #8080c0"&gt;class&lt;/SPAN&gt; &lt;SPAN style="COLOR: #c7c7f1"&gt;StringListEventArgs&lt;/SPAN&gt; : &lt;SPAN style="COLOR: #c7c7f1"&gt;EventArgs&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;    {&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        &lt;SPAN style="COLOR: #8080c0"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #8080c0"&gt;readonly&lt;/SPAN&gt; &lt;SPAN style="COLOR: #8080c0"&gt;string&lt;/SPAN&gt;[] &lt;SPAN style="COLOR: #fef1a9"&gt;_strings&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt; &lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        &lt;SPAN style="COLOR: #8080c0"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;StringListEventArgs&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #8080c0"&gt;string&lt;/SPAN&gt;[] &lt;SPAN style="COLOR: #fef1a9"&gt;_strings&lt;/SPAN&gt;)&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        {&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;            &lt;SPAN style="COLOR: #8080c0"&gt;this&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;_strings&lt;/SPAN&gt; = &lt;SPAN style="COLOR: #fef1a9"&gt;_strings&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        }&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt; &lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        &lt;SPAN style="COLOR: #8080c0"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #8080c0"&gt;string&lt;/SPAN&gt;[] &lt;SPAN style="COLOR: #fef1a9"&gt;StringList&lt;/SPAN&gt; { &lt;SPAN style="COLOR: #8080c0"&gt;get&lt;/SPAN&gt; { &lt;SPAN style="COLOR: #8080c0"&gt;return&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;_strings&lt;/SPAN&gt;; } }&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;    }&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;}&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;A questo punto finalmente scriviamo il nostro test: &lt;/P&gt;
&lt;DIV style="FONT-SIZE: 10pt; BACKGROUND: #181818; COLOR: #e0e0e0; FONT-FAMILY: Courier New"&gt;
&lt;P style="MARGIN: 0px"&gt;        [&lt;SPAN style="COLOR: #c7c7f1"&gt;Test&lt;/SPAN&gt;]&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        &lt;SPAN style="COLOR: #8080c0"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #8080c0"&gt;void&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;WhenTheModelFiresTheSymbolListChangedThePresenterCallsTheViewToFillTheList&lt;/SPAN&gt;()&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        {&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;            &lt;SPAN style="COLOR: #8080c0"&gt;string&lt;/SPAN&gt;[] &lt;SPAN style="COLOR: #fef1a9"&gt;symbolNames&lt;/SPAN&gt; = &lt;SPAN style="COLOR: #8080c0"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #8080c0"&gt;string&lt;/SPAN&gt;[] {&lt;SPAN style="COLOR: #60ff60"&gt;"ENEL-MIL"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #60ff60"&gt;"ENI-MIL"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #60ff60"&gt;"G-MIL"&lt;/SPAN&gt;};&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt; &lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;            &lt;SPAN style="COLOR: #fef1a9"&gt;_view&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;FillSymbolNameList&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #fef1a9"&gt;symbolNames&lt;/SPAN&gt;);&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;            &lt;SPAN style="COLOR: #c7c7f1"&gt;LastCall&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;Repeat&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;Once&lt;/SPAN&gt;();&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;            &lt;SPAN style="COLOR: #fef1a9"&gt;_mocks&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;ReplayAll&lt;/SPAN&gt;();&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt; &lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;            &lt;SPAN style="COLOR: #8080c0"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #c7c7f1"&gt;SelectSymbolPresenter&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #fef1a9"&gt;_model&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #fef1a9"&gt;_view&lt;/SPAN&gt;);&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;            &lt;SPAN style="COLOR: #fef1a9"&gt;_symbolNameListChangedRaiser&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;Raise&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #fef1a9"&gt;_model&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #8080c0"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #c7c7f1"&gt;StringListEventArgs&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #fef1a9"&gt;symbolNames&lt;/SPAN&gt;));&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        }&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;Per chi non &amp;#232; abituato ad usare Rhino Mocks pu&amp;#242; sembrare un p&amp;#242; ostico, ma &amp;#232; pi&amp;#249; semplice di quello che sembra. La prima riga crea la variabile symbolNames che contiene l'elenco dei symbol che arriveranno come dati dall'evento (vedi l'ultima riga del test), le due righe successive significano che ci aspettiamo che il presenter chiami la vista passando come argomento l'elenco dei nomi creato prima. La chiamata ReplayAll indica a Rhino Mocks che da quel punto in avanti si &amp;#232; in &lt;I&gt;Play Mode&lt;/I&gt; cio&amp;#232; che abbiamo finito il codice in cui dichiaramo che cosa ci aspettiamo che venga chiamato dei nostri oggetti mock.&lt;/P&gt;
&lt;P&gt;Se lanciamo adesso il test vediamo che non passa per il seguente motivo: &lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;TestCase 'SelectSymbolPresenterTests.SetUp.WhenTheModelFiresTheSymbolListChangedThePresenterCallsTheViewToFillTheList.TearDown' failed: ISelectSymbolModel.add_SymbolNameListChanged(any); Expected #1, Actual #0. &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Per far passare il test scriviamo la classe presenter come segue: &lt;/P&gt;
&lt;DIV style="FONT-SIZE: 10pt; BACKGROUND: #181818; COLOR: #e0e0e0; FONT-FAMILY: Courier New"&gt;
&lt;P style="MARGIN: 0px"&gt;&lt;SPAN style="COLOR: #8080c0"&gt;using&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;System&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt; &lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&lt;SPAN style="COLOR: #8080c0"&gt;namespace&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;PresenterFirstExample&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;{&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;    &lt;SPAN style="COLOR: #8080c0"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #8080c0"&gt;class&lt;/SPAN&gt; &lt;SPAN style="COLOR: #c7c7f1"&gt;SelectSymbolPresenter&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;    {&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        &lt;SPAN style="COLOR: #8080c0"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #8080c0"&gt;readonly&lt;/SPAN&gt; &lt;SPAN style="COLOR: #c7c7f1"&gt;ISelectSymbolModel&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;_model&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        &lt;SPAN style="COLOR: #8080c0"&gt;private&lt;/SPAN&gt; &lt;SPAN style="COLOR: #8080c0"&gt;readonly&lt;/SPAN&gt; &lt;SPAN style="COLOR: #c7c7f1"&gt;ISelectSymbolView&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;_view&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt; &lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        &lt;SPAN style="COLOR: #8080c0"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;SelectSymbolPresenter&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #c7c7f1"&gt;ISelectSymbolModel&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;model&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #c7c7f1"&gt;ISelectSymbolView&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;view&lt;/SPAN&gt;)&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        {&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;            &lt;SPAN style="COLOR: #fef1a9"&gt;_model&lt;/SPAN&gt; = &lt;SPAN style="COLOR: #fef1a9"&gt;model&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;            &lt;SPAN style="COLOR: #fef1a9"&gt;_view&lt;/SPAN&gt; = &lt;SPAN style="COLOR: #fef1a9"&gt;view&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;            &lt;SPAN style="COLOR: #fef1a9"&gt;_model&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;SymbolNameListChanged&lt;/SPAN&gt; += &lt;SPAN style="COLOR: #8080c0"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: #c7c7f1"&gt;EventHandler&lt;/SPAN&gt;&lt;&lt;SPAN style="COLOR: #c7c7f1"&gt;StringListEventArgs&lt;/SPAN&gt;&gt;(&lt;SPAN style="COLOR: #fef1a9"&gt;Model_SymbolNameListChanged&lt;/SPAN&gt;);&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        }&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt; &lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        &lt;SPAN style="COLOR: #8080c0"&gt;void&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;Model_SymbolNameListChanged&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #8080c0"&gt;object&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;sender&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #c7c7f1"&gt;StringListEventArgs&lt;/SPAN&gt; &lt;SPAN style="COLOR: #fef1a9"&gt;e&lt;/SPAN&gt;)&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        {&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;            &lt;SPAN style="COLOR: #fef1a9"&gt;_view&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;FillSymbolNameList&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #fef1a9"&gt;e&lt;/SPAN&gt;.&lt;SPAN style="COLOR: #fef1a9"&gt;StringList&lt;/SPAN&gt;);&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;        }&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;    }&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;}&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;A questo punto possiamo iniare a scrivere altre funzionalit&amp;#224;. &lt;/P&gt;
&lt;P&gt;Continua... &lt;/P&gt;&lt;img src="http://blogs.ugidotnet.org/AntonioGanci/aggbug/72175.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Antonio Ganci</dc:creator>
            <guid>http://blogs.ugidotnet.org/AntonioGanci/archive/2007/03/02/72175.aspx</guid>
            <pubDate>Fri, 02 Mar 2007 10:12:00 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/AntonioGanci/comments/72175.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/AntonioGanci/archive/2007/03/02/72175.aspx#feedback</comments>
            <slash:comments>5</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/AntonioGanci/comments/commentRss/72175.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/AntonioGanci/services/trackbacks/72175.aspx</trackback:ping>
        </item>
        <item>
            <title>Usare Rhino Mocks per sviluppare in TDD</title>
            <link>http://blogs.ugidotnet.org/AntonioGanci/archive/2007/01/03/64722.aspx</link>
            <description>&lt;P&gt;Per chi sviluppa in &lt;A href="http://en.wikipedia.org/wiki/Test_driven_development"&gt;TDD&lt;/A&gt; utilizzare i &lt;A href="http://en.wikipedia.org/wiki/Mock_Object"&gt;Mock Objects&lt;/A&gt; &amp;#232; una delle basi dell'&lt;A href="http://codebetter.com/blogs/jeremy.miller/pages/129544.aspx"&gt;interaction based testing&lt;/A&gt;. &lt;/P&gt;
&lt;P&gt;Per facilitare questo compito sono disponibili alcune librerie in rete. Fino all'anno scorso ho utilizzato &lt;A href="http://www.typemock.com/"&gt;TypeMock&lt;/A&gt;, ora con l'anno nuovo ho voluto provare un'altra libreria ed ho scaricato &lt;A href="http://www.ayende.com/projects/rhino-mocks.aspx"&gt;Rhino Mocks&lt;/A&gt;. &lt;/P&gt;
&lt;P&gt;Le prime impressioni sono positive in quanto l'object model mi sembra pi&amp;#249; chiaro rispetto a TypeMock. Ho avuto qualche difficolt&amp;#224; con in metodi che non ritornano valori (void).&lt;/P&gt;
&lt;P&gt;Vediamo un esempio pratico:&lt;/P&gt;
&lt;P&gt;Supponiamo di voler creare un mock object della seguente interfaccia: &lt;/P&gt;
&lt;DIV style="FONT-SIZE: 10pt; BACKGROUND: white; COLOR: black; FONT-FAMILY: Courier New"&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;interface&lt;/SPAN&gt; &lt;SPAN style="COLOR: teal"&gt;ICustomerList&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; Add(&lt;SPAN style="COLOR: teal"&gt;Customer&lt;/SPAN&gt; customer);&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; Count { &lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt;;}&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;Il codice del test sar&amp;#224;: &lt;/P&gt;
&lt;DIV style="FONT-SIZE: 10pt; BACKGROUND: white; COLOR: black; FONT-FAMILY: Courier New"&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;SPAN style="COLOR: teal"&gt;Test&lt;/SPAN&gt;]&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; RhinoMocksSampleTest()&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: teal"&gt;MockRepository&lt;/SPAN&gt; mockRepository = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: teal"&gt;MockRepository&lt;/SPAN&gt;();&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: teal"&gt;ICustomerList&lt;/SPAN&gt; customers = mockRepository.CreateMock&amp;lt;&lt;SPAN style="COLOR: teal"&gt;ICustomerList&lt;/SPAN&gt;&amp;gt;();&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: teal"&gt;Expect&lt;/SPAN&gt;.Call(customers.Count).Return(10);&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; mockRepository.ReplayAll();&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: teal"&gt;Assert&lt;/SPAN&gt;.AreEqual(10, customers.Count);&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; mockRepository.VerifyAll();&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;Con la chiamata Expect.Call indichiamo che la prossima volta che viene letto il valore della property Count dell'interfaccia ICustomerList viene ritornato il valore 10. Un p&amp;#242; pi&amp;#249; complicato &amp;#232; invece il mock del metodo Add perch&amp;#232; non ritorna nessun valore e quindi non si pu&amp;#242; usare ExpectCall: &lt;/P&gt;
&lt;DIV style="FONT-SIZE: 10pt; BACKGROUND: white; COLOR: black; FONT-FAMILY: Courier New"&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;SPAN style="COLOR: teal"&gt;Test&lt;/SPAN&gt;]&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt; RhinoMocksSampleTest()&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: teal"&gt;MockRepository&lt;/SPAN&gt; mockRepository = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: teal"&gt;MockRepository&lt;/SPAN&gt;();&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: teal"&gt;ICustomerList&lt;/SPAN&gt; customers = mockRepository.CreateMock&amp;lt;&lt;SPAN style="COLOR: teal"&gt;ICustomerList&lt;/SPAN&gt;&amp;gt;();&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; customers.Add(&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: teal"&gt;Customer&lt;/SPAN&gt;());&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: teal"&gt;LastCall&lt;/SPAN&gt;.Repeat.Once().IgnoreArguments();&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; mockRepository.ReplayAll();&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; customers.Add(&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: teal"&gt;Customer&lt;/SPAN&gt;());&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; mockRepository.VerifyAll();&lt;/P&gt;
&lt;P style="MARGIN: 0px"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;In questo caso abbiamo detto che ci aspettiamo una sola chiamata del metodo Add e non ci interessa il valore dei parametri.&lt;/P&gt;&lt;img src="http://blogs.ugidotnet.org/AntonioGanci/aggbug/64722.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Antonio Ganci</dc:creator>
            <guid>http://blogs.ugidotnet.org/AntonioGanci/archive/2007/01/03/64722.aspx</guid>
            <pubDate>Wed, 03 Jan 2007 16:47:00 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/AntonioGanci/comments/64722.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/AntonioGanci/archive/2007/01/03/64722.aspx#feedback</comments>
            <slash:comments>3</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/AntonioGanci/comments/commentRss/64722.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/AntonioGanci/services/trackbacks/64722.aspx</trackback:ping>
        </item>
        <item>
            <title>Behaviour-Driven Development</title>
            <link>http://blogs.ugidotnet.org/AntonioGanci/archive/2006/12/18/60021.aspx</link>
            <description>&lt;P&gt;Segnalo l'articolo &lt;A href="http://dannorth.net/introducing-bdd"&gt;Introducing Behaviour-Driven Development&lt;/A&gt; (BDD) di Dan North. &lt;/P&gt;
&lt;P&gt;Per me che pratico &lt;A href="http://en.wikipedia.org/wiki/Test_driven_development"&gt;TDD&lt;/A&gt; da alcuni anni &amp;#232; stato illuminante perch&amp;#232; il BDD guida la scrittura dei test dal punto di vista del comportamento del sistema. &lt;/P&gt;
&lt;P&gt;Secondo l'articolo &amp;#232; importante rimanere focalizzati sulla domanda: &lt;/P&gt;
&lt;P&gt;&lt;B&gt;What&amp;#8217;s the next most important thing the system doesn&amp;#8217;t do?&lt;/B&gt; &lt;/P&gt;
&lt;P&gt;Voglio provare ad introdurre le pratiche suggerite nel mio prossimo progetto e verificarne i benefici. &lt;/P&gt;&lt;img src="http://blogs.ugidotnet.org/AntonioGanci/aggbug/60021.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Antonio Ganci</dc:creator>
            <guid>http://blogs.ugidotnet.org/AntonioGanci/archive/2006/12/18/60021.aspx</guid>
            <pubDate>Mon, 18 Dec 2006 08:58:00 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/AntonioGanci/comments/60021.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/AntonioGanci/archive/2006/12/18/60021.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/AntonioGanci/comments/commentRss/60021.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/AntonioGanci/services/trackbacks/60021.aspx</trackback:ping>
        </item>
        <item>
            <title>Flexibility vs Efficiency</title>
            <link>http://blogs.ugidotnet.org/AntonioGanci/archive/2006/11/20/55633.aspx</link>
            <description>&lt;P&gt;Segnalo il post &lt;A href="http://siddhi.blogspot.com/2006/11/flexibility-vs-efficiency.html"&gt;Flexibility vs Efficiency&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Fonte: &lt;A href="http://joel.reddit.com/info/rn40/comments"&gt;joel reddit&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Nell'articolo viene paragonato l'approccio agile a quello waterfall, sostenendo che il metodo waterfall &amp;#232; pi&amp;#249; efficiente nel caso in cui non ci siano cambiamenti durante la realizzazione di un progetto, mentre il secondo reagisce velocemente alle modifiche (praticamente tutti i progetti software).&lt;/P&gt;&lt;img src="http://blogs.ugidotnet.org/AntonioGanci/aggbug/55633.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Antonio Ganci</dc:creator>
            <guid>http://blogs.ugidotnet.org/AntonioGanci/archive/2006/11/20/55633.aspx</guid>
            <pubDate>Mon, 20 Nov 2006 12:04:00 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/AntonioGanci/comments/55633.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/AntonioGanci/archive/2006/11/20/55633.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/AntonioGanci/comments/commentRss/55633.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/AntonioGanci/services/trackbacks/55633.aspx</trackback:ping>
        </item>
        <item>
            <title>Il Test di Joel per un team agile</title>
            <link>http://blogs.ugidotnet.org/AntonioGanci/archive/2006/10/11/51074.aspx</link>
            <description>&lt;P&gt;Joel Spolsky ha creato un semplice &lt;A href="http://italian.joelonsoftware.com/Articles/TheJoelTest.html"&gt;test&lt;/A&gt; di dodici domande per valutare la qualit&amp;#224; di un gruppo di sviluppo software. Le risposte consentite sono si o no dopodic&amp;#232; si fa la somma dei si: &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Usate un sistema per il versionamento del codice? &lt;/LI&gt;
&lt;LI&gt;Potete compilare una build in un solo passo? &lt;/LI&gt;
&lt;LI&gt;Fate compilazioni giornaliere? &lt;/LI&gt;
&lt;LI&gt;Avete un database dei bug? &lt;/LI&gt;
&lt;LI&gt;Sistemate i bug prima di scrivere nuovo codice? &lt;/LI&gt;
&lt;LI&gt;Avete una tabella di marcia aggiornata? &lt;/LI&gt;
&lt;LI&gt;Avete delle specifiche? &lt;/LI&gt;
&lt;LI&gt;I programmatori lavorano in un posto tranquillo? &lt;/LI&gt;
&lt;LI&gt;Usate i migliori strumenti sul mercato? &lt;/LI&gt;
&lt;LI&gt;Avete dei tester? &lt;/LI&gt;
&lt;LI&gt;I candidati scrivono codice durante il colloquio? &lt;/LI&gt;
&lt;LI&gt;Fate test dell'usabilit&amp;#224; "da corridoio"? &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;L'idea mi piace e vorrei proporre una lista di domande per calcolare quando &lt;EM&gt;agile&lt;/EM&gt; &amp;#232; un gruppo di sviluppo software:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Fate tutti i giorni lo standup meeting?&lt;/LI&gt;
&lt;LI&gt;Il vostro codice &amp;#232; coperto da test automatici?&lt;/LI&gt;
&lt;LI&gt;Quando viene segnalato un nuovo bug scrivete un test automatico che lo riproduca?&lt;/LI&gt;
&lt;LI&gt;Avete una build automatica notturna, la quale fallisce se tutti i test automatici non passano?&lt;/LI&gt;
&lt;LI&gt;Lavorate con iterazioni non pi&amp;#249; lunghe di 15 giorni?&lt;/LI&gt;
&lt;LI&gt;Organizzate Design Review almeno una volta al mese?&lt;/LI&gt;
&lt;LI&gt;Organizzate planning game dopo ogni iterazione in cui partecipa anche il cliente?&lt;/LI&gt;
&lt;LI&gt;Fate pair programming per almeno un quarto del tempo di sviluppo?&lt;/LI&gt;
&lt;LI&gt;Raccogliete e pubblicate metriche sul software e sulle attivit&amp;#224; svolte?&lt;/LI&gt;
&lt;LI&gt;I requisiti sono raccolti come User Story della durata non superiore ad una iterazione?&lt;/LI&gt;
&lt;LI&gt;Stimate le attivit&amp;#224; prima di svolgerle?&lt;/LI&gt;
&lt;LI&gt;Almeno due volte all'anno fate un meeting in cui si valutano la qualit&amp;#224; delle pratiche usate?&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Una risposta affermativa ad una domanda si pu&amp;#242; dare solo se &lt;STRONG&gt;tutto il team&lt;/STRONG&gt; attua quell'attivit&amp;#224;, basta che un solo membro non la segua affinch&amp;#232; la risposta sia no. Ad ogni si, si ottiene un punto, se il punteggio complessivo non &amp;#232; almeno 10 il team non pu&amp;#242; considerarsi agile. &lt;/P&gt;
&lt;P&gt;Cosa ne pensate? L'ho scritto di getto quindi potrei aver dimenticato qualcosa di importante.&lt;/P&gt;&lt;img src="http://blogs.ugidotnet.org/AntonioGanci/aggbug/51074.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Antonio Ganci</dc:creator>
            <guid>http://blogs.ugidotnet.org/AntonioGanci/archive/2006/10/11/51074.aspx</guid>
            <pubDate>Wed, 11 Oct 2006 09:22:00 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/AntonioGanci/comments/51074.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/AntonioGanci/archive/2006/10/11/51074.aspx#feedback</comments>
            <slash:comments>3</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/AntonioGanci/comments/commentRss/51074.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/AntonioGanci/services/trackbacks/51074.aspx</trackback:ping>
        </item>
    </channel>
</rss>