From: <ari...@us...> - 2009-09-08 13:21:01
|
Revision: 1949 http://simpletest.svn.sourceforge.net/simpletest/?rev=1949&view=rev Author: arialdomartini Date: 2009-09-08 13:20:51 +0000 (Tue, 08 Sep 2009) Log Message: ----------- 3 pages translated from English to Italian. Minor fixes in English version: implemntation => implementation afterwoods => afterwards Modified Paths: -------------- simpletest/trunk/docs/source/en/mock_objects_documentation.xml simpletest/trunk/docs/source/it/group_test_documentation.xml simpletest/trunk/docs/source/it/mock_objects_documentation.xml simpletest/trunk/docs/source/it/unit_test_documentation.xml Modified: simpletest/trunk/docs/source/en/mock_objects_documentation.xml =================================================================== --- simpletest/trunk/docs/source/en/mock_objects_documentation.xml 2009-09-06 18:07:34 UTC (rev 1948) +++ simpletest/trunk/docs/source/en/mock_objects_documentation.xml 2009-09-08 13:20:51 UTC (rev 1949) @@ -433,7 +433,7 @@ </p> <p> Objects with dynamic interfaces, using <code>__call</code>, can - be problematic with the current mock objects implemntation. + be problematic with the current mock objects implementation. You can mock the <code>__call()</code> method, but this is ugly. Why should a test know anything about such low level implementation details? It just wants to simulate the call. @@ -571,8 +571,8 @@ <p> Tests without assertions can be both compact and very expressive. Because we intercept the call on the way into an object, here of - the <code>Alert</code> class, we avoid having to assert it's state - afterwoods. + the <code>Alert</code> class, we avoid having to assert its state + afterwards. This not only avoids the assertions in the tests, but also having to add extra test only accessors to the original code. If you catch yourself adding such accessors, called "state based testing", Modified: simpletest/trunk/docs/source/it/group_test_documentation.xml =================================================================== --- simpletest/trunk/docs/source/it/group_test_documentation.xml 2009-09-06 18:07:34 UTC (rev 1948) +++ simpletest/trunk/docs/source/it/group_test_documentation.xml 2009-09-08 13:20:51 UTC (rev 1949) @@ -5,8 +5,8 @@ <content> <section name="group" title="Grouping tests into suites"> <p> - There are many ways to group tests together into test suites. - One way is to simply place multiple test cases into a single file... + Eistono molti sistemi per raggruppare i test in test suite. + Uno di questi \xE8 quello di mettere semplicemente pi\xF9 test case in un singolo file: <php><![CDATA[ <strong><?php require_once(dirname(__FILE__) . '/simpletest/autorun.php'); @@ -21,13 +21,15 @@ } ?></strong> ]]></php> - As many cases as needed can appear in a single file. - They should include any code they need, such as the library - being tested, but need none of the SimpleTest libraries. + E' possibile mettere quanti test case si vuole in ogni file. + Ogni file necessario all'esecuzione, come ad esempio la libreria da + collaudare, dovrebbe essere incluso ma non \xE8 necessario includere + alcuna libreria di SimpleTest. </p> <p> - If you have extended any test cases, you can include them too. - Simply mark any test cases that should not be run as abstract... + Nel caso si sia estesa qualche test case da una classe base, anche questa + deve essere inclusa. + Qualsiasi classe di test non debba essere invocata deve essere marcata come abstract: <php><![CDATA[ <strong>abstract</strong> class MyFileTestCase extends UnitTestCase { ... @@ -37,17 +39,17 @@ class SocketTester extends UnitTestCase { ... } ]]></php> - Here the <code>FileTester</code> class does - not contain any actual tests, but is a base class for other - test cases. + Qui, ad esempio, la classe <code>FileTester</code> non contiene + alcun test ma viene utilizzata come classe base per altri case test. </p> <p> - We will call this sample <em>file_test.php</em>. - Next we create a test suite file, called say <em>my_test_suite.php</em>. - You will think of a better name I am sure. + Chiameremo questo file di esempio <em>file_test.php</em>. + Il passo successivo \xE8 quello di creare il file della test suite + che potremmo chiamare <em>my_test_suite.php</em>. + Sono certo che saprai trovare nomi migliori di questo. </p> <p> - We will add the test file using a safe method... + Adesso aggiungeremo il test file alla suite con un metodo sicuro: <php><![CDATA[ <?php require_once('simpletest/autorun.php'); @@ -61,18 +63,17 @@ } ?> ]]></php> - What happens here is that the <code>TestSuite</code> - class will do the <code>require_once()</code> - for us. - It then checks to see if any new test case classes - have been created by the new file and automatically adds - them to the test suite. - This method gives us the most control. + Quello che accadr\xE0 \xE8 che la classe <code>TestSuite</code> + penser\xE0 autonomamente ad eseguire i <code>require_once()</code> + necessari, controller\xE0 se nuove classi di test case sono presenti nel + file e all'occorrenza li aggiunger\xE0 alla test suite. + + Questo metodo ci fornisce il massimo del controllo. </p> <p> - If this is too much typing, and you are willing to group - test suites together in their own directories or otherwise - tag the file names, then there is a more automatic way... + Nel caso questo metodo sembrasse troppo prolisso e si desiderasse + di raggruppare tra loro pi\xF9 test suite di una stessa directory oppure in + base al loro nome del file, esiste un metodo ancora pi\xF9 automatico: <php><![CDATA[ <?php require_once('simpletest/autorun.php'); @@ -86,36 +87,35 @@ } ?> ]]></php> - This will scan a directory called "unit" for any files - ending with "_test.php" and load them. - You don't have to use <code>SimplePatternCollector</code> to - filter by a pattern in the filename, but this is the most common - usage. + Questo sistema ricerca nella directory "unit" i file + il cui nome termina per "_test.php" e li carica. + L'uso di <code>SimplePatternCollector</code> per filtrare in + base ad un pattern non \xE8 obbligatorio ma \xE8 il sistema pi\xF9 comune. </p> <p> - Now all you have to do is drop a file of test cases into the - directory and it will run just by running the test suite script. + Tutto quel che resta da fare adesso \xE8 creare un file nella directory + dei test case che lancer\xE0 lo script della test suite. </p> <p> - Test cases loaded with the <code>addFile</code> method have some - useful properties. - You can guarantee that the constructor is run - just before the first test method and the destructor - is run just after the last test method. - This allows you to place test case wide set up and tear down - code in the constructor and destructor, just like a normal - class. + I test case caricati con il metodo <code>addFile</code> posseggono + alcune utili propriet\xE0. + Si ha la certezza che il costruttore sia invocato prima del lancio del + primo test e il distruttore dopo l'esecuzione dell'ultimo. + Questo consente di ospitare nel costruttore e nel distruttore + il codice di set up e di tear down che deve valere per tutto il test case. </p> </section> <section name="higher" title="Composite suites"> <p> - The above method places all of the test cases into one large suite. - For larger projects though this may not be flexible enough; you - may want to group the tests in all sorts of ways. + Il metodo appena presentato prevede di ospitare tutti i test case in + un'unica grande test suite. + Per progetti di grandi dimensione, tuttavia, questo metodo non risulta + abbastanza flessibile perch\xE9 si potrebbe desiderare di raggrupare + test nelle pi\xF9 varie modalit\xE0. </p> <p> - To get a more flexible group test we can subclass - <code>TestSuite</code> and then instantiate it as needed... + Per poter disporre di un group test pi\xF9 flessibile + \xE8 possibile istanziare una classe che erediti da <code>TestSuite</code>: <php><![CDATA[ <?php require_once('simpletest/autorun.php'); @@ -128,11 +128,11 @@ }</strong> ?> ]]></php> - This effectively adds our test cases and a single suite below - the first. - Not much use as is, but we can add more than one suite at this point. - We can even mix groups and test cases freely as long as - we are careful about double includes. + In questo modo si \xE8 aggiunta una test suite dentro un'altra. + In questo caso non risulta molto utile ma \xE8 possibile aggiungere + altre suite a piacimento. + E' perfino possibile mescolare gruppi e singoli test case a patto + di prestare attenzione alle inclusioni multiple. <php><![CDATA[ <?php require_once('simpletest/autorun.php'); @@ -146,8 +146,8 @@ } ?> ]]></php> - In the event of a double include, ony the first instance - of the test case will be run. + Nel caso si includa un file pi\xF9 di una volta, verrebbe eseguita + solo la prima istanza del test. </p> </section> </content> Modified: simpletest/trunk/docs/source/it/mock_objects_documentation.xml =================================================================== --- simpletest/trunk/docs/source/it/mock_objects_documentation.xml 2009-09-06 18:07:34 UTC (rev 1948) +++ simpletest/trunk/docs/source/it/mock_objects_documentation.xml 2009-09-08 13:20:51 UTC (rev 1949) @@ -5,58 +5,68 @@ <content> <section name="what" title="What are mock objects?"> <p> - Mock objects have two roles during a test case: actor and critic. + Gli oggetti mock svolgono due ruoli durante un test case: il ruolo di "attori" + ed il ruolo di "critici" </p> <p> - The actor behaviour is to simulate objects that are difficult to - set up or time consuming to set up for a test. - The classic example is a database connection. - Setting up a test database at the start of each test would slow - testing to a crawl and would require the installation of the - database engine and test data on the test machine. - If we can simulate the connection and return data of our - choosing we not only win on the pragmatics of testing, but can - also feed our code spurious data to see how it responds. - We can simulate databases being down or other extremes - without having to create a broken database for real. - In other words, we get greater control of the test environment. + Nel ruolo di attore il mock ha la funzione di simulare il + comportamento di un altro oggetto che durante il test sarebbe + difficile o oneroso da instanziare. + L'esempio classico \xE8 quello di una connessione ad un database. + Allestire un database di collaudo all'inizio di ogni singolo testo + rallenterebbe il collaudo a livelli inaccettabile e richiederebbe + l'istallazione di un apposito motore di database e di dati di test sul + server di test. + Se ci fosse la possibilit\xE0 di similare la connessione e restituire + i dati selezionati per il collaudo non solo si otterrebbero dei + test pi\xF9 pragmatici ma ci si potrebbe permettere di alimentare il + codice con dati spuri per vederne la reazione. + Avremmo la possibilit\xE0 di simulare il caso di un database fuori linea o + altre condizioni estreme di questo tipo, senza la necessit\xE0 di generare + i malfunzionamenti nella realt\xE0. + In altre parole, i mock possono fornire un grande controllo dell'ambiente + di test. </p> <p> - If mock objects only behaved as actors they would simply be - known as "server stubs". - This was originally a pattern named by Robert Binder (<a href="">Testing - object-oriented systems</a>: models, patterns, and tools, - Addison-Wesley) in 1999. + Se gli oggetti mock si comportassero solo come attori sarebbero + semplicemente conosciuto come "server stubs". + Questi sono stati introdotti come pattern di sviluppo da + Robert Binder in (<a href="">Testing object-oriented systems</a> models, patterns, and tools, + Addison-Wesley) nel 1999. </p> <p> - A server stub is a simulation of an object or component. - It should exactly replace a component in a system for test - or prototyping purposes, but remain lightweight. - This allows tests to run more quickly, or if the simulated - class has not been written, to run at all. + Un server stub \xE8 la simulazione di un oggetto o di un componente. + Dovrebbe rimpiazzare esplicitamente un componente con lo scopo di + permettere il test o la prototipazione ma, fondamentalmente, resta un + componente leggero. + In questo modo permette ai test di eseguirsi con rapidit\xE0; nel caso + la classe simulata ancora non esista affatto, permettono di eseguire + comunque il codice. </p> <p> - However, the mock objects not only play a part (by supplying chosen - return values on demand) they are also sensitive to the - messages sent to them (via expectations). - By setting expected parameters for a method call they act - as a guard that the calls upon them are made correctly. - If expectations are not met they save us the effort of - writing a failed test assertion by performing that duty on our - behalf. + Tuttavia, gli oggetti mock non solo svolgono questo ruolo + (restituiendo valori di ritorno alla loro interrogazione) ma + sono anche sensibili ai messaggi che vengono loro inviati + (tramite le expectation). + Impostando i parametri attesi dalla invocazione di un metodo + i mock si comportano da garanti della correttezza nelle chiamate + ai metodi. + Se le expectation non sono rispettare, i mock ci risparmiano la + fatica di scrivere le assert fanno il lavoro sporco a posto nostro. </p> <p> - In the case of an imaginary database connection they can - test that the query, say SQL, was correctly formed by - the object that is using the connection. - Set them up with fairly tight expectations and you will - hardly need manual assertions at all. + Nel caso della connessione ad un database immaginrio sono + in grado di verificare l'oggetto chiamante stia usando una query, supponiamo + SQL, formalmente corretta. + Una volta preparai con expectation sufficientemente rigorose + non si avr\xE0 pi\xF9 bisogno di eseguire manualmente gli assert. </p> </section> <section name="creation" title="Creating mock objects"> <p> - All we need is an existing class, say a database connection - that looks like this... + Tutto quello di cui abbiamo bisogno \xE8 una classe esistente, + supponiamo per la connessione al database, che abbia + questo aspetto: <php><![CDATA[ <strong>class DatabaseConnection { function DatabaseConnection() { } @@ -64,8 +74,8 @@ function selectQuery($sql) { } }</strong> ]]></php> - The class does not need to have been implemented yet. - It could be just an interface... + Non c'\xE8 bisogno che la classe sia stata implementata. + Pu\xF2 bastare la sua interfaccia: <php><![CDATA[ <strong>interface DatabaseConnection { function DatabaseConnection(); @@ -73,18 +83,18 @@ function selectQuery($sql); }</strong> ]]></php> - To create a mock version of the class we need to run a - code generator... + Per generare una versione mock della classe si + deve invocare il code generator: <php><![CDATA[ require_once('simpletest/autorun.php'); require_once('database_connection.php'); <strong>Mock::generate('DatabaseConnection');</strong> ]]></php> - This generates a clone class called - <code>MockDatabaseConnection</code>. - We can now create instances of the new class within - our test case... + Questo genera una classe clone + chiamata <code>MockDatabaseConnection</code>. + Adesso \xE8 possibile istanziare la nuova classe + all'interno del test case: <php><![CDATA[ require_once('simpletest/autorun.php'); require_once('database_connection.php'); @@ -98,9 +108,9 @@ } } ]]></php> - The mock version now has all the methods of the original. - Also, any type hints will be faithfully preserved. - Say our query methods expect a <code>Query</code> object... + La versione mock possiede tutti i metodi della classe originale. + Anche i tipi degli argomenti vengono fedelmente preservati. + Supponiamo che il metodo query si aspetti un oggetto <code>Query</code>: <php><![CDATA[ <strong>class DatabaseConnection { function DatabaseConnection() { } @@ -108,7 +118,8 @@ function selectQuery(Query $query) { } }</strong> ]]></php> - If we now pass the wrong type of object, or worse a non-object... + Nel caso si invochi il metodo con un oggetto di tipo sbagliato o, + peggio, con un non-object... <php><![CDATA[ class MyTestCase extends UnitTestCase { @@ -118,54 +129,57 @@ } } ]]></php> - ...the code will throw a type violation at you just as the - original class would. + ...il codice lancerebbe un'eccezione di violazione di tipo + esattamente come farebbe la classe originale. </p> <p> - The mock version now has all the methods of the original. - Unfortunately, they all return <code>null</code>. - As methods that always return <code>null</code> are not that useful, - we need to be able to set them to something else... + Anche se la versione mock possiede tutti i metodi della classe originale, + questi restituiscono sfortunatamente <code>null</code>. + Dal momenti che i metodi restituiscono sistematicamente <code>null</code> + non risultano molto utili + ed abbiamo bisogno di un modo per impostarle per + avere un comportamento diverso: </p> <p> <a class="target" name="stub"><h2>Mocks as actors</h2></a> </p> <p> - Changing the return value of a method from <code>null</code> - to something else is pretty easy... + Modificare il valore di ritorno di un metodo da <code>null</code> + a qualcos'altro \xE8 abbastanza semplice: <php><![CDATA[ <strong>$connection->returns('query', 37)</strong> ]]></php> - Now every time we call - <code><![CDATA[$connection->query()]]></code> we get - the result of 37. - There is nothing special about 37. - The return value can be arbitrarily complicated. + Adesso, ogni invocazione di + <code><![CDATA[$connection->query()]]></code> restituisce 37. + 38 non ha niente di speciale: il valore di ritorno pu\xF2 + essere arbitrariamente complesso. </p> <p> - Parameters are irrelevant here, we always get the same - values back each time once they have been set up this way. - That may not sound like a convincing replica of a - database connection, but for the half a dozen lines of - a test method it is usually all you need. + I parametri, in questo caso, sono irrilevanti e + una volta che si sia impostato il mock con questo + sistema si otterr\xE0 sempre il medesimo valore qualsiasi essi siano + Questa potrebbe apparire una replica poco convincente di una + connessione al database, ma per un metodo di test di + una mezza dozzina di righe, solitamente, \xE8 tutto quello + di cui si pu\xF2 aver bisogno. </p> <p> - Things aren't always that simple though. - One common problem is iterators, where constantly returning - the same value could cause an endless loop in the object - being tested. - For these we need to set up sequences of values. - Let's say we have a simple iterator that looks like this... + Tuttavia, le cose non sono sempre cos\xEC semplici. + Uno dei problemi comuni si propone con le iterazioni, nelle quali + il ritorno sistematico del solito valore pu\xF2 causare cicli + infiniti dentro l'oggetto da collaudare. + Per questo c'\xE8 bisogno di poter impostare sequenze di valori. + Supponiamo di avere una semplice iterazione come questa: <php><![CDATA[ class Iterator { function Iterator() { } function next() { } } ]]></php> - This is about the simplest iterator you could have. - Assuming that this iterator only returns text until it - reaches the end, when it returns false, we can simulate it - with... + Stiamo parlando dell'iterazione pi\xF9 semplice che possa capitare. + Se si assume che questa iterazione restituisca del testo + fino a quando raggiunge la fine e che da quel momento + debba restituire false, si potrebbe simularla cos\xEC: <php><![CDATA[ Mock::generate('Iterator'); @@ -180,90 +194,93 @@ } } ]]></php> - When <code>next()</code> is called on the - <code>MockIterator</code> it will first return "First string", - on the second call "Second string" will be returned - and on any other call <code>false</code> will - be returned. - The sequenced return values take precedence over the constant - return value. - The constant one is a kind of default if you like. + Quando <code>next()</code> di <code>MockIterator</code> viene invocata + restituir\xE0 "First string" la prima volta e "Second string" la + seconda mentre false tutte le altre volte. + I valori di ritorno delle sequenze hanno precedenza sul valori + di ritorno costante. + Se pu\xF2 essere utile, si pu\xF2 pensare al valore di ritorno costante + come il valore di ritorno di default. </p> <p> - Another tricky situation is an overloaded - <code>get()</code> operation. - An example of this is an information holder with name/value pairs. - Say we have a configuration class like... + Un'altra situazione delicata \xE8 il caso di un'operazione + <code>get()</code> overloaded. + Ad esempio \xE8 quando un'informazione conservata con una coppia nome/valore. + Supponiamo di avere una classe di configurazione come questa: <php><![CDATA[ class Configuration { function Configuration() { ... } function get($key) { ... } } ]]></php> - This is a likely situation for using mock objects, as - actual configuration will vary from machine to machine and - even from test to test. - The problem though is that all the data comes through the - <code>get()</code> method and yet - we want different results for different keys. - Luckily the mocks have a filter system... + Questo \xE8 la tipica situazione in cui un oggetto mock risulta + utile, dal momento che la configurazione variet\xE0 da macchina + a macchina e perfino da test a test. + Tuttavia, il problema \xE8 che i dati vengono recuperati mediante + la chiamata al metodo <code>get()</code> e che, contemporaneamente, + si desiderano valori differenti in corrispondenza di chiavi differenti. + Fortunatamente, i mock dispongono di un sistema di filtraggio: <php><![CDATA[ <strong>$config = &new MockConfiguration(); $config->returns('get', 'primary', array('db_host')); $config->returns('get', 'admin', array('db_user')); $config->returns('get', 'secret', array('db_password'));</strong> ]]></php> - The extra parameter is a list of arguments to attempt - to match. - In this case we are trying to match only one argument which - is the look up key. - Now when the mock object has the - <code>get()</code> method invoked - like this... + Il parametro aggiunto \xE8 l'elenco degli argomenti con + i quali provare a fare un match. + In questo caso, ad esempio, si sta provando il match con il solo + argomento a disposizione il quale viene usato come look up key. + Adesso, quando il metodo <code>get()</code> dell'oggetto mock + viene invocato, come in... <php><![CDATA[ $config->get('db_user') ]]></php> - ...it will return "admin". - It finds this by attempting to match the calling arguments - to its list of returns one after another until - a complete match is found. + ...restituir\xE0 "admin". + Il risultato \xE8 stato ricavato tentando il match degli argomenti + richiesti con ognuno dei valori dell'elenco, fino a che un match + completo viene individuato. </p> <p> - You can set a default argument argument like so... + E' anche possibile impostare un argomento di default: <php><![CDATA[<strong> $config->returns('get', false, array('*'));</strong> ]]></php> - This is not the same as setting the return value without - any argument requirements like this... + Questo non \xE8 equivalente ad impostare il valore di + ritorno che si deve avere in assenza di argomenti, come accade con: <php><![CDATA[<strong> $config->returns('get', false);</strong> ]]></php> - In the first case it will accept any single argument, - but exactly one is required. - In the second case any number of arguments will do and - it acts as a catchall after all other matches. - Note that if we add further single parameter options after - the wildcard in the first case, they will be ignored as the wildcard - will match first. - With complex parameter lists the ordering could be important - or else desired matches could be masked by earlier wildcard - ones. - Declare the most specific matches first if you are not sure. + Nel primo caso, viene accettato qualsiasi singolo argomento ma + un argomento \xE8 comunque richiesto. + Il secondo caso accetta un qualsiasi numero di argomenti e + viene considerato nel caso siano gi\xE0 stati tentati tutti gli altri match. + + Si noti che se nel primo caso si aggiungesse ulteriori parametri + dopo il carattere jolly questi verrebbero ignorati perch\xE9 + la condizione sul carattere jolly verrebbe soddisfatta prima della + loro valutazione. + + Con elenchi di parametri particolarmente complessi l'ordine + potrebbe essere importante e si corre il rischio di avere delle + corrispondenze che vengono mascherate da caretteri jolly dichiarati + prima. + Nel caso di dubbi \xE8 meglio dichiarare i match pi\xF9 specifici all'inzio. + </p> <p> - There are times when you want a specific reference to be - dished out by the mock rather than a copy or object handle. - This a rarity to say the least, but you might be simulating - a container that can hold primitives such as strings. - For example... + Ci sono casi in cui si desidera che il mock gestisca dei + riferimenti ad oggetti piuttosto che delle copie degli stessi. + Accade raramente, ma potrebbe capitare di dover simulare + un oggetto che gestisce dati primitivi, come delle stringhe. + Per esempio: <php><![CDATA[ class Pad { function Pad() { } function ¬e($index) { } } ]]></php> - In this case you can set a reference into the mock's - return list... + In questo caso, per impostare un riferimento nell'elenco + dei valori di ritorno: <php><![CDATA[ function testTaskReads() { $note = 'Buy books'; @@ -273,15 +290,15 @@ ... } ]]></php> - With this arrangement you know that every time - <code><![CDATA[$pad->note(3)]]></code> is - called it will return the same <code>$note</code> each time, - even if it get's modified. + Con questa soluzione si \xE8 certi che ogni volta che viene + invocato <code><![CDATA[$pad->note(3)]]></code> viene + restituito sempre il medesimo oggetto <code>$note</code>, perfino + quando questo viene modificato. </p> <p> - These three factors, timing, parameters and whether to copy, - can be combined orthogonally. - For example... + E' possibile combinare ortogonalmente i tre fattori tempo, parametri e + uso delle copie e dei riferimenti. Per esempio: + <php><![CDATA[ $buy_books = 'Buy books'; $write_code = 'Write code'; @@ -289,20 +306,20 @@ $vector-><strong>returnsByReferenceAt(0, 'note', $buy_books, array('*', 3)); $vector-><strong>returnsByReferenceAt(1, 'note', $write_code, array('*', 3)); ]]></php> - This will return a reference to <code>$buy_books</code> and - then to <code>$write_code</code>, but only if two parameters - were set the second of which must be the integer 3. - That should cover most situations. + Questo restituisce un riferimento a <code>$buy_books</code> e + successivamente a <code>$write_code</code>, ma solo sei i due + paramtri risultano impostati ed il secondo \xE8 l'intero 3. + In questo modo ogni esigenza dovrebbe risultare soddisfatta. </p> <p> - A final tricky case is one object creating another, known - as a factory pattern. - Suppose that on a successful query to our imaginary - database, a result set is returned as an iterator, with - each call to the the iterator's <code>next()</code> giving - one row until false. - This sounds like a simulation nightmare, but in fact it can all - be mocked using the mechanics above... + Un ultimo caso delicato \xE8 quello di un oggetto che ne instanzia un + altro, ovvero quello che \xE8 conosciuto come factory pattern. + Supponiamo che una query al nostro immaginario database abbia successo + e che venga restituito un result set nella forma di iteratore in modo + che ad ogni chiamata del metodo <code>next()</code> dell'iteratore venga fornita una + riga o il valore false. + L'idea di dover simulare un comportamento simile pu\xF2 sembrare da incubo ma + in realt\xE0 pu\xF2 essere realizzata con un mock con il meccanismi gi\xE0 presentati: <php><![CDATA[ Mock::generate('DatabaseConnection'); Mock::generate('ResultIterator'); @@ -326,46 +343,44 @@ } } ]]></php> - Now only if our - <code>$connection</code> is called with the - <code>query()</code> method will the - <code>$result</code> be returned that is - itself exhausted after the third call to <code>next()</code>. - This should be enough - information for our <code>UserFinder</code> class, - the class actually - being tested here, to come up with goods. - A very precise test and not a real database in sight. + Adesso solo se viene invocato il metodo <code>query()</code> + di <code>$connection</code> viene restituito l'oggetto <code>$result</code> + che si esaurisce la sua funzione dopo la terza chiamata a <code>next()</code>. + Dovrebbero esserci abbastanza informazioni perch\xE9 la classe + <code>UserFinder</code> possa essere collaudata senza problemi. + Un test molto preciso e nessun database reale tra i piedi. </p> <p> - We could refine this test further by insisting that the correct - query is sent... + E' possibile ulteriormente raffinare questo test richiedendo che venga + utilizzata la query corretta: <php><![CDATA[ $connection->returns('selectQuery', $result, array(<strong>'select name, id from people'</strong>)); ]]></php> - This is actually a bad idea. + Il realt\xE0 questa \xE8 una cattiva idea. </p> <p> - We have a <code>UserFinder</code> in object land, talking to - database tables using a large interface - the whole of SQL. - Imagine that we have written a lot of tests that now depend - on the exact SQL string passed. - These queries could change en masse for all sorts of reasons - not related to the specific test. - For example the quoting rules could change, a table name could - change, a link table added or whatever. - This would require the rewriting of every single test any time - one of these refactoring is made, yet the intended behaviour has - stayed the same. - Tests are supposed to help refactoring, not hinder it. - I'd certainly like to have a test suite that passes while I change - table names. + Abbiamo <code>UserFinder</code> che appartiene al mondo degli oggetti + e che comunica con le tabelle del database utilizzando un'interfaccia + piuttosto estesa, l'intero SQL. + Immaginamo di aver scritto molti test come questo che adesso si trovano + a dipendere dall'esatta stringa SQL utilizzata. + C'\xE8 la possibilit\xE0 che queste query cambino in massa per ragioni non legate + allo specifico test. Ad esempio, le regole nell'uso di apici e virgolette + potrebbe cambiare, potrebbe essere rinominata una tabella, potrebbe venire + aggiunta una link table e cos\xEC via. + Queste modifiche richiederebbero la riscrittura di ogni singolo test ogni volta + che viene eseguito un refactoring, nonostante il comportamento da collaudare + sia fondamentalmente restato inalterato. + I test sono pensati per aiutare il refactoring, non per ostacolarlo. + Personalmente, preferirei certamente una test suite che non faccia fallire i + test solo per un cambio di nome di tabella. </p> <p> - As a rule it is best not to mock a fat interface. + Una regola \xE8 quella di non scrivere mock di interfacce troppo complesse. + </p> <p> - By contrast, here is the round trip test... + Al contrario, ecco come appare un test completo: <php><![CDATA[ class DatabaseTest extends UnitTestCase {<strong> function setUp() { ... } @@ -382,23 +397,24 @@ } } ]]></php> - This test is immune to schema changes. - It will only fail if you actually break the functionality, which - is what you want a test to do. + Questo collaudo \xE8 immune ai cambiamenti dello schema del db. + Fallisce solo se si rompono le funzionalit\xE0 dell'applicazione, cio\xE8 + quello che intendevamo collaudare. </p> <p> - The catch is those <code>setUp()</code> and <code>tearDown()</code> - methods that we've rather glossed over. - They have to clear out the database tables and ensure that the - schema is defined correctly. - That can be a chunk of extra work, but you usually have this code - lying around anyway for deployment purposes. + Il segreto \xE8 nel codice di <code>setUp()</code> e di <code>tearDown()</code> + sui quali fino ad ora abbiamo sorvolato. + Questi metodi hanno il compito di ripulire le tabelle del database + ed assicurare la correttezza dello schema. + Realizzare questo risultato pu\xF2 comportare molto lavoro ma generalente + si dispone comunque di codice simile per svolgere il deployment. </p> <p> - One place where you definitely need a mock is simulating failures. - Say the database goes down while <code>UserFinder</code> is doing - it's work. - Does <code>UserFinder</code> behave well...? + Un'area dove si ha veramente bisogno del mocking \xE8 nella simulazione + delle anomalie. + Supponiamo che il database cada durante il funzionamento di <code>UserFinder</code> + + <code>UserFinder</code> reagisce come desideriamo? <php><![CDATA[ class DatabaseTest extends UnitTestCase { @@ -412,93 +428,94 @@ } } ]]></php> - We've passed the <code>UserFinder</code> an <code>$alert</code> - object. - This is going to do some kind of pretty notifications in the - user interface. - To pass this test, the finder has to write a nice user friendly - message to <code>$alert</code>, rather than propogating the exception. - So far, so good. + E' stato passato un oggetto <code>$alert</code> a <code>UserFinder</code>. + Questo invier\xE0 alcuni messaggi all'interfaccia utente. + Per poter passare il test, il finder, piuttostci che propagare + un'eccezione, deve scrivere un messaggio a <code>$alert</code>. + + Per adesso, tutto bene. + </p> <p> - How do we get the mock <code>DatabaseConnection</code> to throw an exception? - We generate the exception using the <code>throwOn</code> method - on the mock. + Come possiamo dire al mock <code>DatabaseConnection</code> di lanciare l'eccezione? + La generiamo usando il metodo <code>throwOn</code>. </p> <p> - Finally, what if the method you want to simulate does not exist yet? - If you set a return value on a method that is not there, SimpleTest - will throw an error. - What if you are using <code>__call()</code> to simulate dynamic methods? + Infine, cosa accade se il metodo che intendiamo simulare non esiste affatto? + Se si tenta di impostare un valore di ritorno su un metodo che non esiste, + SimpleTest lancia un'errore. + Perch\xE9 non usare <code>__call()</code> per simulare dinamicamente i metodi? </p> <p> - Objects with dynamic interfaces, using <code>__call</code>, can - be problematic with the current mock objects implemntation. - You can mock the <code>__call()</code> method, but this is ugly. - Why should a test know anything about such low level implementation details? - It just wants to simulate the call. + L'uso di <code>__call</code> sugli oggetti con interfacce dinamiche + nella implementazione corrente dei mock pu\xF2 essere problematico. + E' possibile fare il mock del metodo <code>__call()</code> ma \xE8 una soluzione + orrenda. + Perch\xE9 mail un test dovrebbe prendersi cura di tali dettagli di implementazione? + Il test vuole solo simulare la chiamata. </p> <p> - The way round this is to add extra methods to the mock when - generating it. + La soluzione a questo \xE8 di aggiungere metodi extra al mock durante + la sua generazione. <php><![CDATA[ <strong>Mock::generate('DatabaseConnection', 'MockDatabaseConnection', array('setOptions'));</strong> ]]></php> - In a large test suite this could cause trouble, as you probably - already have a mock version of the class called - <code>MockDatabaseConnection</code> without the extra methods. - The code generator will not generate a mock version of the class if - one of the same name already exists. - You will confusingly fail to see your method if another definition - was run first. + In test suite di notevoli dimensioni questo pu\xF2 generare problemi, dal momento + che c'\xE8 il rischio di avere gi\xE0 una classe chiamata + <code>MockDatabaseConnection</code> priva dei metodi extra. + Il code generator infatti non genera la versione mock di una classe se ne + trova un'altra con lo stesso nome. + Vedere il proprio metodo fallire perch\xE9 un'altra definizione \xE8 stata + invocata precedentemente pu\xF2 essere disorientante. </p> <p> - To cope with this, SimpleTest allows you to choose any name for the - new class at the same time as you add the extra methods. + Per gestire questa situazione, SimpleTest permette allo sviluppatore + di scegliere liberamente il nome della nuova classe nel momento dell'aggiunta + dei metodi extra. <php><![CDATA[ Mock::generate('DatabaseConnection', <strong>'MyMockDatabaseConnection'</strong>, array('setOptions')); ]]></php> - Here the mock will behave as if the <code>setOptions()</code> - existed in the original class. + In questo esempio il mock si comporta come se <code>setOptions()</code> + esistesse nella classe originale. </p> <p> - Mock objects can only be used within test cases, as they send messages, - upon expectations, straight to the currently running test case. - Creating them outside a test case will cause a run time error - when an expectation is triggered. - We cover expectations next. + Gli oggetti mock possono essere utilizzati solo all'interno dei test case + perch\xE9 inviano messaggi, come expectation, direttamente al test case. + Lanciarli al di fuori dell'ambiente del test case provocherebbe + un run time error non appena la prima expectation fosse invocata. + Parleremo delle expectation pi\xF9 avanti. </p> </section> <section name="expectations" title="Mocks as critics"> <p> - Although the server stubs approach insulates your tests from - real world disruption, it is only half the benefit. - You can have the class under test receiving the required - messages, but is your new class sending correct ones? - Testing this can get messy without a mock objects library. + Nonostante l'approccio dei server stub riesca ad isolare i test + dagli sconvolgimenti del mondo, questa \xE8 solo una met\xE0 dei benefici. + E' possibile fare in modo che la classe sotto collaudo riceva + i messaggi richiesti: ma si riesce a fargli inviare indietro quelli corretti? + Il collaudo pu\xF2 diventare un vero inferno senza una libreria di mocking. </p> <p> - By way of example, let's take a simple <code>PageController</code> - class to handle a credit card payment form... + Per fare un esempio, consideriamo una semplice classe <code>PageController</code> + che gestisca il form per il pagamento con carta di credito: + <php><![CDATA[ class PaymentForm extends PageController { function __construct($alert, $payment_gateway) { ... } function makePayment($request) { ... } } ]]></php> - This class takes a <code>PaymentGateway</code> to actually talk - to the bank. - It also takes an <code>Alert</code> object to handle errors. - This class talks to the page or template. - It's responsible for painting the error message and highlighting any - form fields that are incorrect. + Questa classe utilizza un oggetto <code>PaymentGateway</code> per comunicare + fisicamente con la banca ed un oggetto <code>Alert</code> per gestire gli errori. + La classe comunica anche alla pagine o al template. + E' responsabile della visualizzazione degli errori e dell'evidenziazione + di ogni campo del form che non sia stato compilato correttamente. </p> <p> - Our interest is in the <code>makePayment()</code> method. - If we fail to enter a "CVV2" number (the three digit number - on the back of the credit card), we want to show an error rather than - try to process the payment. - In test form... + Il metodo che ci interessa \xE8 <code>makePayment()</code>. + Se viene inserito un numero "CVV2" errato (le ultime 3 cifre + sul retro della carta di credito) si vuole che il processo di pagamento non + venga nemmeno iniziato e che venga visualizzato invece un errore. + Nel test form avremo: <php><![CDATA[ <?php require_once('simpletest/autorun.php'); @@ -521,26 +538,27 @@ } ?> ]]></php> - The first question you may be asking is, where are the assertions? + Una domanda sorge spontanea: dove sono gli assert? </p> <p> - The call to <code>expectOnce('warn', array(...))</code> instructs the mock - to expect a call to <code>warn()</code> before the test ends. - When it gets a call to <code>warn()</code>, it checks the arguments. - If the arguments don't match, then a failure is generated. - It also fails if the method is never called at all. + La chiamata a <code>expectOnce('warn', array(...))</code> indica al mock + di attendersi una chiamata a <code>warn()</code> prima che il test termini. + Nel momento in cui la chiamata a <code>warn()</code> viene intercettata, il mock verifica + gli argomenti utilizzati. Se gli argomenti non corrispondono a quanto + stabilito viene generata una failure. + Viene generata una failure anche nel caso la chiamata non venga eseguita affatto. </p> <p> - The test above not only asserts that <code>warn</code> was called, - but that it received the string "Missing three digit security code" - and also the tag "cvv2". - The equivalent of <code>assertIdentical()</code> is applied to both - fields when the parameters are compared. + Il test appena visti non si milita a verificare che <code>warn</code> venga + chiamato ma che vengano ricevuta la stringa "Missing three digit security code" + ed il tag "cvv2". + Nel momento della comparazione di entrambi i parametri viene applicato + l'equivalente di <code>assertIdentical()</code>. </p> <p> - If you are not interested in the actual message, and we are not - for user interface code that changes often, we can skip that - parameter with the "*" operator... + Nel caso non si sia interessati al messaggio, come accade nel caso + di messaggi provenienti dall'interfaccia utente soggetti a molti cambiamenti, + \xE8 possibile saltare il parametro con l'operatore "*": <php><![CDATA[ class PaymentFormFailuresShouldBeGraceful extends UnitTestCase { @@ -554,8 +572,8 @@ function requestWithMissingCvv2() { ... } } ]]></php> - We can weaken the test further by missing - out the parameters array... + Possiamo rendere ancora pi\xF9 debole il test tralasciando l'array + dei parametri: <php><![CDATA[ function testMissingCvv2CausesAlert() { $alert = new MockAlert(); @@ -564,24 +582,26 @@ $controller->makePayment($this->requestWithMissingCvv2()); } ]]></php> - This will only test that the method is called, - which is a bit drastic in this case. - Later on, we'll see how we can weaken the expectations more precisely. + In questo modo l'unico test che verr\xE0 effettuato \xE8 sull'invocazione + del metodo, il che pu\xF2 essere un po' eccessivo in questo caso. + Pi\xF9 avanti vedremo come indebolire le expectation in modo pi\xF9 selettivo. </p> <p> - Tests without assertions can be both compact and very expressive. - Because we intercept the call on the way into an object, here of - the <code>Alert</code> class, we avoid having to assert it's state - afterwoods. - This not only avoids the assertions in the tests, but also having - to add extra test only accessors to the original code. - If you catch yourself adding such accessors, called "state based testing", - it's probably time to consider using mocks in the tests. - This is called "behaviour based testing", and is normally superior. + I test senza assert sono sia compatti che molto espressivi. + Siccome la chiamata viene intercettata mentre arriva dall'interno dell'oggetto, in questo + caso della classe <code>Alert</code>, non c'\xE8 il bisogno di dichiarare alcun assert sul suo + stato. + Non solo questo evita gli assert nei test ma anche la necessit\xE0 di aggiungere + altri accessor al codice originale. + Nel caso ci si dovesse scoprire ad aggiungere accessor al codice, cio\xE8 quelli che + comunemente vengono chiamati "state based testing", potrebbe essere il momento di + considerare l'uso dei mock nei propri test. + Quest'ultimo approccio \xE8 chiamato "behaviour based testing" ed \xE8 normalmente considerato + migliore rispetto all'uso degli accessor. </p> <p> - Let's add another test. - Let's make sure that we don't even attempt a payment without a CVV2... + Aggiungiamo un altro test. + Assicuriamoci che non si riesca nemmeno a tentare un pagamento in assenza del codice CVV2: <php><![CDATA[ class PaymentFormFailuresShouldBeGraceful extends UnitTestCase { @@ -597,17 +617,17 @@ ... } ]]></php> - Asserting a negative can be very hard in tests, but - <code>expectNever()</code> makes it easy. + Nei test pu\xF2 risultare molto difficile realizzare l'assert di una condizione negativa + ma il metodo <code>expectNever()</code> rende l'operazione semplice: </p> <p> - <code>expectOnce()</code> and <code>expectNever()</code> are - sufficient for most tests, but - occasionally you want to test multiple events. - Normally for usability purposes we want all missing fields - in the form to light up, not just the first one. - This means that we should get multiple calls to - <code>Alert::warn()</code>, not just one... + <code>expectOnce()</code> e <code>expectNever()</code> sono pi\xF9 che sufficienti + per la maggior parte dei test ma, occasionalmente, si potrebbe aver bisogno di + collaudare pi\xF9 eventi. + Normalmente, a vantaggio dell'usabilit\xE0, si vuole che vengano evidenziati tutti i campi + non compilati del form e non solo il primo. + Allo scopo dovremmo essere in grado di eseguire chiamate multiple + a <code>Alert::warn()</code> e non solo una: <php><![CDATA[ function testAllRequiredFieldsHighlightedOnEmptyRequest() { $alert = new MockAlert();<strong> @@ -623,92 +643,93 @@ $controller->makePayment($this->requestWithMissingCvv2()); } ]]></php> - The counter in <code>expectAt()</code> is the number of times - the method has been called already. - Here we are asserting that every field will be highlighted. + Il contatore presente in <code>expectAt()</code> rappresenta il numero + di volte per il quale il metodo \xE8 gi\xE0 stato invocato. + Qui si sta eseguendo un assert per ogni campo che verr\xE0 evidenziato. </p> <p> - Note that we are forced to assert the order too. - SimpleTest does not yet have a way to avoid this, but - this will be fixed in future versions. + Si noti che siamo costretti a valutare anche l'ordine delle chiamate. + SimpleTest non prevede ancora un sistema per evitare questo inconveniente + ma lo preveder\xE0 nelle prossime versioni. </p> <p> - Here is the full list of expectations you can set on a mock object - in <a href="http://simpletest.org/">SimpleTest</a>. - As with the assertions, these methods take an optional failure message. + Di seguito \xE8 riportato un elenco delle expectation utilizzabili su un + oggetto mock in <a href="http://simpletest.org/">SimpleTest</a>. + Cos\xEC come per gli assert, questi metodi accettano un parametro opzionale + con il messaggio di failure. <table> - <thead><tr><th>Expectation</th><th>Description</th></tr></thead> + <thead><tr><th>Expectation</th><th>Descrizione</th></tr></thead> <tbody> <tr> <td><code>expect($method, $args)</code></td> - <td>Arguments must match if called</td> + <td>Nel caso il metodo venga invocato, gli argomenti devono corrispondere a quanto dichiarato</td> </tr> <tr> <td><code>expectAt($timing, $method, $args)</code></td> - <td>Arguments must match when called on the <code>$timing</code>'th time</td> + <td>Gli argomenti devono corrispondere alla <code>$timing</code>-esima chiamata</td> </tr> <tr> <td><code>expectCallCount($method, $count)</code></td> - <td>The method must be called exactly this many times</td> + <td>Il metodo deve essere invocato esattamente <code>$count</code> volte</td> </tr> <tr> <td><code>expectMaximumCallCount($method, $count)</code></td> - <td>Call this method no more than <code>$count</code> times</td> + <td>Il metodo deve essere invocato non pi\xF9 di <code>$count</code> volte</td> </tr> <tr> <td><code>expectMinimumCallCount($method, $count)</code></td> - <td>Must be called at least <code>$count</code> times</td> + <td>Il metodo deve essere invocato almeno <code>$count</code> volte</td> </tr> <tr> <td><code>expectNever($method)</code></td> - <td>Must never be called</td> + <td>Il metodo non deve essere mai invocato</td> </tr> <tr> <td><code>expectOnce($method, $args)</code></td> - <td>Must be called once and with the expected arguments if supplied</td> + <td>Il metodo deve essere invocato una sola volta e con i parametri indicati</td> </tr> <tr> <td><code>expectAtLeastOnce($method, $args)</code></td> - <td>Must be called at least once, and always with any expected arguments</td> + <td>Il metodo deve essere invocato almeno una volta e con i parametri indicati</td> </tr> </tbody> </table> - Where the parameters are... + I parametri sono: <dl> <dt class="new_code">$method</dt> - <dd>The method name, as a string, to apply the condition to.</dd> + <dd>La stringa con il nome del metodo al quale applicare la condizione.</dd> <dt class="new_code">$args</dt> <dd> - The arguments as a list. Wildcards can be included in the same - manner as for <code>setReturn()</code>. - This argument is optional for <code>expectOnce()</code> - and <code>expectAtLeastOnce()</code>. + L'elenco degli argomenti. E' possibile utilizzare i caratteri jolly allo + stesso modo in cui si utilizzano con <code>setReturn()</code>. + Questo argomento \xE8 opzionale in <code>expectOnce()</code> + e in <code>expectAtLeastOnce()</code>. </dd> <dt class="new_code">$timing</dt> <dd> - The only point in time to test the condition. - The first call starts at zero and the count is for - each method independently. + L'istante in cui valutare la consizione. + La prima chiamata inizia con 0 ed i conteggi delle chiamate ai vari + metodi sono indipendenti tra loro. </dd> <dt class="new_code">$count</dt> - <dd>The number of calls expected.</dd> + <dd>Il numero di invocazioni attese</dd> </dl> </p> <p> - If you have just one call in your test, make sure you're using - <code>expectOnce</code>.<br /> - ... [truncated message content] |