unit testing Groovy स्क्रिप्ट में बाहर निकलने की स्थिति कैसे सेट करें




unit-testing exit-code (2)

ये तकनीक है जो हम अंततः प्रयोग करते थे।

हम सिर्फ System.exit() को कॉल की उपेक्षा नहीं कर सकते, क्योंकि स्क्रिप्ट चलाना जारी रहेगा। इसके बजाय हम इच्छित स्थिति कोड के साथ एक अपवाद फेंकना चाहते हैं। जब System.exit() को हमारे परीक्षणों में बुलाया जाता है, तो हम एक (कस्टम) ProgramExitException फेंकते हैं

class ProgramExitException extends RuntimeException {

    int statusCode

    public ProgramExitException(int statusCode) {
        super("Exited with " + statusCode)
        this.statusCode = statusCode
    }
}

तो हम इस अपवाद को फेंकने के लिए System.exit() को रोकते हैं

/**
 * Make System.exit throw ProgramExitException to fake exiting the VM
 */
System.metaClass.static.invokeMethod = { String name, args ->
    if (name == 'exit')
        throw new ProgramExitException(args[0])
    def validMethod =  System.metaClass.getStaticMetaMethod(name, args)
    if (validMethod != null) {
        validMethod.invoke(delegate, args)
    }
    else {
        return  System.metaClass.invokeMissingMethod(delegate, name, args)
    }
}

और अंत में हमारे पास GroovyShell को कोई ProgramExitException GroovyShell पकड़ कर और run विधि से स्टेटस कोड वापस कर दिया है।

/**
 * Catch ProgramExitException exceptions to mimic exit status codes
 * without exiting the VM
 */
GroovyShell.metaClass.invokeMethod = { String name, args ->
    def validMethod = GroovyShell.metaClass.getMetaMethod(name, args)
    if (validMethod != null) {
        try {
            validMethod.invoke(delegate, args)
        } catch (ProgramExitException e) {
            return e.statusCode
        }
    }
    else {
        return GroovyShell.metaClass.invokeMissingMethod(delegate, name, args)
    }
 }

हमारे परीक्षण सरल देख सकते हैं, हमें स्क्रिप्ट्स में कुछ भी बदलने की आवश्यकता नहीं है और हमें वह आदेश मिलता है जो हम कमांड लाइन पर चलने की उम्मीद करते हैं।

assertEquals 'Unexpected status code', 0, shell.run(script,[arg1, arg2])
assertEquals 'Unexpected status code', 10, shell.run(script,[badarg1, badarg2])

हमारे पास ग्रूवी स्क्रिप्ट है जो 0 status के साथ बाहर निकलता है, जब सब कुछ काम करता है और विभिन्न प्रकार की असफलता स्थितियों के लिए non-0 status । उदाहरण के लिए यदि स्क्रिप्ट ने एक उपयोगकर्ता और ईमेल पता को तर्क के रूप में लिया है तो यह एक अमान्य उपयोगकर्ता के लिए 1 status और एक अमान्य ईमेल पता प्रारूप के लिए 2 status से बाहर निकल जाएगा। हम इसके लिए System.exit(statusCode) उपयोग करते हैं। यह ठीक काम करता है, लेकिन स्क्रिप्ट के लिए परीक्षण के मामलों को लिखना मुश्किल बनाता है।

एक परीक्षण में हम अपना GroovyShell बनाते हैं, हमारी Binding और कॉल shell.run(script,args) बनाएँ। shell.run(script,args) । विफलता की स्थितियों का दावा करने वाले परीक्षणों के लिए, System.exit() JVM (और परीक्षण) को बाहर करने के कारण होता है

क्या Groovy Script से बाहर निकलने के लिए System.exit() का उपयोग करने के विकल्प हैं? मैंने बिना किसी अपवादों को फेंकने के साथ प्रयोग किया, लेकिन यह झुंड आउटपुट और हमेशा स्थिति कोड 1 बनाता है

हमारे परीक्षण मामलों में मैंने System.metaClass.static.invokeMethod का उपयोग करने के लिए System.exit() के व्यवहार को बदलने के लिए भी प्रयोग किया है जो कि जेवीएम से बाहर नहीं निकलता है, लेकिन यह एक बदसूरत हैक की तरह लगता है।


imho System.metaClass.static.invokeMethod ठीक लग रहा है। यह परीक्षण है, और हैकिंग ठीक है यहाँ।

इसके अलावा आप अपने चारों ओर अपना आवरण बना सकते हैं, जैसे:

class ExitUtils {

    static boolean enabled = true

    static exit(int code) {
        if (!ExitUtils.enabled) {
            return  //TODO set some flag?
        }
        System.exit(code)
    }

}

और परीक्षणों के लिए इसे अक्षम करें





exit-code