2014-07-22 10 views
9

मैं यह स्वीकार करके यह प्रस्ताव दूंगा कि मैं शायद कुछ कर रहा हूं जो मुझे नहीं करना चाहिए। लेकिन चूंकि मैं पहले से ही यह गहरा हूं, इसलिए मैं समझ सकता हूं कि इस तरह से चीजें क्यों हो रही हैं।मोचा परीक्षणों के दौरान stdout और stderr को म्यूट करना

मैं कुछ नोड.जेएस कोड का परीक्षण करने के लिए मोचा का उपयोग कर रहा हूं। यह कोड विंस्टन लॉगिंग लाइब्रेरी का उपयोग करता है, जो सीधे process.stdout.write() और process.stderr.write() (source) पर कॉल करता है। यह अच्छा काम करता है; मुझे उस व्यवहार के बारे में कोई शिकायत नहीं है।

हालांकि, जब मैं इकाई परीक्षण इस कोड, मोचा परीक्षण धावक के उत्पादन में कभी-कभी लॉग उत्पादन है, जो कुछ संवाददाताओं (dot, bdd) है और उसका दुरूपयोग अमान्य दूसरों में (xunit) में बदसूरत है की लाइनों के साथ बीच-बीच में है। मैं विंस्टन को संशोधित या उपclass किए बिना इस आउटपुट को अवरुद्ध करना चाहता था, और अगर मैं इससे बच सकता तो मैं एप्लिकेशन को संशोधित करना चाहता था।

क्या मैं पर पहुंचे उपयोगिता कार्यों का एक सेट है कि अस्थायी तौर पर एक नहीं सेशन समारोह के साथ नोड builtins जगह ले सकता है, और इसके विपरीत था:

var stdout_write = process.stdout._write, 
    stderr_write = process.stderr._write; 

function mute() { 
    process.stderr._write = process.stdout._write = function(chunk, encoding, callback) { 
     callback(); 
    }; 
} 

function unmute() { 
    process.stdout._write = stdout_write; 
    process.stderr._write = stderr_write; 
} 

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

अब यह अजीब हो जाता है!

पहली बार के लिए, मैं एक फाइल करने के लिए उत्पादन पुनः निर्देशित करने की कोशिश की:

mocha spec_file.js > output.txt 

अवांछित उत्पादन वापस आ गया! आउटपुट के प्रत्येक टुकड़े जो stdout को भेजा गया था फ़ाइल में प्रकट होता है। 2>&1 जोड़ना, मुझे फ़ाइल में भी stderr मिलता है। हालांकि, किसी भी मामले में कंसोल पर कुछ भी नहीं दिखाई देता है।

परीक्षण कोड दो आमंत्रणों के बीच इतना अलग व्यवहार क्यों करेगा? मेरा आंत अनुमान यह है कि मोचा यह निर्धारित करने के लिए कुछ प्रकार का परीक्षण कर रहा है कि यह एक टीटीवी को लिख रहा है या नहीं, लेकिन मैं एक स्पष्ट स्थान नहीं देख सका जहां यह अपने लेखन के व्यवहार को बदलता है।

इसके अलावा व्यापक सवाल है, वहाँ किसी भी सही तरह से परीक्षण के दौरान stdout/stderr म्यूट करने के लिए है, एक सशर्त में सभी संभावित-लॉगिंग एप्लिकेशन कोड लपेटकर बिना कि परीक्षण वातावरण के लिए चेक?

+0

विंस्टन पता नहीं है, लेकिन है यह जाँच करता है कि stdout और stderr एक tty हैं या नहीं, और यदि हां अलग ढंग से व्यवहार करती है संभव है (जैसे:, रंग में प्रवेश करने आदि)? यदि ऐसा है, तो मुझे लगता है कि 'लिखने' और '_write' को ओवरराइड न करें, बल्कि" शून्य "स्ट्रीम बनाएं और' stdout' और 'stderr' को पूरी तरह से बदलें। मैं आश्चर्यचकित हूं कि विंस्टन के लिए "ग्लोबल सेटिंग" नहीं था, बस ऐसा करने के लिए: म्यूट। (कहें: कम से कम लॉग स्तर कम करें)। –

उत्तर

2

मुझे इस व्यवहार के लिए संभावित कारण पता चला। यह वास्तव में करना है कि stdout/stderr एक टीटीवी है या नहीं।

स्क्रिप्ट एक कंसोल में चलता है, इन दोनों TTYs हैं, और process.stdout और process.stderr,, tty.WriteStream की नहीं उदाहरणों और प्रतीत रूप में मैं मूल रूप से मान लिया है एक stream.Writable। जहां तक ​​मेरी बातचीत हुई, दोनों वर्ग वास्तव में अलग नहीं थे - दोनों में write() विधियां थीं जिन्हें आंतरिक _write() विधियों कहा जाता था, और दोनों ने एक ही विधि हस्ताक्षर साझा किए थे।

जब फ़ाइल में पाइप किया जाता है, तो चीजें थोड़ा अलग हो जाती हैं। process.stdout और process.stderr एक अलग वर्ग के उदाहरण थे जो तुरंत परिचित नहीं थे। सबसे अच्छा मैं समझ सकता हूं, यह fs. SyncWriteStream है, लेकिन यह अंधेरे में एक स्टैब है। वैसे भी, इस वर्ग में _write() विधि नहीं है, इसलिए इसे ओवरराइड करने का प्रयास करना व्यर्थ था।

समाधान एक स्तर ऊपर स्थानांतरित करना था और _write() के बजाय write() के साथ मेरा उत्परिवर्तन करना था। यह वही काम करता है, और यह निरंतर ध्यान देता है कि आउटपुट कहां जा रहा है।

5

https://www.npmjs.org/package/mute देखें

it('should shut the heck up', function (done) { 
    var unmute = mute() 
    app.options.defaults = true; 

    app.run(function() { 
     unmute(); 

     helpers.assertFiles([ 
      ['package.json', /"name": "temp-directory"/], 
      ['README.md', /# TEMP.Directory/] 
     ]); 

     done(); 
    }); 
}); 
संबंधित मुद्दे