AntonioGanci

Il blog di Antonio Ganci
posts - 201, comments - 420, trackbacks - 31

Un tecnica per testare l'interazione tra oggetti

Ogni tanto, nello sviluppo software, emerge qualche meme come ad esempio: tutte le dipendenze devono essere disaccoppiate tramite un interface, tutte gli oggetti devono essere creati tramite factory, l'accesso ad un database deve avvenire tramite un ORM, il TDD genera un buon design ecc.

Cosa hanno in comune tutte le frasi precedenti? Semplice: creano scorciatoie per evitare di pensare. Sarebbe bello se potessimo scrivere codice seguendo alla lettera un manuale, ma sarebbe anche terribilmente noioso e probabilmente verremmo sostituiti da qualche tipo di bot.

Prendiamo la prima affermazione: tutte le dipendenze devono essere disaccoppiate tramite un interface e cerchiamo di capire da dove nasce questa esigenza. Il vantaggio di avere le dipendenze solo tramite interfacce dovrebbe essere quello di rendere più testabile le nostre classi. Ma è l'unico modo? Ed è il più semplice?

Proviamo a fare un esempio. Supponiamo di voler testare il metodo SayHello:

var display = new Display();
var greeting = new Greeting(display);
greeting.SayHello();

L'implementazione di Greeting è la seguente:

public class Greeting
{
    private readonly Display _display;

    public Greeting(Display display)
    {
        _display = display;
    }

    public void SayHello()
    {
        _display.Show("Hello!");
    }
}

Mentre l'implementazione di display è la seguente:

public class Display
{
    public void Show(string text)
    {
        Console.WriteLine(text);
    }
}

Sembra proprio il tipico esempio da manuale in cui si estrae l'interfaccia IDisplay e tramite la libreria di mocking preferita testo le interazioni di Greeting con Display. Esiste un'alternativa?

La classe Console eredita da TextWriter, anche la classe StringWriter eredita da TextWriter. Proviamo quindi a passare la Console in costruzione a Display:

public class Display
{
    private readonly TextWriter _textWriter;

    public Display(TextWriter textWriter)
    {
        _textWriter = textWriter;
    }

    public void Show(string text)
    {
        _textWriter.WriteLine(text);
    }
}

Ora modfichiamo il main:

var display = new Display(Console.Out);
var greeting = new Greeting(display);
greeting.SayHello();

A questo punto possiamo scrivere il test:

var stringWriter = new StringWriter();
var greeting = new Greeting(new Display(stringWriter));

greeting.SayHello();

Assert.That(stringWriter.ToString(), Is.EqualTo("Hello!"));

In questo modo abbiamo fatto un test più solido rispetto a testare l'interazione con un interfaccia ed il codice è più semplice.

Print | posted on lunedì 6 settembre 2010 11:54 | Filed Under [ Tips Extreme Programming ]

Feedback

Gravatar

# re: Un tecnica per testare l'interazione tra oggetti

x Luca: carina la storia che hai linkato :-).
Se avessi due tipi di display e Greetings usasse uno o l'altro in base al contesto allora l'interfaccia sarebbe una buona soluzione altrimenti mi accontento.
Comunque sto rivalutando i test end-to-end cioè non testare unitariamente tutte le classi perchè questo comporta extra lavoro durante il refactoring.

x Jacopo:
Diciamo che i test unitari li sto scrivendo sempre meno e ne vedo sempre meno l'utilità.
07/09/2010 11:53 | Antonio Ganci
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET