unit testing - Groovy स्क्रिप्ट में बाहर निकलने की स्थिति कैसे सेट करें
unit-testing exit-code (2)
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)
}
}
और परीक्षणों के लिए इसे अक्षम करें
हमारे पास ग्रूवी स्क्रिप्ट है जो 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()
के व्यवहार को बदलने के लिए भी प्रयोग किया है जो कि जेवीएम से बाहर नहीं निकलता है, लेकिन यह एक बदसूरत हैक की तरह लगता है।
ये तकनीक है जो हम अंततः प्रयोग करते थे।
हम सिर्फ 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])