2013-06-07 15 views
6

Ich habe eine Klasse in Sonar:Sonar Zweigüberdeckung auf Klassendeklaration

public class Foo { 
..... much code .... 
} 

Und Sonar berichtet 1/2 an dieser public class Foo Linie, die Zweige. Was bedeutet das? Wie testen Sie eine Zeile, die eine Klasse deklariert?

Edit: falls es darauf ankommt, ist dies Sonar v3.5.

Edit 2: Ein Screenshot zeigt, was ich meine, beachten Sie die 1/2 neben der „public-Klasse“ auf Linie 9. Wenn darüber schwebt ich ein Tooltip erhalten Angabe „1 Zweige durch Tests abgedeckt werden“

http://img829.imageshack.us/img829/2626/screenshot20130607at120.png

Edit # 3: Ok, auf etwas mehr Untersuchung, habe ich es auf kleinsten Schnipsel eingrenzen kann ich feststellen, dass löst dies:

public class Foo { 

    Foo(final String s) { 
     assert (s != null); 
    } 
} 

Wenn das assert im Konstruktor existiert nicht , die Markierung "N/2 Zweige bedeckt" wird nicht angezeigt generiert in Sonar. Wenn die Assertion weg ist, verschwindet auch die Flagge. Also meine Rate ist, dass es auf den Zweigen innerhalb des Konstruktors basiert? (Dieser Code hat 0/4 Zweige für die Assert-Zeile und 0/2 für die öffentliche Klasse Zeile abgedeckt).

+0

Eine Erklärung Klasse ist keine zu überwindende Linie. Ohne einen Screenshot wäre es ziemlich schwer zu verstehen und Ihnen zu helfen. –

+0

@DavidRACODON: fertig. –

+0

Sind Zusicherungen zur Laufzeit aktiviert? – wchargin

Antwort

7

Es scheint, dass dies ein Problem in Bezug auf die JaCoCo Code Coverage Komponente von Sonar ist. JaCoCo arbeitet mit kompiliertem Bytecode anstatt mit Java-Quelle, und der Java-Compiler kann Code erzeugen, der nicht direkt mit der zugrunde liegenden Quelle in Beziehung steht.

bei the docs der Suche nach JaCoCo, gibt es einen Abschnitt, der (Hervorhebung hinzugefügt) lautet:

In manchen Situationen ist es nicht offensichtlich ist, warum bestimmte Linien hervorgehoben haben oder eine bestimmte Farbe haben. Der Grund dafür ist, dass die zugrunde liegende Code-Coverage-Bibliothek JaCoCo nur an Java-Klassendateien arbeitet. In einigen Fällen erstellt der Java-Compiler zusätzlichen Bytecode für eine bestimmte Zeile des Quellcodes. Solche Situationen können durch zukünftige Versionen von JaCoCo/EclEmma gefiltert werden.

Nach dem Link in der Passage führt Sie zur FilteringOptions Seite auf dem GH-Website Jacoco, und es nennt eine ganze Reihe von Möglichkeiten, wie die JDK möglicherweise Code erzeugen kann, die diese „unechten“ Code-Coverage-Warnungen auslösen .

Das ist jedoch nicht, was hier (oder nicht genau) spielt.

Wie bereits erwähnt, arbeitet JaCoCo mit Java-Bytecode, so dass jeder Code, der vom Compiler erzeugt wird, der nicht direkt der Quelle zugeordnet ist, zur Abdeckung zählt.

In meinem speziellen Fall hatte ich eine assert, die in der Quelle eine Verzweigung an dem Punkt darstellt, an dem die Bestätigung stattfindet, aber auch auf einer "globalen" Ebene. Wenn Sie an der Bytecode für die Foo Klasse siehe oben definiert (mit dem javap -c Foo), werden Sie sehen:

Compiled from "Foo.java" 
public class Foo extends java.lang.Object{ 
static final boolean $assertionsDisabled; 

Foo(java.lang.String); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."<init>":()V 
    4: getstatic #2; //Field $assertionsDisabled:Z 
    7: ifne 22 
    10: aload_1 
    11: ifnonnull 22 
    14: new #3; //class java/lang/AssertionError 
    17: dup 
    18: invokespecial #4; //Method java/lang/AssertionError."<init>":()V 
    21: athrow 
    22: return 

static {}; 
    Code: 
    0: ldc_w #5; //class Foo 
    3: invokevirtual #6; //Method java/lang/Class.desiredAssertionStatus:()Z 
    6: ifne 13 
    9: iconst_1 
    10: goto 14 
    13: iconst_0 
    14: putstatic #2; //Field $assertionsDisabled:Z 
    17: return 

Hinweis Linie 7, die eine bedingte Verzweigung abhängig ist, ob oder nicht Behauptungen aktiviert sind.Wenn Sie also eine Klasse mit einem einfachen Java assert darin haben, haben Sie diesen Zweig irgendwo im Bytecode, und dies erzeugt die Überdeckungswarnung "N/2 Zweige ausgeführt" für die Klassendeklaration, wobei N entweder 0 ist oder 1 abhängig davon, ob die Klasse jemals durch einen Test (1) oder nicht (0) ausgeübt wurde.

Edit: beachten Sie, dass dies auch in https://sourceforge.net/apps/trac/eclemma/wiki/FilteringOptions erwähnt wird:

Blöcke, die AssertionErrors werfen - Entire Block, wenn eine Bedingung ignoriert werden sollte (wenn Behauptung neue AssertionError werfen!)

Verwandte Themen