2009-08-28 7 views
30

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

मुझे इसका परीक्षण कैसे करना चाहिए? जब मैं phpunit चलाता हूं यह उस परीक्षण के लिए कुछ भी वापस नहीं करता है, और पूरी तरह बंद हो जाता है।

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

क्या कोई बेहतर तरीका है?

उत्तर

22

के रूप में हर परीक्षण ही PHPUnit प्रक्रिया द्वारा चलाए जा रहे हैं, यदि आप बाहर निकल का उपयोग/अपने PHP कोड में मर जाते हैं, आप सब कुछ मार देंगे - के रूप में आपने देखा ^^

तो, आप एक और समाधान खोजने के लिए है, हाँ - मरने की बजाए लौटने की तरह; या एक अपवाद फेंकना (आप परीक्षण कर सकते हैं कि कुछ परीक्षण कोड ने अपेक्षित अपवाद फेंक दिया है)

शायद PHPUnit 3.4 और यह --process-isolation स्विच है (देखें Optionally execute each test using a separate PHP process) पराक्रम मदद , लेकिन आप अभी भी परीक्षण के परिणाम प्राप्त करने में सक्षम नहीं होगा, अगर PHPUnit नहीं है (मर सब कुछ नहीं होने से) नियंत्रण वापस प्राप्त करें।

मुझे यह समस्या दो बार मिली है; मरने की जगह लौटने से इसे हल करके हल किया गया - कॉल स्टैक में "उच्च पर्याप्त" वापस जाने के लिए, यदि आवश्यक हो तो कई बार लौटाना ^^
अंत में, मुझे लगता है कि मेरे पास अब कोई "मर" नहीं है आवेदन ... एमवीसी, बीटीडब्ल्यू के बारे में सोचते समय यह शायद बेहतर है।

+0

हाँ, अभी मैंने अपवाद फेंकने का फैसला किया है। समस्या यह है कि मेरा डिफ़ॉल्ट अपवाद हैंडलर इस फ़ंक्शन को कॉल करने का इरादा रखता है, इसलिए मुझे killProgramException नामक एक नया अपवाद बनाना है जो मेरा अपवाद हैंडलर अनदेखा करता है। हैकी –

7

मुझे पता है आप पहले से ही इस के लिए एक जवाब स्वीकार कर लिया है और यह एक पुराने सवाल है, लेकिन मैं समझ यह किसी के लिए उपयोगी हो सकता है, इसलिए यहाँ जाता है:

इसके बजाय die() उपयोग कर, आप throw new RuntimeException() इस्तेमाल कर सकते हैं (या अपने आप का एक अपवाद वर्ग), जो प्रोग्राम निष्पादन को रोक देगा (यद्यपि एक अलग फैशन में) और इसे पकड़ने के लिए PHPUnit के setExpectedException() का उपयोग करें। यदि आप अपनी स्क्रिप्ट die() पर चाहते हैं, तो उस अपवाद का सामना करना पड़ता है, तो उपयोगकर्ता के स्तर पर बिल्कुल कुछ भी प्रिंट नहीं करना, set_exception_handler() पर एक नज़र डालें।

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

+3

की तरह जब मैं एक पुरानी पोस्ट मेरे प्रश्न का उत्तर देता हूं तो इसे प्यार करें। – stefgosselin

+0

यह उत्तर मूल रूप से प्रवाह नियंत्रण संरचनाओं के रूप में अपवादों का उपयोग करने का सुझाव देता है, जो आम तौर पर वांछनीय नहीं है। –

13

कोड को बदलने की आवश्यकता नहीं है बस इसे जांचने में सक्षम होने के लिए, आप बस set_exit_overload() (test_helpers द्वारा उसी लेखक से PHPUnit के रूप में प्रदान किया जा सकता है) का उपयोग कर सकते हैं।

+1

आलसी के लिए लिंक: https://github.com/php-test-helpers/php-test-helpers (ध्यान दें कि यह एक PHP एक्सटेंशन है जिसे आपको अपने php.ini में सक्रिय करने की आवश्यकता है) –

+1

नोट: यह प्रोजेक्ट है अब बनाए रखा नहीं है (2014 के बाद से)। – amphetamachine

3

यह उन मुद्दों के सेट से संबंधित है जो मुझे परीक्षा उत्तीर्ण करने के लिए कुछ विरासत कोड प्राप्त कर रहे हैं। इसलिए मैं() Testable :: exitphp के साथ इस तरह एक Testable वर्ग के साथ आए हैं ...

class Testable { 
    static function exitphp() { 
     if (defined('UNIT_TESTING')) { 
     throw new TestingPhpExitException(); 
     } else { 
     exit(); 
     } 
    } 
} 

अब मैं बस से बाहर निकलने के लिए कॉल की जगह()।

यदि यह परीक्षण में है तो मैं केवल UNIT_TESTING को परिभाषित करता हूं, उत्पादन में मैं नहीं करता हूं। एक साधारण मॉक की तरह लगता है।

+0

आईएमओ, यह बहुत ही सुरुचिपूर्ण है। धन्यवाद। –

+1

यह शुरुआत में अच्छा लग सकता है, लेकिन यह परीक्षण के लिए कार्यक्रम के व्यवहार को बदल रहा है, जो अंत में अच्छा नहीं होगा IMHO –

16

यह स्पष्ट रूप से एक पुराना सवाल है, लेकिन मेरा सुझाव कोड को die() पर ले जाने के लिए एक अलग विधि में स्थानांतरित करना होगा जिसे आप नकली कर सकते हैं।

उदाहरण के लिए, बजाय यह होने का:

class SomeClass 
{ 
    public function do() 
    { 
     $this->terminate(123); 
     // or 
     $this->terminate('Message'); 
    } 

    protected function terminate($code = 0) 
    { 
     exit($code); 
    } 

    // or 
    protected function terminate($message = '') 
    { 
     die($message); 
    } 
} 

इस तरह आप आसानी से terminate विधि नकली सकता है और आप के बारे में चिंता करने की ज़रूरत नहीं है:

class SomeClass 
{ 
    public function do() 
    { 
     exit(1); 
     // or 
     die('Message'); 
    } 
} 

ऐसा करने स्क्रिप्ट समाप्त होने के बिना आप इसे पकड़ने में सक्षम हैं।

class SomeClassTest extends \PHPUnit_Framework_TestCase 
{ 

    /** 
    * @expectedExceptionCode 123 
    */ 
    public function testDoFail() 
    { 
     $mock = $this->getMock('SomeClass'); 
     $mock->expects($this->any()) 
      ->method('terminate') 
      ->will($this->returnCallback(function($code) { 
       throw new \Exception($code); 
      })); 

     // run to fail 
     $mock->do(); 
    } 
} 

मैं कोड का परीक्षण नहीं किया है, लेकिन बहुत एक काम राज्य के करीब होना चाहिए:

आपका परीक्षण कुछ इस तरह दिखेगा।

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