Läsbara tester med extension methods

Skriv en kommentar
8 maj 2009 23:11

Som jag nämnde i mitt senaste inlägg

kan vi enkelt skapa mer läsbara tester genom att använda oss av extension methods. Vad vi vill uppnå med dessa metoder är ett sätt att slippa skriva våra vanliga verifieringar enligt följande:

Assert.AreEqual(1000.0, order.TotalAmount());
Istället vill vi få till en läsbar verifering enligt följande:

totalAmount.ShouldEqual(1000);

nBehave har en bra klass med extension methods att utgå ifrån. S#arp Architecture

har anammat samma approach, men har samtidigt lagt till några mer specifika metoder som exempelvis följande:

public static void ShouldEqualSqlDate(this DateTime actual, DateTime expected)
{
    TimeSpan timeSpan = actual – expected;
    Assert.Less(Math.Abs(timeSpan.TotalMilliseconds), 3);
}

och

public static void ShouldContainErrorMessage(this Exception exception, string expected){
    StringAssert.Contains(expected, exception.Message);
}

Som ni ser är metoderna väldigt enkla att skapa själv. Vi kan exempelvis skapa en läsbar verifiering av ett värde med två decimaler enligt följande:

using NUnit.Framework;

namespace
ExtensionMethods

{
    public static class TestExtensions
    {
        public static void ShouldEqualRoundedValue(this double
       
actual, double
expected)
        {
            // 0.005 är deltat
            Assert.AreEqual(expected, actual, 0.005);
        }
    }
}

Självklart ska vi även testa våra egna veriferingsmetoder:

using NUnit.Framework;

namespace
ExtensionMethods
{
    [TestFixture]
    public class ShouldEqualRoundedValueTests
    {

        [Test]
        public void CanRoundCorrectWhenRoundingDown()
        {
            const double amount = 100.124;
            amount.ShouldEqualRoundedValue(100.12);
        }


        [
Test]
        public void CanRoundCorrectWhenRoundingUp()
        {
            const double amount = 100.126;
            amount.ShouldEqualRoundedValue(100.13);
        }


        [
Test]
        public void CanRoundCorrectWhenInBetween()
        {
            const double amount = 100.125;
            amount.ShouldEqualRoundedValue(100.13);

        }

        [Test]
        public void CanRoundAmountCorrectWhenAssertFails()
        {
            const double amount = 100.125;

            try
           
{
                amount.ShouldEqualRoundedValue(100.14);
                Assert.Fail(”The test should fail!”);
            }
            catch (AssertionException exc)

            {
                Assert.AreNotEqual(”The test should fail!”,
                exc.Message);
            }
        }

    }
}


Snygg och enkel verifiering!

Introduktion till MSpec

1 kommentar
1 maj 2009 10:09

För några veckor sedan var jag nere på Developer Summit som anordnas årligen av Cornerstone (bildbevis hittar ni här). I en av presentationerna visade Scott Bellware hur man kan använda Behaviour-Driven Design (BDD) tillsammans med Machine Specifications

, även kallat Mspec (Ytterligare information finns här och källkoden till MSpec hittar ni här).

BDD integrerar tankar från Test Driven Design (TDD) och Domain Driver Design

 och försöker överbrygga skillnaden i hur ett system uppfattas av användare och utvecklare. Genom att använda ett gemensamt vokabulär minimeras översättningen mellan det tekniska språk som koden är skriven i och det domämnspråk som verksamhet och projektledning använder. Fokus ligger på varför koden ska skapas, snarare än de tekniska detaljerna.

En sak som Scott tryckte på i sin presentation var hur svårt det är att använda vanliga enhetstester som dokumentation av vår kod. När vi som utvecklare läser igenom enhetstester för att få en första introduktion till produktionkodens beteende, visar undersökningar att vi enbart läser koden i början på varje rad och därmed missar det viktigaste. För dagens testramverk bygger ju på veriferingar liknande denna:

Assert.AreEqual(1000.0, order.TotalAmount());
Vår verifiering döljs alltså i slutet av anropet till en assert. Har vi med en kommentar blir det ännu svårare att se verifieringen:

Assert.AreEqual(1000.0, order.TotalAmount(), ”Total amount incorrect!”);
Denna läsbarhetsbrist undanröjer MSpec, samtidigt som det använder BDD för att klargöra beteendet av koden under test:

[Subject(typeof(Order))]
public class when_summarizing_order_line_amounts_with_
two_order_lines_with_amount_1000_and_amount_2000

{
    Establish context = () =>
    {
        order.OrderLines.Add(new OrderLine(1000M));
        order.OrderLines.Add(new OrderLine(2000M));
    };

    Because of = () => 
        totalAmount = order.TotalAmount();

    It
should_sum_the_order_amount_to_3000 = () => 
        totalAmount.ShouldEqual(3000);
    
   
private
static readonly Order order = new Order
();
    private static decimal totalAmount;
}


Som ni ser grundar sig MSpec på att varje test skrivs som en egen klass. Detta kan tyckas vara en liten skillnad, men personligen var det svårare än väntat att ta till sig. Klassnamnet skrivs med små bokstäver och ska kunna läsas som en mening som beskriver initialtillståndet för testet. Viktigt är att verbet, dvs det som ska utföras, kommer tidigt i klassnamnet, helst redan som andra ordet. Genom att ha verbet tidigt i klassnamnet ökar vi läsbarheten och därmed förståelsen om varför testet skapades.

Testet skapar först ett kontext (Establish context), anropar produktionskoden (Because of) och verifierar slutliges dess utfall (It should_sum_the_order_amount_to_3000). MSpec grundar sig på användning av lambdauttryck och även om det kan tyckas svårt att läsa koden, blir det snabbt ett naturligt arbetssätt. Som ni ser används inga assertmetoder för att verifiera utfallet, utan istället används extension methods (totalAmount.ShouldEqual(3000)) för att göra verifieringen direkt på den variabel eller egenskap som håller utfallet. Detta underlättar läsbarheten eftersom det blir naturligt att läsa ut veriferingen direkt ur koden. Intressant att notera är att MSpec i grunden använder NUnit‘s assertmetoder när ett testutfall verifieras.

Tester skrivna med MSpec går att exekvera direkt i Visual Studio via plugins för både ReSharper och TestDriven.Net. När tester exekveras med hjälp av TestDriven.Net, skapas det en läsbar dokumentation i output-fönstret. För ovanstående test blir det följande output:

Order, when summarizing order line amounts with two order lines with amount 1000 and amount 2000
» should sum the order amount to 3000

Denna dokumentation går också att få ut som en HTML-fil om man använder den medföljande testexekveringsmotorn, men jag hittade vid mina försök inget sätt att göra detta direkt via TestDriven.Net. Någon som vet hur man får ut filen direkt med TestDriven.Net? Dokumentationen som skapas från den specifika MSpec-motorn ser annars ut så här

.

För att öka användbarheten av dokumentationen bör vi undvika att blanda in tekniska termer i de texter som kommer som output från testerna. En dokumentation som enbart använder domänspråket kan användas av alla parter i utvecklingsprojektet.

Scott har ett antal poänger i sina påpekanden om att våra tester är en svårläst dokumentation. Genom att använda MSpec och grundtankarna hos BDD kan vi få mer lättlästa tester. Däremot krävs det en viss mognad hos utvecklingsteamet för att kunna ta till sig arbetssättet och det sätt som testerna skrivs på.

Om man inte vill använda MSpec, kan man ändå skapa mer läsbara tester genom att utöka sitt befintliga testramverks verifieringsmetoder med extension methods. Detta finns exempelvis redan med som en del av ramverket S#arp Architecture, men kan även åstadkommas enkelt med egen kod. Jag kommer i ett kommande blogginlägg att beskriva hur man gör detta.

 

Dokumentera mindre men bättre

2 kommentarer
6 mars 2009 11:22

Vi utvecklare tycker om att skriva kod, men att skriva dokumentation brukar inte vara speciellt uppskattat. I början går det väl an, men när man suttit och skrivit en hel dag börjar det ta emot.

Att skriva en bra dokumentation är inte heller helt enkelt. För, vad är det egentligen vi ska dokumentera? Om vi skriver en systemdokumentation vill vi inte ha några ingående kodbeskrivningar, utan snarare fånga de mer övergripande idéerna, inre och yttre beroenden, loggning etc.

Hur ska vi då dokumentera vår kod? I långa svårlästa dokument som ingen bryr sig om att varken läsa eller uppdatera? Spontant tycker jag att kod ska dokumenteras i kod. Det är den som utvecklaren läser och förstår.

När koden dokumenteras är det inte hur vi har löst problemet vi ska beskriva, för det ska ju koden visa, utan våra kommentarer ska fokusera på varför vi har löst problemet på det sätt som vi har gjort. Dokumentationen ska också innehålla kända begränsningar så att kommande utvecklare slipper hitta dem den hårda vägen. Visst vore det också bra om vi även kunde få den att uppdatera sig själv?

Om vi är disciplinerade och skriver våra enhetstester kommer vi faktiskt att komma rätt nära denna ideala dokumentation, åtminstone för delar av systemet. Enhetstesterna definierar och dokumenterar funktionaliteten för vår produktionskod och ger en grundläggande förståelse för hur dess gränssnitt är tänkt att användas. De visar med hjälp av negativa testfall vår produktionskods begränsningar, men även vilka extremfall vi har.

När testerna går igenom är även dokumentationen verifierad och det bästa av allt, vår dokumentation är alltid uppdaterad! Ler

Så, nästa gång ni harvar med era trista dokument, se till att utelämna detaljerna och låt era enhetstester bli en levande dokumentation istället.

Detta var det sista inlägget i en serie om varför vi ska enhetstesta.

Testa enklare

Skriv en kommentar
4 mars 2009 13:18

Ett enhetstest är i sin vanligaste form en enkel och trivsam bekantskap. Inga komplexa relationer eller stora otympliga kodmassor. Även de tester som blir lite mer komplicerade bör fortfarande vara  avgränsade och överskådliga.

Om vi däremot blir tvungna att testa vår kod via en applikation bestående av flera lager, måste vi inte bara starta alla våra lager via utvecklingsmiljön, vi måste också börja klicka oss fram i applikationen tills vi når användargränsnittet som anropar den lilla kodsnutt vi är intresserade av att testa. Vi måste alltså köra vår produktionskod hela vägen, även om vi bara vill testa en liten kodsnutt längst ner i anropskedjan. Inte särskilt effektivt, eller hur? Det är inte ens säkert att vi enkelt kan åstadkomma en situation där vi från applikationen kan nå den kod vi vill testa. Och hur ska vi kunna testa av alla extremfall? Nej, att testa vår kod via applikationen är inte att föredra.

Genom att använda enhetstester kan vi enkelt testa vår produktionskod, flera gånger om på bara några sekunder. Vi kan alltså köra en hel grupp av tester på mindre tid än det tar att få igång vår flerlagersapplikation. Det enda som krävs är att vår kod kompilerar.

Vi kan även testa komplexa datadrivna tester utan att exv. anropa databasen. Vi behöver därmed inte skapa en massa testdata i vår databas för att kunna komma fram till ett testresultat. Istället använder vi mockade objekt som simulerar våra kopplade objekt. För datadrivna tester sparar vi mycket tid om vi använder enhetstester istället för att testa via applikationen.

Skulle det krävas går det också enkelt att debugga ett enhetstest. Det räcker med att sätta en brytpunkt och starta enhetstestet i debugläge.

Vi inser rätt snabbt att det är smidigt, men framförallt tidseffektivt, att skapa enhetstester för att testa vår kod. När testerna väl finns kan vi dessutom köra dem om och om igen med enbart en minimal tidskostnad.

Om vi använder enhetstester blir vårt testande så mycket enklare och därmed också roligare, och vem vill inte ha roligt på jobbet? Ler

Positiva designeffekter

Skriv en kommentar
2 mars 2009 13:21

För att produktionskoden ska bli testbar måste den designas med det i åtanke. Vi kommer framöver att diskutera detta ämne mer ingående, men redan nu tänkte jag peka på några positiva designeffekter vi får om vi skriver vår kod utifrån ambitionen att den ska vara testbar.

Klasser måste skrivas konfigurerbara
Det går inte längre att ha hårdkodade värden i klasserna. Alla parametrar som påverkar funktionaliteten måste kunna sättas utifrån, annars kommer inte testerna att kunna testa alla flöden och möjliga varianter.

Fler interfaces och fabriker
En klass kan inte längre skapa sina relaterade objekt internt, utan de måste komma utifrån. Om vi binder implementationen internt mot en specifik klass kommer vi aldrig att kunna testa relationerna med denna. Vi kommer inte heller att kunna förvalta och förädla vår produktionskod på ett enkelt sätt. Detta är mycket viktigt att ha i åtanke.

Istället bör vi jobba mot interface som tvingar oss att skicka in instanserna utifrån. Detta är en form av dependency injection. Genom att skicka in speciella testobjekt kan vi  verifiera relationerna på ett enkelt sätt. Det finns färdiga ramverk att använda för att sätta upp våra testobjekt, exv Rhino Mocks och Moq. Jag kommer i kommande inlägg visa hur enkelt det är att använda dessa ramverk.

När vi testar relationerna mellan objekt utgår vi alltid från antagandet att alla relaterade objekt fungerar korrekt. Det är inte de relaterade objekten som ska testas, utan den specifika klassens interaktion med dem.

För att centralisera och förenkla hanteringen kan det underlätta att använda fabriker som skapar instanser av våra objekt.

Mindre och mer specifika metoder
För att få bra testbarhet får inte våra metoder vara för långa och komplexa. Det blir då helt omöjligt att skriva bra och små tester som täcker vår funktionalitet. Därför faller det sig naturligt att dela upp våra metoder i små koncentrerade delar där varje metod har ett specifikt syfte. På köpet får vi en samling av metoder som vi kan kombinera till att realisera nya funktioner.

API’t är redan använt en gång
När vi skriver våra tester använder vi det API som produktionskoden senare kommer att nyttja. Våra enhetstester kommer att visa om API’t är lätthanterligt och intuitivt.

Känner ni igen ovanstående påståenden? Jag hoppas det iallafall. De är vanliga enkla regler för design av bra kod. De hjälper oss att skapa en konfigurerbar, öppen och lättförståelig design.

Det är alltså ingen skillnad mellan att skriva testbar kod och att att skriva bra och underhållsvänlig kod.

Refaktorera tryggt

Skriv en kommentar
27 februari 2009 09:47

Refaktorering syftar till att öka kvalitén på vår kod utan att förändra dess funktion. Därmed räknas inte en ombyggnad som medför ett förändrat gränssnitt som en refaktorering, även om man ibland kan benämna detta som en brytande refaktorering. Inte heller anses felrättning vara refaktorering.

Refaktoreringens huvudsyfte är att säkerställa att vår applikation går att underhålla, förändra och optimera för prestanda.

Begreppet designskuld dyker ofta upp i samband med refaktorering. Allt eftersom vi i ett projekt lär känna kundens behov och hittar mönster och arbetssätt kommer den äldre koden att förfalla mer och mer och skapa vår designskuld. Designskulden uppstår så fort vi börjar skriva vår kod och följer med oss genom hela applikationens livslängd.  Det är därför nödvändigt att vara alert och alltid refaktorera kod som inte längre håller måttet. För att refaktoreringen ska bli utförd måste den ske direkt när vi ser en potentiell förbättring och därmed blir refaktorering en viktig del av vårt dagliga arbete.

Nära relaterat till designskuld är begreppet code smell som är det synliga symptomet på att vår designskuld måste åtgärdas.

Refaktorering kan vara en farlig operation att utföra om vi inte på ett enkelt sätt kan verifiera att vår produktsionskod fortfarande har det beteende som vi förväntar oss. Här är en bra testsvit guld värd! Även om vi inte kan garantera att vår testsvit är heltäckande och fångar alla fel som kan uppkomma, kommer den att fånga många av de småfel som vi enkelt introducerar i och med en refaktorering. Åter igen, skriv testerna tillsammans med produktionskoden för att skapa en bra testsvit att tillgå när den behövs.

Skulle vi sakna enhetstester kan det kännas enklare och tryggare att hoppa över nödvändiga refaktoreringar och låta koden förfalla. Detta är ett skräckcenario som vi till varje pris måste undvika! En applikation som förfaller blir till sist en koloss som inte går att styra och därmed en mycket dyr investering för vår kund. När vår kund inser detta blir han/hon inte glad och en irriterad kund är aldrig någon bra kund.

Men, även om vi skulle sakna en bra testsvit måste vi kunna refaktorera koden. Nyligen hamnade jag i just den situationen. Jag skulle refaktorera en del av en applikation som var skriven av en annan utvecklare och det fanns inga enhetstester som jag kunde luta mig mot. Innan jag påbörjade mitt refaktoreringsarbete skrev jag därför en grupp tester som gick mot den gamla koden. När alla testerna gick igenom och jag kände att testerna täckte funktionaliteten gjorde jag min refaktorering. Efteråt använde jag mina tester för att verifiera att min refaktorering hade uppnått mitt tänkta resultat, dvs att koden fått en bättre implementation utan att förändra dess beteende utåt.

Vid ett annat tillfälle hade jag samma problem, dvs det fanns inga tester som kunde verifiera funktionaliteten, och jag började därför med att försöka få en så komplett testsvit som möjligt. Jag gjorde därefter min refaktorering och till min förvåning fallerade hälften av mina tester. Det visade sig att jag när jag hade delat en större metod i två mindre, hade jag i anropet till en av de nya metoderna kastat om ordningen på två indataparametrar. Ett fel som jag hade haft mycket svårt att hitta genom att testa via applikationen, men som mina enkla testfall hittade direkt. Ler

Om vi känner oss trygga vid vår refaktorering vågar vi göra nödvändiga förbättringar som ökar applikationens livslängd. Väljer vi att avstå helt från att refaktorera har vi valt en väg som leder åt helt fel håll, eller som Mark Burhop lär ha uttryckt det:

Code, left untouched, will develop bugs

Felrättning är tidsödande

Skriv en kommentar
24 februari 2009 08:31

Felrättning kan vara ett tidsödande arbete. Oftast är det inte själva rättningen i sig som tar mest tid, utan snarare arbetet med att hitta och senare verifiera felet. Har vi otur inför vi samtidigt nya fel som vi inte upptäcker på grund av otillräcklig testning.

Genom att använda enhetstester som en naturlig del av vår felrättning kan vi minska tiden för själva felrättningen och samtidigt minska risken för uppkomst av nya fel.

Felrättning genomförs i fyra enkla steg:

1. Lokalisera var felet är beläget och skriv minst ett enhetstest som verifierar felet genom att simulera situationen som orsakade det. Om felet har verifierats korrekt ska testet fallera.
2. Rätta felet i produktionskoden.
3. Kör samma enhetstest igen och verifiera att felet är rättat. Nu ska enhetstestet gå igenom.
4. Kör hela testsviten för att minimera risken att rättningen skapade oönskade effekter.

Som ni ser kan vi uppnå verifiering av felet och verifiering av rättningen med samma enhetstest! Som bonus verifierar resterande testsvit att vi inte har introducerat några nya fel i och med vår rättning. Vi kan alltså uppnå en hög testningsgrad med väldigt lite arbete.

Jag förändrade mitt arbetssätt radikalt när jag började använda enhetstestning som ett verktyg för felrättning. Enhetstesterna gjorde att jag till stor del slapp det tidsödande arbetet med att försöka återskapa ett fel via applikationens användargränssnitt. Om vi utifrån exv ett felmeddelande i en applikationslogg (för ni har väl en loggningsfunktion?) kan isolera i vilken del av applikationen felet ligger, kan vi börja att skriva enhetstesterna där.

Jag rekommenderar att vi som en sista verifiering exekverar det flöde som först påvisade felet. Därmed säkerställer vi att vi inte har missat några andra fel och slipper samtidigt skämmas inför våra testare/kunder för att vi missade uppenbara följdfel. Hittar vi fler fel, startar vi vår felrättningsprocess igen.

Varje nytt enhetstest vi tillför skapar en bättre och mer täckande testsvit. Enhetstester som verifierar uppkomna fel brukar också ha ett stort testvärde, eftersom felen ofta har upptäckts av någon med kunskap om hur applikationen verkligen är tänkt att fungera.

Snabb återkoppling är viktig

Skriv en kommentar
18 februari 2009 15:12

Om vi gör som vana att alltid skriva tester i samband med att vi skriver vår produktionskod (antingen före eller efter), får vi direkt indikation på om vår produktionskod har det beteende vi förväntar oss. För att vi ska kunna komma till denna slutsats krävs det att vi utifrån specifikationen skriver testfall över tänkt funktionalitet, samt ser till att utöka testerna för att täcka specifika implementationsdetaljer.

Skulle vi inte testa vår produktionskod i  samband med att den skrivs, fördröjer vi vår testning och försvårar därmed både felsökning och rättning. Det är mycket lättare att hitta och förstå fel om vi är mitt i arbetet, än två veckor senare när vi kanske helt har bytt fokus. Vi sparar därmed tid eftersom det alltid uppstår en omställelsetid om vi måste växla tillbaka till ett kontext vi redan lämnat. Uppnår vi en tidig enhetstestning sparar vi även tid för våra testare, som därmed slipper passera en snårskog av irriterande småfel innan de kan börja testa på allvar.

Snabb återkopplingen är också önskvärt för att vi ska kunna säga att vi är klara med en utvecklingspunkt. Om vi inte har verifierat den både med enhetstester och systemtester kan den ju inte anses vara avklarad. Vi vill därför ha denna återkoppling snabbt så att vi kan flytta aktiviteten till listan över avklarade funktioner för att därefter kunna fokusera helt och fullt på nästa aktivitet.

Återkoppling är så pass viktigt att det är en av de fyra ursprungliga värderingarna i Extreme Programming.
(De andra tre är Communication, Simplicity och Courage. Till dessa har Respect tillkommit.)

Enhetstestet guidar oss rätt

Skriv en kommentar
15 februari 2009 13:31

Vi har tidigare beslyst några av de vanligaste ursäkterna till varför man inte enhetstestar och vi har även kommit fram till att även om vi enhetstestar så löser det inte alla våra problem. Varför ska man då enhetstesta? Blir det inte bara en massa jobb i onödan? Faktum är att även om enhetstestning inte löser världsproblemen, löser de en hel del andra problem.

Det finns många anledningar till att enhetstesta och nedan är bara en liten lista över de delar som jag tycker är viktiga:

- Snabb återkoppling om ändrad/ny kod har förväntat beteende
- Effektivare fellösning
- Säkrare refaktorering
- Positiva designeffekter
- Snabbare och enklare tester
- Levande dokumentation av produktionskoden

Varje del är värd ett eget inlägg och därför kommer jag att ägna de kommande inläggen åt förklara dem mer ingående. Intressant att notera är att om vi kan få till en testsvit som ger de positiva sideffekterna som listas ovan, kan vi använda våra enhetstester både som ett skyddsnät och en guide för vår utveckling. Inte illa för några extra rader kod.

Enhetstestning är ingen silver bullet

2 kommentarer
27 januari 2009 21:37

Idag hade jag en mycket intressant diskussion med en utvecklare hos min nuvarande kund. Vi pratade om testning och då framförallt om enhetstestning. Han delade med sig av sina erfarenheter och tryckte på det faktum att många har en lite glorifierad syn på enhetstestning. Han har helt rätt! Även om jag är en klar förespråkare för enhetstestning måste vi förstå vad det är enhetstesterna kan ge oss.

Enhetstester kan inte lösa alla kvalitétsproblem och de kan inte heller säga att vår applikation är felfri. Just här ligger de flesta missförstånden. Bara för att alla våra tester går igenom  kan vi inte dra några som helst slutsatser om applikationens felfrekvens. Det enda vi kan säga är att den funktionalitet som testerna testar fungerar, vilket är viktigt i sig, men det är absolut inte detsamma som att applikationen är felfri.

Styrkan ligger egentligen inte i de tester som går igenom, utan i de tester som fallerar. Ett litet konstigt uttalande kanske, men medan ett godkänt test inte kan säga att produktionskoden är felfri, signalerar ett fallerande test ett fel i produktionskoden (förutsatt att inte testet är felskrivet förstås Ler). Ett fel som vi hittade med hjälp av vår testsvit! Vi kan då ändra produktionskoden och därefter köra testsviten igen för att se om felet kvarstår eller om vår fix rättade det.

Enhetstester har alltså två primära uppgifter:

1. Verifiera funktionen hos den kod vi skriver, men verifieringen blir inte bättre än de tester vi kan skriva. Verifieringen kan i stort sett aldrig bli heltäckande så att vi kan dra slutsatsen att vår kod är felfri.

2. Agera stöd vid refaktorering, funktionsändringar och felrättningar. En testsvit kan fånga många fel och spara oss massor av tidsödande felsökning.

Ledordet i enhetstestning är disciplin. Vi måste fortsätta skriva enhetstester, oavsett om det är ”min” eller ”din” kod som är under förändring. Håller vi disciplinen uppe, kommer vi att öka chanserna att vår testsvit fångar fel, samtidigt som det minskar risken att testerna förfaller.

Det är självklart också lika viktigt att refaktorera sina tester som det är att refaktorera produktionskoden. Testkoden kräver samma underhåll och omtanke som all annan kod, annars vittrar både den och meningen med vår testsvit sönder.

Enhetstestning är ingen silver bullet som löser alla våra testproblem, men det är ett kraftfullt verktyg som borde finnas i varje utvecklares verktygslåda. Som alla verktyg måste det användas på rätt sätt för att få tänkt effekt.

Cloud Magazine-nytt

Mest läst just nu

Senaste testerna

Mest kommenterade

Bloggare

Heta whitepaper

Senaste nytt 100 senaste | Arkiv | RSS | Läsarfavoriter

IDG.se bottom line
Dagens dilbert
Dagens dilbert via idg en enkel XML som visar dagens Dilbert
Städjes skriverier

Sveriges vassaste it-krönikörer

Krönikor

Dags för Dell att lyfta blicken

HiQ har ännu mer att ge

Bygg en bro mellan vd:n och cio:n

Tre spikar har hjälpt mig i soppkoket

Sluta simulera bibliotek - e-böcker hör inte hemma där


It-nyheter efter ämne
Outsourcing

AdtechHar du synpunkter på sajten? Kontakta ansvarig utgivare: Carl Grape | Kontakta IDG.se | Tipsa om en nyhet |
Så använder vi cookies | Om Personuppgifter & copyright
Karlbergsv. 77 106 78 Stockholm Tel: 08-453 60 00 Karta | Copyright © International Data Group