Kontrakty a unit testy

Jak se změní svět unit testování, když začneme používat kontrakty?

Pokud to myslíte s unit testy, potažmo TDD, opravdu velmi vážně, pak by pro vás neměla být následující ukázka překvapivá.

    public class Rectangle
    {
        public Rectangle(int width, int height)
        {
            this.Width = width;
            this.Height = height;
        }

        public int Width { get; private set; }
        public int Height { get; private set; }
    }	

	[TestFixture]
	public class RectangeTest
	{
		[Test]
		public void Fields_Of_Rectangle_Are_Assigned()
		{
			var r = new Rectangle(3, 4);
			Assert.AreEqual(3, r.Width);
			Assert.AreEqual(4, r.Height);
		}
	}

I ve dvou přiřazeních v konstruktoru se dá teoreticky udělat chyba, třeba je někdo může omylem prohodit. Podívejte se ale pozorně na výše uvedený test. Přijde vám na něm něco zvláštního? Napsat takový test je naprosto rutinní záležitost, možná bychom měli přenechat dřinu strojům…

Kontrakty na scénu

Výsledkem volání uvedeného konstruktoru, není nic, co by se nedalo popsat jednoduchou podmínkou. Oproti tomu, pokud máme implementovat metodu, co má v zadaném grafu najít nejkratší cestu, těžko popíšeme výsledek vzhledem k vstupním datům, to bychom museli pro ověření správnosti výsledku výsledek znovu vypočítat — nebo-li definice kruhem. Zpět k obdélníku. Podívejme se na verzi s kontrakty pro post-condition (=podmínky, co mají platit po provedení metody).

    public class Rectangle
    {
        public Rectangle(int width, int height)
        {
            Contract.Ensures(this.Width == width);
            Contract.Ensures(this.Height == height);

            this.Width = width;
            this.Height = height;
        }

         // ...
    }

V podstatě jsme zapsali to samé, co v unit testu, ale přehledněji, čistě deklarativně a v kódu „testované“ třídy. Nicméně, v této verzi unit test chybí. Může tohle standardní milovník TDD akceptovat, aniž by autorovi tohoto kódu vyhlásil džihád? Odpověď je ano, může! Pokud máte nainstalované Code Contracts, zkuste prohodit width a height v přiřazovacích příkazech. Statická kontrola vám po kompilaci ihned ukáže chybu, protože za nás v podstatě udělala ten nudný unit-test z úvodu. Dokonce víc. Code Contracts provedly (logický) důkaz, že kód je správně. Takže nechme dřinu strojům a soustřeďme se na testování opravdu složitého kódu, který nelze ověřit statickou analýzou, třeba to hledání nejkratší cesty v grafu.

Co si myslíte o nahrazení unit-testů odpovídajícími kontrakty vy?

Disclaimer: Code Contracts mají v současné verzi svoje mouchy. Syntaxe by taky mohla být hezčí. Prodloužená doba kompilace při použití Contracts se nemusí líbit každému. Ano unit-testování přiřazovacích příkazů, stejně jako psaní post-conditions pro jejich ověření, se může někomu jevit jako zbytečnost. :-)

Post a Comment

Your email is never published nor shared. Required fields are marked *