2010-08-04 4 views
9

मैं स्कालाटेस्ट का उपयोग करके स्कैला में लिखे गए एक पार्सर का परीक्षण कर रहा हूं। पार्सर एक समय में एक फ़ाइल हैंडल और यह निम्नलिखित की तरह एक सिंगलटन वस्तु है:स्कैलाटेस्ट: सिंगलटन ऑब्जेक्ट पुन: प्रारंभिकरण के साथ मुद्दे

class Parser{...} 
object Resolver {...} 

परीक्षण का मामला मैं लिखा है इस

describe("Syntax:") { 
    val dir = new File("tests\\syntax"); 
    val files = dir.listFiles.filter(
        f => """.*\.chalice$""".r.findFirstIn(f.getName).isDefined); 

    for(inputFile <- files) { 
     val parser = new Parser(); 
     val c = Resolver.getClass.getConstructor(); 
     c.setAccessible(true); 
     c.newInstance(); 

     val iserror = errortest(inputFile) 
     val result = invokeparser(parser,inputFile.getAbsolutePath) //local method 
     it(inputFile.getName + (if (iserror)" ERR" else " NOERR")){ 
     if (!iserror) result should be (ResolverSuccess()) 
     else if(result.isInstanceOf[ResolverError]) assert(true) 
     } 
    } 
    } 

अब पिछले के साइड इफेक्ट यात्रा प्रत्येक पर की तरह कुछ हद तक है सिंगलटन ऑब्जेक्ट रिजॉल्वर के अंदर पुनरावृत्तियों को साफ़ नहीं किया जाता है।

क्या सिंगलटन ऑब्जेक्ट को फिर से शुरू करने के लिए स्केलेटेस्ट मॉड्यूल को निर्दिष्ट करने का कोई तरीका है?

अद्यतन: डैनियल के सुझाव का उपयोग करना, मैं कोड को अद्यतन किया है, यह भी अधिक जानकारी के लिए जोड़ा।

अद्यतन: स्पष्ट रूप से यह पार्सर है जो कुछ ख़राब कर रहा है। बाद की कॉल में यह पिछले एएसटी को त्याग नहीं करता है। अजीब। के बाद से इस विषय बंद है, मैं और अधिक सब

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

+0

क्या 'आर' के अंदर कोई क्लीन-अप विधि है, या क्या आप इसे फिर से बनाए जाने की उम्मीद करते हैं? –

+0

आर में कोई क्लीनअप विधि नहीं है और मैं कोड नहीं बदल सकता। क्या आप स्कैला में सिंगलटन ऑब्जेक्ट्स को फिर से बना सकते हैं? – thequark

+0

नहीं। वे सख्ती से सिंगलेट हैं। ऑन-डिमांड शुरू किया गया (जैसा कि जेवीएम के वर्ग लोडिंग द्वारा निर्धारित किया गया है) और उसके बाद शाश्वत। वे निश्चित रूप से किसी भी स्काला कक्षाओं के साथ, परिवर्तनीय आंतरिक स्थिति हो सकती है। –

उत्तर

7

भाषा spec के अनुसार, नहीं, सिंगलटन ऑब्जेक्ट्स को फिर से बनाने का कोई तरीका नहीं है। हालांकि, यह संभव है संजीदगी से एक सिंगलटन है, जो आंतरिक MODULE$ क्षेत्र है जो वास्तविक सिंगलटन मान अधिलेखित कर देता है के निर्माता आह्वान करने के लिए:

object Test 

Test.hashCode // => e.g. 779942019 

val c = Test.getClass.getConstructor() 
c.setAccessible(true) 
c.newInstance() 

Test.hashCode // => e.g. 1806030550 

अब जब कि मैं तुम्हारे साथ बुराई गुप्त साझा किया है, मुझे सावधानी बरतें, ऐसा करने के लिए कभी भी। मैं इस तरह की चुस्त चाल चलाने के बजाए कोड को समायोजित करने के लिए बहुत मेहनत करूँगा। हालांकि, अगर चीजें आप कहती हैं, और आपके पास वास्तव में कोई अन्य विकल्प नहीं है, तो यह कम से कम कुछ है।

+1

इस तरह से सिंगलटन ऑब्जेक्ट का पुन: प्रारंभिक कार्य करता है लेकिन मेरी समस्या अभी भी बनी हुई है। मुझे नहीं पता कि कैसे। असल में यदि मैं व्यक्तिगत रूप से प्रत्येक इनपुटफाइल का परीक्षण करता हूं तो यह ठीक काम करता है लेकिन यदि मैं उन्हें एक साथ परीक्षण करता हूं तो मुझे त्रुटि मिलती है। अगर मैं ऑर्डर बदलता हूं तो मुझे भी एक त्रुटि मिलती है (पिछले टेस्ट केस से संबंधित त्रुटि संदेशों के साथ!)। मुझे संदेह है कि कारण हो सकता है क्योंकि सिंगलटन ऑब्जेक्ट के पिछले पुनरावृत्तियों से साइड इफेक्ट्स हैं। – thequark

+0

कोशिश की, यह मिल गया ... java.lang.No.SuchMethodException: com.whatever.SingletonObject $। () – jm0

+0

मुझे उपरोक्त @ daniel-spiewak उदाहरण को 'वैल सी = टेस्ट.getClass.getDeclaredConstructor() ' –

4

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

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

आपको पार्सर & क्लासपाथ से बाहर और रनपाथ के बंद करने की आवश्यकता होगी। उन्हें अपनी निर्देशिका में रखो। फिर उस निर्देशिका को इंगित करने वाले प्रत्येक परीक्षण के लिए URLClassLoader बनाएं।फिर उस क्लास लोडर पर FindClass ("पार्सर") को कॉल करने के लिए कॉल करें। मुझे लगता है कि पार्सर रिजॉल्वर को संदर्भित करता है, और उस स्थिति में JVM क्लास लोडर पर वापस जायेगा जो रिज़ॉल्वर प्राप्त करने के लिए पार्सर को लोड करता है, जो आपका URLClassLoader है। उदाहरण प्राप्त करने के लिए पार्सर पर एक नया प्रवेश करें। इससे आपकी समस्या हल होनी चाहिए, क्योंकि आपको प्रत्येक परीक्षण के लिए एक नया रिजॉल्वर सिंगलटन ऑब्जेक्ट मिलेगा।

+0

नया पार्सर बनाने से पहले सिंगलटन ऑब्जेक्ट को पुन: प्रारंभ नहीं किया गया है और पार्सर ऑब्जेक्ट सृजन लूप के अंदर है । (अद्यतन कोड की जांच करें) कोड एक निष्पादन ट्रेस में एक इनपुट फ़ाइल को स्वीकार करने के लिए बनाया गया था। – thequark

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

  • कोई संबंधित समस्या नहीं^_^