2008-10-10 12 views
47

मैं वर्तमान में PHPUnit के साथ काम कर रहा हूं, जो मैं लिख रहा हूं उसके साथ परीक्षण करने और विकसित करने के लिए, हालांकि, मैं वर्तमान में सत्र प्रबंधक लिखने पर काम कर रहा हूं, और मुझे ऐसा करने में समस्याएं हैं ...हेडर भेजने की आवश्यकता वाले आइटमों के साथ यूनिट परीक्षण

सत्र से निपटने वर्ग के लिए निर्माता

private function __construct() 
{ 
    if (!headers_sent()) 
    { 
     session_start(); 
     self::$session_id = session_id(); 
    } 
} 

है हालांकि, PHPUnit पाठ भेजता है के रूप में इससे पहले कि यह परीक्षण शुरू होता है, इस वस्तु पर किसी भी परीक्षण एक असफल परीक्षण देता है, HTTP "हेडर के रूप में "भेजा गया है ...

+0

मैंने अभी भी एक ही समस्या में भाग लिया है, लेकिन नीचे दिए गए कोई भी जवाब काम नहीं कर रहा है। अंत में आपने क्या किया? कृप्या मुझे ई - मेल करें। –

उत्तर

36

ठीक है, आपका सत्र प्रबंधक मूल रूप से डिज़ाइन द्वारा टूटा हुआ है। कुछ परीक्षण करने में सक्षम होने के लिए, इसे साइड इफेक्ट्स से अलग करना संभव होना चाहिए। दुर्भाग्य से, PHP को इस तरह से डिज़ाइन किया गया है, कि यह वैश्विक स्थिति (echo, header, exit, session_start इत्यादि आदि के उदार उपयोग को प्रोत्साहित करता है)।

सबसे अच्छी चीज जो आप कर सकते हैं, एक घटक में साइड इफेक्ट्स को अलग करना है, जिसे रनटाइम पर बदला जा सकता है। इस तरह, आपके परीक्षण मॉक ऑब्जेक्ट्स का उपयोग कर सकते हैं, जबकि लाइव कोड एडाप्टर का उपयोग करता है, जिनके वास्तविक दुष्प्रभाव होते हैं। आप पाएंगे कि यह सिंगलेट्स के साथ अच्छा नहीं खेलता है, जो मुझे लगता है कि आप इसका उपयोग कर रहे हैं। तो आपको अपने कोड में वितरित साझा वस्तुओं को प्राप्त करने के लिए कुछ अन्य तंत्र का उपयोग करना होगा। आप एक स्थिर रजिस्ट्री से शुरू कर सकते हैं, लेकिन अगर आपको कुछ सीखने की कोई बात नहीं है तो बेहतर समाधान भी हैं।

यदि आप ऐसा नहीं कर सकते हैं, तो आपके पास हमेशा एकीकरण-परीक्षण लिखने का विकल्प होता है। उदाहरण के लिए। PHPUnit के WebTestCase के बराबर का उपयोग करें।

+0

धन्यवाद, मुझे इस कठिन प्यार की ज़रूरत है! मेरा डिजाइन अब निर्विवाद रूप से बेहतर है कि मैंने अपनी शेष कक्षा से पर्यावरण दुष्प्रभावों को अलग कर दिया है। – DaveGauer

+1

वेबटेस्टकेस के लिए प्रलेखन अब http://www.simpletest.org/en/web_tester_documentation.html पर है। – untill

0

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

भले ही ओबी आपके वर्गों के अंदर कहीं भी उपयोग किया जाता है, यह स्थिर है और ओबी को अंदर क्या हो रहा है को प्रभावित नहीं करना चाहिए।

+0

ऐसा लगता है कि ob_start() वास्तव में रीसेट नहीं करता है कि PHP सोचता है कि हेडर भेजे जाते हैं या नहीं। – Mez

+0

हाँ, ob_start हेडर के साथ काम नहीं करता है, ताकि यदि आप इसका उपयोग करते हैं, तब भी यह शिकायत करेगा कि हेडर अब और नहीं भेजे जा सकते हैं। मैं इसके लिए PHPUnit संपादित कर सकता हूं हालांकि ... – Mez

0

जहां तक ​​मुझे पता है कि ज़ेंड फ्रेमवर्क उनके Zend_Session पैकेज परीक्षणों के लिए एक ही आउटपुट बफरिंग का उपयोग करता है। आप शुरू करने के लिए अपने परीक्षण मामलों पर एक नज़र डाल सकते हैं।

5

मुझे लगता है कि "दाएं" समाधान एक बहुत ही सरल वर्ग (इतना आसान है कि इसे परीक्षण करने की आवश्यकता नहीं है) बनाना है जो PHP के सत्र से संबंधित कार्यों के लिए एक रैपर है, और session_start() आदि को कॉल करने के बजाय इसका उपयोग करें। सीधे।

परीक्षण में वास्तविक स्थितिपूर्ण, अवांछित सत्र कक्षा के बजाय मैक ऑब्जेक्ट में पास करें।

session_start(); 

तो इस तरह PHPUnit शुरू:

phpunit --bootstrap pathToBootstrap.php --anotherSwitch /your/test/path/ 

बूटस्ट्रैप फ़ाइल बाकी सब से पहले कहा जाता हो जाता है, तो हैडर hasn

private function __construct(SessionWrapper $wrapper) 
{ 
    if (!$wrapper->headers_sent()) 
    { 
     $wrapper->session_start(); 
     $this->session_id = $wrapper->session_id(); 
    } 
} 
20

PHPUnit के लिए एक बूटस्ट्रैप फ़ाइल है, जो कहता है बनाएं भेजा नहीं गया है और सब कुछ ठीक काम करना चाहिए।

+1

यदि आप एक एक्सएमएल कॉन्फ़िगरेशन फ़ाइल का उपयोग कर रहे हैं, तो आप अपने रूट '' तत्व में बूटस्ट्रैप विशेषता जोड़कर बूटस्ट्रैप सेट अप कर सकते हैं: ' ... ' –

0

बूटस्ट्रैप फ़ाइल का निर्माण, 4 पदों की ओर इशारा करते हुए इस चारों ओर सबसे साफ तरीका लगता है।

अक्सर PHP के साथ हमें बनाए रखना होता है, और विरासत परियोजनाओं के लिए किसी प्रकार का इंजीनियरिंग अनुशासन जोड़ने की कोशिश की जाती है जो अबाध रूप से एक साथ रखी जाती है।हमारे पास बकवास के पूरे ढेर को कुचलने और फिर से शुरू करने का समय (या प्राधिकरण) नहीं है, इसलिए troelskn द्वारा पहला एवर हमेशा आगे बढ़ने के रूप में संभव नहीं है। (यदि हम प्रारंभिक डिज़ाइन पर वापस जा सकते हैं, तो हम पूरी तरह से PHP को डुबो सकते हैं और वेब विकास दुनिया के इस कोबोल को बनाए रखने में मदद के बजाय रूबी या पायथन जैसे कुछ आधुनिक का उपयोग कर सकते हैं।)

यदि आप हैं एक बूस्ट्रैप फ़ाइल में सत्र शुरू करने से, मॉड्यूल के लिए यूनिट परीक्षण लिखने का प्रयास कर रहे हैं जो सत्र_स्टार्ट या सेटक्यूकी का उपयोग करते हैं, इन मुद्दों को आपके दौर में ले जाते हैं।

19

phpUnit परीक्षणों के रूप में आउटपुट प्रिंट करता है जिससे सिरर्स_सेंट() आपके पहले परीक्षण में भी सही हो जाता है।

पूरे परीक्षण सूट के लिए इस समस्या को दूर करने के लिए आपको बस अपनी सेटअप स्क्रिप्ट में ob_start() का उपयोग करने की आवश्यकता है।

उदाहरण के लिए, कहें कि आपके पास AllTests.php नाम की एक फ़ाइल है जो phpUnit द्वारा लोड की गई पहली चीज़ है।

<?php 

ob_start(); 

require_once 'YourFramework/AllTests.php'; 

class AllTests { 
    public static function suite() { 
     $suite = new PHPUnit_Framework_TestSuite('YourFramework'); 
     $suite->addTest(YourFramework_AllTests::suite()); 
     return $suite; 
    } 
} 
+2

ब्लैक बॉक्स PHP कोड का परीक्षण करने के लिए सबसे अच्छा समाधान आप नहीं बदल सकते हैं। – Ando

+0

ध्यान दें कि PHP 3.6 अब यह स्वचालित रूप से करता है। –

+2

यह समाधान मेरे लिए काम करता है: डी PHPUnit 3.6 इसे लागू करने वाला है लेकिन मेरे लिए सही ढंग से काम नहीं करता है। मैंने ob_start() जोड़ा; मेरी bootstrap.php फ़ाइल में और कुकीज़ और हेडर के साथ मेरे सभी परीक्षण सही ढंग से काम करना शुरू कर दिया। – Tim

0

मैं अपने बूटस्ट्रैप unittesting कर रहा हूँ के रूप में (हाँ मैं जानता हूँ कि आप में से अधिकांश कि ऐसा नहीं करते हैं), मैं एक ही समस्या में चल रहा हूँ (दोनों शीर्ष लेख: यह स्क्रिप्ट दिखाई दे सकता है() और session_start())। समाधान मैंने पाया बल्कि सरल है, अपने unittest में बूटस्ट्रैप एक निरंतर परिभाषित करने और बस हैडर सत्र भेजने या शुरू करने से पहले यह जाँच:

// phpunit_bootstrap.php 
define('UNITTEST_RUNNING', true); 

// bootstrap.php (application bootstrap) 
defined('UNITTEST_RUNNING') || define('UNITTEST_RUNNING', false); 
..... 
if(UNITTEST_RUNNING===false){ 
    session_start(); 
} 

मैं मानता हूँ कि इस डिजाइन से सही नहीं है, लेकिन मैं कर रहा हूँ मौजूदा अनुप्रयोग को बेकार करना, बड़े हिस्सों को फिर से लिखना वांछित नहीं है। मैं __call() और __set() जादू विधियों का उपयोग करके निजी विधियों का परीक्षण करने के लिए एक ही तर्क का उपयोग कर रहा हूं।

public function __set($name, $value){ 
    if(UNITTEST_RUNNING===true){ 
     $name='_' . $name; 
     $this->$name=$value; 
    } 
    throw new Exception('__set() can only be used when unittesting!'); 
} 
11

मैं एक ही मुद्दा था और मैं सिर्फ इस तरह --stderr ध्वज के साथ PHPUnit फोन करके इसे हल:

phpunit --stderr /path/to/your/test 

आशा है कि यह किसी को मदद करता है!

+0

खोज के एक या दो घंटे बाद यह सबसे आसान और सबसे अच्छा समाधान था जिससे मुझे कोडक्यूकी() को अंदर डालने वाले कोड का परीक्षण करने की अनुमति मिल सके। @runInSeparateProcess का उपयोग अन्य मुद्दों का कारण बनता है जबकि यह सही है (अभी के लिए)। – Frug

1

मैं क्यों कोई सूचीबद्ध किया है XDebug विकल्प सोच रहा हूँ:

/** 
* @runInSeparateProcess 
* @requires extension xdebug 
*/ 
public function testGivenHeaderIsIncludedIntoResponse() 
{ 
    $customHeaderName = 'foo'; 
    $customHeaderValue = 'bar'; 

    // Here execute the code which is supposed to set headers 
    // ... 

    $expectedHeader = $customHeaderName . ': ' . $customHeaderValue; 
    $headers = xdebug_get_headers(); 

    $this->assertContains($expectedHeader, $headers); 
} 
0

ऐसा लगता है कि तुम इतनी है कि आप अपने कोड का परीक्षण कर सकते सत्र इंजेक्षन की जरूरत है। मैंने उपयोग किया है कि सबसे अच्छा विकल्प प्रमाणीकरण प्रक्रिया के लिए Aura.Auth है और परीक्षण के लिए NullSession और NullSegment का उपयोग कर।

Aura testing with null sessions

आभा ढांचे खूबसूरती से लिखा है और आप किसी भी अन्य आभा ढांचे निर्भरता के बिना अपने दम पर Aura.Auth उपयोग कर सकते हैं।

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