2009-10-20 17 views
17

PHPUnit के साथ अपवादों के परीक्षण के दौरान, परीक्षा के लिए प्रत्येक कथन या दावे को अपवाद फेंकने का सबसे अच्छा तरीका क्या है?मैं PHPUnit के साथ कई अपवादों का परीक्षण कैसे करूं?

मैं मूल रूप से इस तरह कुछ करना चाहता हूँ:

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 

मैं निम्नलिखित है, जो काम करता है, लेकिन IMO काफी बदसूरत है के साथ आ गए हैं।

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); 

} 

उत्तर

16

अपवाद जैसे कार्यक्रम प्रवाह में इतनी बड़ी घटनाएं हैं, एक परीक्षण में एकाधिक परीक्षणों को समस्याग्रस्त करना समस्याग्रस्त है।

सबसे आसान बात यह है कि इसे आसानी से दो परीक्षणों में विभाजित करना है - पहले को पास करने में सक्षम होने के लिए अपवाद की आवश्यकता होती है, दूसरा बस चलता है, और असफल हो जाता है, यह एक फेंक देता है। यदि आप चाहते थे तो आप दूसरे में कुछ अन्य परीक्षण जोड़ सकते हैं (शायद वापसी मूल्य की पुष्टि कर रहे हैं), लेकिन मैं यह सुनिश्चित करने के इच्छुक हूं कि यह अभी भी एक आवश्यक चीज़ है, इसके नामकरण के अनुसार।

/** 
* @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 
} 
+1

मैं निश्चित रूप से आपका बिंदु देखता हूं, हालांकि यह अभी भी कई परीक्षणों के लिए थोड़ा अजीब लगता है जब प्रत्येक का बिंदु यह सुनिश्चित करना है कि अपवाद फेंक दिया जाए। – etheros

+3

आप मानों में पास करने के लिए '@डेटावाइडर एनोटेशन' का भी उपयोग कर सकते हैं (और यहां तक ​​कि अपेक्षित अपवाद का नाम भी - '$ this-> setExpectedException ($ x)' के साथ उपयोग करें)। एक नया टेस्ट वैल्यू जोड़ना (जो अपवाद फेंक देगा) तो डेटा प्रोवाइडर फ़ंक्शन में बस एक और सरणी प्रविष्टि होगी। –

+1

रॉबर्ट मार्टिन हमेशा मामलों को विभिन्न परीक्षणों में विभाजित करने के लिए कहेंगे। मेरी राय में, @AlisterBulman उत्तर समस्या के लिए सही समाधान दिखाता है। –

1

यह मुझे समझ में नहीं आता है।

मुझे लगता है कि आप एक परीक्षण मामले के साथ कई अलग-अलग चीजों का परीक्षण करने की कोशिश कर रहे हैं जो खराब अभ्यास है।

जब foo() अपेक्षित अपवाद फेंकता है तो परीक्षण केस सफल है और bar() नहीं चलेंगे।

बस दो अलग-अलग टेस्ट केस बनाएं जो कि बहुत कम कोड है, फिर आपने दूसरी लिस्टिंग में जो उत्पादन किया था।

या बताएं कि bar() चलाने के लिए क्यों समझदारी होगी, foo() अपवाद के साथ असफल रहा, जब यह अपवाद भी फेंक देगा।

+0

मैं अलग-अलग तर्कों के साथ एक ही फ़ंक्शन को कॉल करने का परीक्षण करने का प्रयास कर रहा था (और मैंने इसे बेहतर रूप से प्रतिबिंबित करने के लिए अपना उदाहरण संपादित किया)। PHPUnit मैन्युअल में एक उदाहरण एक परीक्षण में किए गए कई संबंधित दावों को दिखाता है, इसलिए मैं इसे दोहराने की कोशिश कर रहा था लेकिन अपवादों के साथ। – etheros

6

थोड़ा क्लीनर कोड (लेकिन मैं अभी भी अपने परीक्षण के बंटवारे का सुझाव चाहते हैं:

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

@ dave1010 के जवाब में विस्तार करते हुए, यहाँ है कि कैसे मैं इस मुद्दे को हल यह आप इन सभी रखने के "करने के लिए अनुमति देता है। एक परीक्षण के भीतर साफ और साफ है। आप केवल वेरिएबल्स की एक सरणी परिभाषित करते हैं जो परीक्षण में विफल होना चाहिए, और फिर प्रत्येक के माध्यम से लूप करें और देखें कि कोई अपवाद उठाया गया है या नहीं। अगर कोई असफल हो जाता है (कोई अपवाद फेंक नहीं जाता है), अन्यथा परीक्षण विफल रहता है, अन्यथा परीक्षण पास होता है।

<?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) { 
     } 
    } 
} 
+0

'विफल' 'PHPUnit_Framework_AssertionFailedError 'फेंकता है। आपको अपने कोड में कस्टम अपवादों का उपयोग करने की आवश्यकता है। – sectus

15

मुझे लगता है कि यह इकाई परीक्षण में एक बहुत ही आम स्थिति है। इस मामले में मैं जिस दृष्टिकोण का उपयोग करता हूं वह phpunit dataProviders का उपयोग कर रहा है। अपेक्षित सभी कार्य, और परीक्षण कोड अधिक स्पष्ट और संक्षिप्त हो जाता है।

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); 
    } 
} 
+2

बहुत अच्छा विचार ... एक परीक्षण के साथ कई अपवादों का परीक्षण करें। – Andrew

+0

क्या वहां सरणी (1) 'होनी चाहिए? –

+3

कि समाधान सबसे सुंदर और सुरुचिपूर्ण है और स्वीकार्य उत्तर होना चाहिए। –

संबंधित मुद्दे