Nasıl PHPUnit ile birden istisnalar için test?

5 Cevap php

PHPUnit ile istisnalar sınarken, ne testi geçmek için her deyim veya onaylama amacıyla bir istisna gerektiğini gerektirecek en iyi yolu nedir?

Temelde böyle bir şey yapmak istiyorum:

public function testExceptions()
{

    $this->setExpectedException('Exception');

    foo(-1); //throws exception
    foo(1); //does not throw exception

}

//Test will fail because foo(1) did not throw an exception

Ben iş yapar aşağıdaki ile geldi, ancak IMO oldukça çirkin ettik.

public function testExceptions()
{

    try {
    	foo(-1);
    } catch (Exception $e) {
    	$hit = true;
    }

    if (!isset($hit))
    	$this->fail('No exception thrown');

    unset($hit);

    try {
    	foo(1);
    } catch (Exception $e) {
    	$hit = true;
    }

    if (!isset($hit))
    	$this->fail('No exception thrown');

    unset($hit);

}

5 Cevap

Istisnalar tek bir test ile birden fazla olanları test program akışı gibi büyük olaylar, olduğu gibi sorunludur.

Kolay şey, sadece iki test bölmek olduğunu - ilk, ikinci sadece çalışır geçmek edebilmek için bir istisna gerektirir, ve bir tane atmak yaptım bunu başarısız olur. Bunun adlandırma göre, (belki bir dönüş değeri teyit) isteseydi saniyede diğer bazı testler ekleyebilirsiniz, ama ben emin hala sadece tek önemli şey yaptım yapmak için eğimli olurdu.

/**
 * @expectedException Exception
 */
public function testBadFooThrowsException()
{
    // optional, can also do it from the '@expectedException x'
    //$this->setExpectedException('Exception');
    foo(-1); //throws exception -- good.
}

public function testFooDoesNotThrowException()
{
    foo(1); //does not throw exception
}

Bu benim için mantıklı değil.

Ben kötü bir uygulamadır, bir test durumu ile birden fazla ayrı şeyleri test için çalışıyoruz sanırım.

foo() beklenen istisna atar test durumda başarılı ve bar() çalışmaz.

Sadece ikinci kotasyon üretilen sonra ne çok daha az kod iki ayrı test durumları oluşturabilirsiniz.

foo(), bir istisna ile başarısız sonra çok bir özel durum zaman, bar() çalıştırmak için mantıklı neden ya da açıklar.

Kod biraz daha temiz (ama ben hala testleri bölme öneririm:

try {
    foo(-1);
    $this->fail('No exception thrown');
} catch (Exception $e) {}

Dave1010 cevabı @ genişletilmesi, burada ben bu sorunu nasıl çözdüklerini olduğunu. Bu bir test içindeki temiz ve derli toplu, tüm bu "iddiaları" saklamanızı sağlar. Sadece test başarısız gereken değişkenleri bir dizi tanımlamak ve sonra döngü her biri ile ve bir istisna yükseltilmiş olup olmadığını görmek. Herhangi bir (bir istisna atılır) başarısız olursa, test başarısız, aksi testi geçer.

<?php

public function testSetInvalidVariableType()
{
    $invalid_vars = array(
        '',                 // Strings
        array(),            // Arrays
        true,               // Booleans
        1,                  // Integers
        new \StdClass       // Objects
    );

    foreach ($invalid_vars as $var) {
        try {
            $object->method($var);
            $this->fail('No exception thrown for variable type "' . gettype($var) . '".');
        } catch (\Exception $expected) {
        }
    }
}

Ben bu birim test çok yaygın bir durum olduğunu düşünüyorum. Ben bu gibi durumlarda kullanmak yaklaşım phpunit kullanarak dataProviders. Edilir Tüm beklendiği gibi çalıştığını ve test kodu daha açık ve anlaşılır hale gelir.

class MyTest extends PHPUnit_Framework_TestCase
{
    public function badValues()
    {
       return array(
           array(-1),
           array(1)
       );
    }


    /**
     * @dataProvider badValues
     * @expectedException Exception
     */
    public function testFoo($badValue)
    {
        foo($badValue);
    }
}