I den här artikeln ska jag skriva lite om EclEmma, en plugin till Eclipse för testramverket EMMA. Pluginen är inte på något sätt ny, men inte desto mindre användbar. Verktyget är till för att visa dig hur väl dina tester täcker din kod, s. k. test coverage.

Även om man utvecklar enligt TDD (Test Driven Development) så kan det vara bra att få ett kvitto på att ens egen bild av testerna stämmer överens med verkligheten. För den som inte utvecklar testdrivet är EMMA en riktig ”eye-opener” för att, allt som oftast, inse att det behövs fler tester.

Jag fortsätter med ett exempel av Hello World-kaliber. Ladda gärna hem pluginen själv och prova samtidigt, projektets hemsida är www.eclemma.org där du kan välja manuell nerladdning eller använda länken till projektets update-site, samt att det finns tillgängligt i Eclipse Marketplace.

Då kör vi. Testet ser ut såhär:

public class EmmaTest { 
    @Test
    public void testGreeter() { 
        Greeter greeter = new Greeter(); 
        Assert.assertEquals("Hello Cygni!", greeter.greet("Cygni"));
    }
}

Och klassen vi ska testa:

public class Greeter {
    public String greet(String name) { 
        if (name != null) {
            return "Hello " + name + "!";
        } else { 
            return "Who are you?";
        }
    }

    public String greetSimple() { 
        return "Hello you!";
    }
}

Att testet inte täcker hela Greeter-klassen har du nog redan insett. Vi låter dock EclEmma sköta analysen.

När EclEmma är installerat dyker ytterligare ett alternativ för att exekvera upp. Sedan tidigare har vi Run as och Debug as, men nu kommer även Coverage as att finnas tillgängligt. Om du kör Java-perspektivet skall också en ikon för detta ha tillkommit (kör du andra perspektiv kan du behöva lägga till ikonen via ”Customize perspective”). Vi kör testet via Coverage as:

Testet körs och vi får upp Coverage-vyn, samt att kodraderna i de klasser där det körts kod kommer att ha fått lite färg. Vi börjar med Coverage-vyn:

Som synes kan vi gå ner på olika nivåer för att tydligare se var det täcker bättre eller sämre. Efter att ha expanderat trädet fullt ut ner på metodnivå ser vi att greetSimple() har 0% täckning och att greet() behöver testas mer för att nå 100%. Metoden greetSimple() tog jag bara med här för att visa på hur användbart det är att kunna se test coverage på metodnivå och på så sätt tydligare identifiera svagheter, men jag låter den vara otestad för det här exemplet.

Om vi öppnar klassen Greeter, så ser ni tydligt vad som är testat och inte:

I greetSimple() är det inte så mycket att tala om, den är röd (no coverage) eftersom vi inte har något test som kör metoden. I greet() är raden med ”Who are you?” röd eftersom vi inte har gjort något anrop där if-satsen utvärderas till false.

Den gröna raden är grön (full coverage) därför att det är den rad som exekverades när metoden returnerade ”Hello Cygni!”, det väntade resultatet av vårt test.

Den gula raden betyder att raden är delvis täckt (partial coverage), en mycket användbar indikator. I det här fallet vet vi att det finns två scenarion för if-satsen. Antingen har argumentet name värdet null, eller så är name skilt från null. I vårt test skickade vi in ”Cygni”, name var alltså skilt från null. EclEmma talar också om för oss hur många fall vi har missat om vi håller muspekaren över diamantikonen bredvid:

Vi skriver ytterligare ett test för att nå 100% test coverage i metoden greet():

@Test
public void testGreeterNullArg() { 
    Greeter greeter = new Greeter(); 
    Assert.assertEquals("Who are you?", greeter.greet(null));
}

Resultatet ser nu mycket trevligare ut:

En inställning som är bra att känna till är vilken typ av counter man kör. Hur stor test coverage dina tester har kan variera stort beroende på hur man räknar. I vårt exempel kunde vi se att vi i if-satsen hade två stycken branches. I första testet kördes bara ett anrop där uttrycket i if-satsen var sant (name var skilt från null), vilket innebar att vi täckte en branch av två – branchen där name var null kördes inte. Alltså hade vi i det testet 50% branch coverage på den raden.

Men, om vi istället räknar line coverage, så är siffran 100% eftersom line coverage inte tar hänsyn till vilken typ av kodrad som exekveras, bara att den exekveras. Klicka på den vita nedåtriktade pilen i coverage-vyn för att ändra typ av counter:

Du kan läsa mer om de olika typerna av counters som finns på EclEmma‘s hemsida eller exempelvis Wikipedia.

Två tips innan vi är färdiga:

  1. EMMA och andra liknande verktyg (Cobertura till exempel) finns som plugins till exempelvis Maven och Jenkins, som då genererar en rapport över hur testerna gick i ett bygge. Att ha statistik och rapporter över testresultat och trender i projektet ger en trevlig överblick.
  2. Om du kör ett mörkt tema för Eclipse, vilket inte är särskilt ovanligt, rekommenderar jag att ändra highlight-färgerna för EclEmma, annars är risken stor att du inte ser texten på raderna. Gå till Window -> Preferences -> General -> Editors -> Text Editors -> Annotations och välj mörkare färger för alternativen Full coverage, Partial coverage och No coverage.