2009-08-04 20 views
11

के साथ किसी त्रुटि को ट्रिगर करने वाली विधि के वापसी मान का परीक्षण करें यह प्रश्न PHPUnit का उपयोग करने के लिए विशिष्ट है।PHPUnit

PHPUnit स्वचालित रूप से अपवादों में PHP त्रुटियों को परिवर्तित करता है। क्या किसी विधि की वापसी मान का परीक्षण करने का कोई तरीका है जो एक php त्रुटि को ट्रिगर करने के लिए होता है (या तो अंतर्निहित त्रुटियां या ट्रिगर_error के माध्यम से उपयोगकर्ता द्वारा उत्पन्न त्रुटियां)? परीक्षण करने के लिए कोड की

उदाहरण:

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

इस परीक्षण के प्रकार मैं लिखना चाहते है:

public function testLoadFile() 
{ 
    $this->assertFalse(load_file('/some/non-existent/file')); 
} 
समस्या मैं कर रहा हूँ

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

इस उदाहरण काम नहीं करता:

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

    // code after this point never gets executed 

    $this->assertFalse($result); 
} 

कोई भी विचार मैं यह कैसे प्राप्त कर सकता है?

उत्तर

21

एक इकाई परीक्षण के भीतर ऐसा करने का कोई तरीका नहीं है। यह संभव है यदि आप रिटर्न वैल्यू का परीक्षण करते हैं, और नोटिस दो अलग-अलग परीक्षणों में होता है।

PHPUnit का त्रुटि हैंडलर PHP त्रुटियों और नोटिस को पकड़ता है और उन्हें अपवादों में परिवर्तित करता है - जो परिभाषा द्वारा प्रोग्राम निष्पादन को रोकता है। जिस फ़ंक्शन का आप परीक्षण कर रहे हैं वह कभी भी वापस नहीं आता है। हालांकि, आप रनटाइम पर भी अस्थायी रूप से अपवादों में त्रुटियों के रूपांतरण को अक्षम कर सकते हैं।

यह शायद एक उदाहरण के साथ आसान है, इसलिए, यहाँ क्या दो टेस्ट कैसा दिखना चाहिए:

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

यह भी अपने परीक्षण साफ, स्वच्छ और स्वयं कुछ दस्तावेज़ीकृत बनाने का अतिरिक्त लाभ है।

पुन: टिप्पणी: यह एक अच्छा सवाल है, और मुझे तब तक कोई जानकारी नहीं थी जब तक कि मैंने कुछ परीक्षण नहीं किए। ऐसा लगता है कि यह डिफ़ॉल्ट रूप से PHPUnit 3.3.17 (वर्तमान स्थिर रिलीज़ अभी) के रूप में डिफ़ॉल्ट/मूल मान को पुनर्स्थापित करेगा।

तो, मैं वास्तव में ऐसा तरह देखने के लिए ऊपर में संशोधन होगा:

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

पुन: दूसरा टिप्पणी:

पूरी तरह से सच नहीं है यही कारण है कि। मैं PHPUnit के त्रुटि हैंडलर को देख रहा हूँ, और इस प्रकार यह काम करता है:

  • यदि यह एक E_WARNING है, एक अपवाद वर्ग के रूप में PHPUnit_Framework_Error_Warning का उपयोग करें।
  • यदि यह एक E_NOTICE या E_STRICT त्रुटि है, तो, PHPUnit_Framework_Error_Notice
  • वरना का उपयोग अपवाद वर्ग के रूप में PHPUnit_Framework_Error का उपयोग करें।

तो, हाँ, E_USER_* की त्रुटियों PHPUnit के * चेतावनी का दिन या * _Notice वर्ग में बदल नहीं कर रहे हैं, वे अभी भी एक सामान्य PHPUnit_Framework_Error अपवाद के रूप में तब्दील कर रहे हैं।

आगे विचार

कि यह कितना समारोह प्रयोग किया जाता है पर वास्तव में निर्भर करता है, मैं शायद एक वास्तविक अपवाद फेंकने के बजाय एक त्रुटि ट्रिगर है, अगर यह मुझे थे करने के लिए स्विच चाहते हैं। हां, यह विधि के तर्क प्रवाह को बदल देगा, और कोड जो विधि का उपयोग करता है ... अभी निष्पादन तब नहीं रुकता जब यह फ़ाइल नहीं पढ़ सकता है। लेकिन यह तय करने के लिए आप पर निर्भर है कि अनुरोधित फ़ाइल मौजूद नहीं है, वास्तव में असाधारण व्यवहार है। मैं त्रुटियों/चेतावनियों/नोटिस से अधिक अपवादों का उपयोग करता हूं, क्योंकि वे आपके आवेदन प्रवाह में संभाल, परीक्षण और काम करना आसान हैं। मैं आम तौर पर अवमूल्यित विधि कॉल आदि जैसी चीजों के लिए नोटिस आरक्षित करता हूं।

+0

धन्यवाद जेसन। क्या आपको पता है कि PHPUnit_Framework_Error_Warning :: $ सक्षम मान स्वचालित रूप से परीक्षणों के बीच वापस आ गया है या क्या आपको इसे मैन्युअल रूप से अपने मूल मूल्य में बदलने की आवश्यकता है? – dellsala

+0

इस बारे में एक नोट यह उत्तर। हालांकि यह अंतर्निहित PHP कार्यों और विधियों द्वारा उत्पन्न त्रुटियों के लिए काम करता है, यह उपयोगकर्ता द्वारा जेनरेट किए गए त्रुटि प्रकार (E_USER_WARNING और E_USER_NOTICE) ट्रिगर_error के लिए काम नहीं करता है। ऐसा लगता है कि PHPUnit रनटाइम पर इन्हें टॉगल करने का समर्थन नहीं करता है (संस्करण 3.3.17) – dellsala

3

एक सामान्य "Exception" की अपेक्षा करने के बजाय, "PHPUnit_Framework_Error" की अपेक्षा करने के बारे में क्या?

कुछ इस तरह कर सकते हैं:

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

कौन सा है, मुझे लगता है, यह भी रूप में लिखा जा सकता है:

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

अधिक जानकारियां के लिए, Testing PHP Errors
खास तौर पर देखते हैं, यह (के हवाले से) कहते हैं :

PHPUnit_Framework_Error_Notice और PHPUnit_Framework_Error_Warning क्रमशः PHP नोटिस और चेतावनी का प्रतिनिधित्व करता है।

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

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


मैं अपने सिस्टम पर है /usr/share/php/PHPUnit/TextUI/TestRunner.php फ़ाइल को देखते हुए, मैं इस (लाइन 198 और निम्न) देखना

तो शायद आपको उस व्यवहार को सक्रिय करने के लिए किसी प्रकार का पैरामीटर पारित करना होगा? लेकिन यह डिफ़ॉल्ट रूप से सक्षम प्रतीत होता है ...

+0

यह वह नहीं है जो वह पूछ रहा था। – jason

+0

जेसन सही है - बिल्कुल नहीं जो मैं पूछ रहा था, लेकिन PHPUnit अपवाद प्रकारों का उपयोग कर विशिष्ट PHP त्रुटि प्रकार की जांच करने के बारे में अच्छी युक्ति। – dellsala

+0

@ जेसन: ओह, आपका अधिकार :-(क्षमा करें :-(अच्छा जवाब, बीटीडब्ल्यू (दो अलग-अलग परीक्षणों का उपयोग करने की बात निश्चित रूप से एक अच्छी बात है) @ डसेलसा: धन्यवाद :-) –

8

phpunit.xml कॉन्फ़िगरेशन फ़ाइल का उपयोग करें और अपवाद रूपांतरण में नोटिस/चेतावनी/त्रुटि अक्षम करें। अधिक details in the manual। यह मूल रूप से ऐसा कुछ है:

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

@lonut - मैं _this_ की तलाश में था 2 साल पुरानी पोस्ट, अभी भी रिलीज। – stefgosselin

1

वास्तव में वापसी मूल्य और अपवाद को फेंकने का एक तरीका है (इस मामले में PHPUnit द्वारा परिवर्तित त्रुटि)।

तुम बस निम्नलिखित क्या करना है:

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

सूचना है कि वापसी मान आप समारोह कॉल (@ से पहले समारोह नाम) पर त्रुटि दमन ऑपरेटर का उपयोग करने के लिए परीक्षण करने के लिए। इस तरह कोई अपवाद नहीं फेंक दिया जाएगा और निष्पादन जारी रहेगा।फिर आपको त्रुटि का परीक्षण करने के लिए सामान्य रूप से अपेक्षित अपवाद सेट करना होगा।

आप जो नहीं कर सकते हैं वह यूनिट परीक्षण के भीतर कई अपवादों का परीक्षण करता है।