.NET & Software Testing
Andrea Saltarello
Software Architect – Managed Designs S.r.l.
http://blogs.ugidotnet.org/pape
Sponsor
Parliamo di…
•
•
•
•
Design/Test/Interaction patterns
Unit Testing
Mock Objects
Visual Studio 2005
If it ain’t tested, it’s broken
(cit. Bruce Eckel)
Software Testing 101
Possiamo dichiarare funzionante il nostro software
solo se siamo in grado di dimostrarlo
Il funzionamento si dimostra mediante appositi test
Utilizzare un software non è considerabile una
pratica di test (AntiPattern TestByReleasing,
TestingByPokingAround, …)
Tipologie di test
Esistono differenti tipologie di test:
• Programmer Test/Technology facing (definiti
anche unit test)
• Customer Test/Business facing (definiti anche
acceptance test o functional test)
• Stress/Load Test
• Usage Test
• …
Noi parleremo di Unit Testing
Unit Testing 101
Lo Unit Testing è una tipologia di test automatico,
basata sulla possibilità di sottoporre a test i
singoli componenti di un sistema per verificarne
la capacità di soddisfare i requisiti.
I suddetti test sono definiti “unitari”, e sono
programmi batch che utilizzano le nostre classi
inviando messaggi prefissati in modo da poter
verificare la risposta della classe stessa
Toolkit di Unit Testing
Esistono (almeno) 2 affermati toolkit di unit
testing per .NET, entrambi ispirati alla suite
xUnit ideata da Kent Beck ed Erich
Gamma:
• NUnit
• csUnit
…Noi usiamo NUnit
NUnit 101
NUnit è composto da un assembly
(contenente il framework di unit testing) e
da una applicazione host in grado di
eseguire i test e produrre un report. Per
realizzare i test:
• Creare una class library che conterrà i test
• Definire una classe, e implementare i test sotto forma
di metodi
• Decorare i metodi di test con l’attributo TestAttribute
• Decorare la classe che contiene i test con l’attributo
TestFixture
• Eseguire l’assembly dei test mediante l’applicazione
host
Unit Testing - Asserzioni
Pratica comune nello unit testing è avvalersi delle
asserzioni, ossia della capacità di definire delle
condizioni che verificano la correttezza di
funzionamento del codice in esame
NUnit permette di definire delle asserzioni
mediante la classe Assert
Se l’asserzione non è soddisfatta, il test fallisce
[Test]
public void TestSum()
{
int number = 4;
Assert.AreEqual(2, (int) Math.Round(number));
}
NUnit: un assembly con gli “Attributi”
La libreria contiene differenti attributi, tra i quali:
•
•
•
•
•
•
TestFixture
Test
SetUp
TearDown
ExpectedException
Ignore
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void TestSum()
{
int number = int.Parse(null);
}
Houston, abbiamo un
problema!
• Il test unitario insiste su uno specifico
componente
• Un componente interagisce con altri componenti,
eventualmente residenti su layer differenti
• Il fallimento di un componente esterno può
provocare il fallimento di un test
Può essere conveniente isolare il componente
sottoposto a test
Isolare un componente
Esistono alcuni pattern specifici, ispirati allo
Special Case:
• Stub/Shunt
• Fake Objects
• Mock Objects
Diamo anche una occhiata ad Inversion of
Control (a.k.a. Dependency Injection)
Stub/Shunt
The most simple implementation of an
interface. Tipically, one might implement
every method call by throwing a runtime
exception.
Fake Object
A class with methods that return a fixed
value or values that can either be
hardcoded or set programmatically
Mock Objects
An object which, in addition to implementing
the interface (like a Stub/Shunt) and
returning meaningful values (like a Fake),
allows for verification that the correct calls
were made upon the object, perhaps in the
correct order.
Creare Mock Object
Esistono toolkit free appositi:
• DotNetMock
• NMock
…Noi usiamo NMock
NMock
La classe DynamicMock:
• usa CodeDom e Reflection per creare
dinamicamente un Mock Object
DynamicMock mockGenerator = new DynamicMock(typeof(RealObjectType));
RealObjectType mockObject = (RealObjectType) mockGenerator.MockInstance;
• Permette di “istruire” il Mock mediante metodi
quali SetupResult e ExpectAndReturn
mockGenerator.SetupResult(“MethodName”, 42, new Type[]{});
int result = mockObject.MethodName();
Fake vs. Mock
Secondo Ward Cunningham, dovremmo preferire un Mock se:
1. real object has non-deterministic behavior
2. real object is difficult to set up
3. real object has behavior that is hard to cause (e.g., network error)
(similar to 1)
4. real object is slow
5. real object has (or is) a UI
6. test needs to query the object, but the queries are not available in
the real object (e.g., "was this callback called?")
7. real object acts "normal" most of the time, but once a month (or
even less often) it does something "exceptional". We want UnitTests
to make sure the rest of the system does the RightThing whether or
not the object is acting "normal" or "exceptional". (Is this the same
as #2 ?)
8. real object does not yet exist
Ritorno al Futuro: Visual
Studio 2005
I Team System di Visual Studio 2005
includono un toolkit di unit testing:
• Strepitosamente simile a NUnit (Indovinello:
dove lavora oggi James Newkirk, ex project
leader di NUnit? )
• Dotato di funzionalità di code coverage
Riferimenti
Tools:
• NUnit http://www.nunit.org
• csUnit http://www.csunit.org
• NMock http://www.nmock.org
• DotNetMock http://dotnetmock.sourceforge.net
• TestDriven.NET http://www.testdriven.net
Documentazione:
• NUnit vs. Team System
• Mocks Aren't Stubs
• Mock Stub Shunt
• Mock Objects to the Rescue!
Links
http://www.ugidotnet.org
http://forum.ugidotnet.org
http://mobile.ugidotnet.org
Scarica

.NET & Software Testing