2015-02-19 2 views
13

ich zur Zeit begann die strict -Mode in PHPUnit verwenden, wenn ich auf ein Problem mit der Code-Coverage kam:PHPUnit Strict Mode - setUp() - Coverage

Wenn ich die setUp -Methode verwenden, um einen neuen zu erstellen Beispiel einer meiner Klasse die __constructor -Methode ist in der Code-Coverage als abgedeckt aufgeführt, wenn ich die Tests ausführen.

Dies ist mein Test-Setup:

phpunit.config.xml

<?xml version="1.0" encoding="UTF-8"?> 
<phpunit 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.5/phpunit.xsd" 
    bootstrap="../vendor/autoload.php" 
    backupGlobals="false" 
    backupStaticAttributes="false" 
    colors="true" 
    verbose="true"  
    beStrictAboutOutputDuringTests="true" 
    beStrictAboutTestSize="true" 
    beStrictAboutTestsThatDoNotTestAnything="true" 
    beStrictAboutTodoAnnotatedTests="true" 

    checkForUnintentionallyCoveredCode="true" 
    processIsolation="false" 
> 
<testsuites> 
    <testsuite name="FooTests"> 
     <directory suffix="Test.php">../tests</directory> 
    </testsuite> 
</testsuites> 
<filter> 
    <whitelist> 
     <directory suffix=".php">../src</directory> 
    </whitelist> 
</filter> 
<logging> 
    <log type="coverage-html" target="coverage/" higlight="true" showUncoveredFiles="true"></log>  
</logging> 

foo.php

class Foo 
{ 

    protected $_bar; 

    public function __construct($bar) 
    { 
     $this->_bar=$bar;    //Line 10 
    }         //Line 11 

    public function getBar() 
    { 
     return $this->_bar; 
    } 

    public function getBar2() 
    { 
     return $this->_bar; 
    } 

} 

und der Test: FooTest.php

class FooTest extends \PHPUnit_Framework_TestCase 
{ 

    protected $_foo; 

    protected function setUp() 
    { 
     $this->_foo=new Foo(10); 
    } 

    public function testGetBar() 
    { 
     $this->assertSame(10, $this->_foo->getBar()); 
    } 

    /** 
    * @covers Foo::getBar2 
    */ 
    public function testGetBar2() 
    { 
     $this->assertSame(10, $this->_foo->getBar2()); 
    } 

} 

Wenn ich die Tests laufen bekomme ich dieses Ergebnis:

PHPUnit 4.5.0 by Sebastian Bergmann and contributors. 

Configuration read from C:\xampp\htdocs\unittest\build\phpunit.config.xml 

.R 

Time: 88 ms, Memory: 3.50Mb 

There was 1 risky test: 
1) FooTest::testGetBar2 
This test executed code that is not listed as code to be covered or used: 
- C:\xampp\htdocs\unittest\src\Foo.php:10 
- C:\xampp\htdocs\unittest\src\Foo.php:11 

OK, but incomplete, skipped, or risky tests! 
Tests: 2, Assertions: 2, Risky: 1. 

Generating code coverage report in HTML format ... done 

Sobald ich die @covers auf dem Test geben das Problem erscheint.

Ist das erwartete Verhalten?

Einige Dinge, die ich versucht:

  • checkForUnintentionallyCoveredCode zu false funktioniert natürlich ändern, aber ich möchte diese Funktion nutzen ...
  • Mit processIsolation="true" auch funktioniert. Ich weiß nicht warum?
  • Hinzufügen @covers oder @uses-setUp() funktioniert nicht
  • @covers fügte hinzu, dass die setUp() zum Test verwendet funktioniert, aber der Test deckt nicht den Code tatsächlich. (Wenn die Tests komplexer werden, scheint dies eine viel geschrieben zu sein ...)
  • Verschiedene phpunit -Version: ich schon versucht, diese mit 4.3 und 4.5 mit gleichen Ergebnissen
  • Verschiedene PHP-Setup: Ich habe versucht, diese auf ein Win8 mit XAMPP und einem LinuxMint - gleichen Ergebnissen

gibt es eine Möglichkeit, den setUp() Code aus der Code-Abdeckung zu entfernen und mit @covers auf Tests mit Methoden tatsächlich testen sie?

Edit: Dies betrifft auch die Vererbung. Also, wenn BarFoo erweitert und übergibt Argumente auf Foo::__construct, die auch auf der Code-Coverage sein wird -, die die @covers für die __construct einen Schmerz in der eine macht das Schreiben ** ...

Zusätzliche Informationen:

PHP 5.6.3 (cli) (built: Nov 12 2014 17:18:08) 
Copyright (c) 1997-2014 The PHP Group 
Zend Engine v2.6.0, Copyright (c) 1998-2014 Zend Technologies 
with Xdebug v2.2.5, Copyright (c) 2002-2014, by Derick Rethans 
+0

Es ist in der Regel ratsam, dass Konstrukteure möglichst wenig Arbeit zu tun, wenn überhaupt möglich, in der Tat sollten sie nicht etwas anderes als ihre Argumente zu Instanzvariablen zuweisen. Ein einfacher Konstruktor muss nicht wirklich getestet werden, daher sollte seine Auswirkung auf den Code-Coverage-Bericht eigentlich keine Rolle spielen. Für Ihren Fall könnten Sie versuchen, einfach eine leere setup() -Methode zu haben und $ this object = new ObjectUnderTest() in jedem Testfall zu machen. – GordonM

+0

@GordonM Das Einzige, was ich testen möchte, ist, ob das Typhinweis für die Abhängigkeiten (Datenbank, Logger, ...) richtig eingerichtet ist. Die __construct-Methode führt nur Zuordnungen durch. – SpazzMarticus

Antwort

3

Seit dieser Frage begann etwas an Schwung zu gewinnen: Hier ist meine Art von Lösung für das Problem.

Meine Einheit -Test (FooTest) von Foo immer VerwendungFoo daher füge ich @uses Foo der Klasse.

Dies ist auch wichtig, wenn protected/private Funktionen von public Funktionen verwendet werden, da sonst müssen Sie jede einzelne protected/private Funktion zu einem Test hinzufügen, wenn die Klasse der Funktion intern verwendet. Ich denke sogar, dass es falsch ist, wenn Sie Komponententests durchführen, da ein Komponententest sich nicht darum kümmern muss, wie die Klasse "stopft", sondern nur, dass eine bestimmte Eingabe zu einer bestimmten Ausgabe führt.

(Zusätzlich: Der Konstruktor sollte nur tun Zuweisungen, sonst nichts.)

Nach der Zugabe von @uses die Fehler verschwinden.

(Sie @covers Foo::_construct zur Klasse hinzufügen können Code-Abdeckung Ihres Konstruktor zu haben.)

/** 
* @uses Foo 
* (optional)@covers Foo::__construct 
*/ 
class FooTest extends \PHPUnit_Framework_TestCase 
{ 
    protected $_foo; 

    protected function setUp() 
    { 
     $this->_foo=new Foo(10); 
    } 

    public function testGetBar() 
    { 
     $this->assertSame(10, $this->_foo->getBar()); 
    } 

    /** 
    * @covers Foo::getBar2 
    */ 
    public function testGetBar2() 
    { 
     $this->assertSame(10, $this->_foo->getBar2()); 
    } 
} 
2

Sie haben eine strikte Abdeckung mit checkForUnintentionallyCoveredCode="true" angegeben.Und da PHPUnit 4.0 PHPUnit das folgende Verhalten hat:

Umgang mit unbeabsichtigt abgedeckt Code

PHPUnit 4.0 kann optional streng über unbeabsichtigt abgedeckt Code (strict> Deckungsmodus). Wenn diese Option aktiviert ist, wird in PHPUnit ein Test fehlschlagen, der die Annotation @covers verwendet und Code ausführt, der nicht mit einer @covers-Annotation angegeben wurde.

+0

Ich bin mir dessen voll bewusst. Das Problem ist: Der Test führt nicht '__construct' aus, nur das' setUp' tut, trotzdem muss ich '@ cover' für' __construct' bei jedem Test angeben, ansonsten wird der Test als _risky_ klassifiziert. – SpazzMarticus

+0

setUp() und teardown() werden für jeden Test ausgeführt, also sind sie nicht Teil des Tests in diesem Sinne? Ich habe es nicht getestet, aber ich erwarte, dass, wenn ich die Annotation @expectedException verwende und diese Ausnahme in meine setup() - oder teardown() -Methode werfe, der Test deswegen vergehen wird .... – qrazi