PHPUnit bir hata tetikler bir yöntemin dönüş değeri sınamak

4 Cevap php

Bu soru, phpunit kullanarak özgüdür.

PHPUnit otomatik istisnalar php hataları dönüştürür. Is there a way to test the return value of a method that happens to trigger a php error (either built-in errors or user generated errors via *trigger_error*)?

Test için kod örneği:

function load_file ($file)
{
    if (! file_exists($file)) {
        trigger_error("file {$file} does not exist", E_USER_WARNING);
        return false;
    }
    return file_get_contents($file);
}

Bu benim yazmak istiyorum test türüdür:

public function testLoadFile ()
{
    $this->assertFalse(load_file('/some/non-existent/file'));
}

Ben yaşıyorum sorun tetiklenen hata (gerektiği gibi) benim birim test başarısız neden olmasıdır. Onu yakalamak, ya da beklenen bir istisna hatası tetiklenir sonra yürütür asla herhangi bir kod ayarlamak için çalışırsanız Ama ben yöntemin dönüş değeri test yolu yoktur.

Bu örnek çalışmaz:

public function testLoadFile ()
{
    $this->setExpectedException('Exception');
    $result = load_file('/some/non-existent/file');

    // code after this point never gets executed

    $this->assertFalse($result);
}

Herhangi Ben bunu başarmak nasıl fikir?

4 Cevap

Bir birim test içinde bunu yapmak için hiçbir yolu yoktur. Eğer iki farklı testler halinde dönüş değeri ve haber test break up mümkündür.

Phpunit hatası işleyicisi PHP hataları ve uyarıları yakalar ve İstisnalar dönüştürür - tanım gereği program yürütme durur. Eğer test işlevi hiç geri dönmedi. Ancak, geçici bile zamanında, istisnalar içine hataların dönüşümünü devre dışı bırakabilirsiniz.

Bu bir örnek, yani burada iki test gibi görünmelidir ne muhtemelen daha kolaydır:

public function testLoadFileTriggersErrorWhenFileNotFound()
{
    $this->setExpectedException('PHPUnit_Framework_Error_Warning'); // Or whichever exception it is
    $result = load_file('/some/non-existent/file');

}

public function testLoadFileRetunsFalseWhenFileNotFound()
{
    PHPUnit_Framework_Error_Warning::$enabled = FALSE;
    $result = load_file('/some/non-existent/file');

    $this->assertFalse($result);
}

Bu aynı zamanda testleri daha net, temiz ve kendini belgeleyen yapma avantaj vardır.

Re: Comment: That's a great question, and I had no idea until I ran a couple of tests. It looks as if it will not restore the default/original value, at least as of PHPUnit 3.3.17 (the current stable release right now).

Yani, ben aslında öyle gibi görünmek için yukarıdaki değişiklik olur:

public function testLoadFileRetunsFalseWhenFileNotFound()
{
    $warningEnabledOrig = PHPUnit_Framework_Error_Warning::$enabled;
    PHPUnit_Framework_Error_Warning::$enabled = false;

    $result = load_file('/some/non-existent/file');

    $this->assertFalse($result);

    PHPUnit_Framework_Error_Warning::$enabled = $warningEnabledOrig;
}

Re: Second Comment:

Bu tamamen doğru değil. Ben phpunit hata işleyicisi bakıyorum, ve aşağıdaki gibi çalışır:

  • Eğer varsa bir E_WARNING, bir istisna sınıfı olarak PHPUnit_Framework_Error_Warning kullanın.
  • Bir E_NOTICE ya da E_STRICT hata olursa, kullanımı PHPUnit_Framework_Error_Notice
  • Else, istisna sınıfı gibi PHPUnit_Framework_Error kullanın.

Yani, evet, E_USER_* phpunit adlı * _Warning veya * _Notice sınıfa dönük olmayan hatalar, yine de genel bir PHPUnit_Framework_Error istisna haline dönüşür.

Further Thoughts

Bu işlevin nasıl kullanıldığını tam olarak bağlı iken bana olsaydı, herhalde, gerçek bir istisna atma yerine bir hata tetikleme geçmek istiyorum. Evet, bu bir dosyayı okuyamıyor zaman hemen infaz bitmiyor ... yöntemin mantık akışını ve yöntemi kullanır kodunu değiştirmek istiyorsunuz. Ama bu mevcut değil istenen dosya exceptional davranış gerçekten olup olmadığına karar vermek size kalmış. Onlar, idare testi ve uygulama akışına çalışmak daha kolaydır çünkü, hatalar / uyarılar / bildirimlerine yol daha istisnaları kullanma eğiliminde. Ben genellikle vb itfa yöntemi çağrıları, gibi şeyler için bildirimleri rezerv

Bir phpunit.xml yapılandırma dosyası kullanmak ve İstisna dönüşüm haber / uyarı / hata devre dışı. Daha details in the manual. Temelde böyle bir şey var:

<phpunit convertErrorsToExceptions="false"
         convertNoticesToExceptions="false"
         convertWarningsToExceptions="false">
</phpunit>

Bunun yerine, genel bir "Exception" bekleyen, ne bir "PHPUnit_Framework_Error" bekliyor dersiniz?

Böyle bir şey yapacağım:

/**
 * @expectedException PHPUnit_Framework_Error
 */
public function testFailingInclude()
{
    include 'not_existing_file.php';
}

: Sanırım ki, aynı zamanda yazılmış olabilir

public function testLoadFile ()
{
    $this->setExpectedException('PHPUnit_Framework_Error');
    $result = load_file('/some/non-existent/file');

    // code after this point never gets executed

    $this->assertFalse($result);
}

For more informations, see Testing PHP Errors
Especially, it says (quoting) :

PHPUnit_Framework_Error_Notice and PHPUnit_Framework_Error_Warning represent PHP notices and warning, respectively.


Looking at the /usr/share/php/PHPUnit/TextUI/TestRunner.php file I have on my system, I see this (line 198 and following) :

if (!$arguments['convertNoticesToExceptions']) {
    PHPUnit_Framework_Error_Notice::$enabled = FALSE;
}

if (!$arguments['convertWarningsToExceptions']) {
    PHPUnit_Framework_Error_Warning::$enabled = FALSE;
}

Bu yüzden belki de bu davranışı etkinleştirmek için parametre çeşit geçmesi gerekecek? Ama varsayılan olarak etkin gibi görünüyor ...

Aslında dönüş değeri ve (bu durumda PHPUnit tarafından dönüştürülmüş bir hata olarak) istisnayı hem test etmek için bir yol var.

Sadece aşağıdakileri yapmanız gerekir:

public function testLoadFileTriggersErrorWhenFileNotFound()
{
    $this->assertFalse(@load_file('/some/non-existent/file'));

    $this->setExpectedException('PHPUnit_Framework_Error_Warning'); // Or whichever exception it is
    load_file('/some/non-existent/file');
}

Eğer (fonksiyon isminden önce @) işlev çağrısı hata bastırma operatörünü kullanmak zorunda dönüş değeri sınamak için dikkat edin. Bu şekilde bir istisna atılır ve yürütme devam edecektir. Daha sonra hatayı test etmek için her zamanki gibi beklenen istisna ayarlamak zorunda.

Ne yapamaz bir birim test içindeki test birden fazla istisna olduğunu.