2012-11-21 14 views
10

मैं एक अजगर कमांड लाइन-इंटरफेस कार्यक्रम पर काम कर रहा हूँ, और मैं इसे उबाऊ जब testings कर रही है, उदाहरण के लिए मिल जाए, यहां कार्यक्रम की मदद जानकारी है:अजगर CLI कार्यक्रम इकाई परीक्षण

usage: pyconv [-h] [-f ENCODING] [-t ENCODING] [-o file_path] file_path 

Convert text file from one encoding to another. 

positional arguments: 
    file_path 

optional arguments: 
    -h, --help   show this help message and exit 
    -f ENCODING, --from ENCODING 
         Encoding of source file 
    -t ENCODING, --to ENCODING 
         Encoding you want 
    -o file_path, --output file_path 
         Output file path 

जब मैंने प्रोग्राम पर बदलाव किए हैं और कुछ परीक्षण करना चाहते हैं, मुझे टर्मिनल खोलना होगा, कमांड टाइप करें (विकल्पों और तर्कों के साथ), एंटर टाइप करें, और देखें कि कोई त्रुटि चल रही है या नहीं। यदि त्रुटि वास्तव में होता है, मैं वापस संपादक के पास जाना चाहिए और अंत करने के लिए ऊपर से कोड जाँच, जहां बग पदों अनुमान लगा, छोटे बदलाव करने, print लाइनों, टर्मिनल के लिए वापसी लिखते हैं, फिर से चलाने के आदेश ...

रिकर्सिवली।

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

उत्तर

3

संक्षिप्त उत्तर है, हाँ है आप इकाई परीक्षण का उपयोग कर सकते हैं, और चाहिए। यदि आपका कोड अच्छी तरह से संरचित है, तो प्रत्येक घटक को अलग से जांचना बहुत आसान होना चाहिए, और यदि आपको अलग-अलग तर्कों के साथ चलने के अनुकरण के लिए हमेशा sys.argv का नकल करना पड़ता है।

0

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

उदाहरण:

python mycliprogram --someoption "some input" | diff correct_output -

यह और भी आसान, आप इन सभी परीक्षण जोड़ सकते हैं बनाने के अपने 'बनाने के परीक्षण' Makefile लक्ष्य है, जो मैं आप पहले से ही मान के लिए चलाता है। ;)

आप एक बार में इनमें से कई चला रहे हैं, आप इसे एक छोटे से अधिक स्पष्ट कर सकता है जहां हर एक को एक असफल टैग जोड़कर समाप्त होता है:

python mycliprogram --someoption "some input" | diff correct_output - || tput setaf 1 && echo "FAILED"

1

तो मेरा सवाल यह है कि, सीएलआई प्रोग्राम के साथ परीक्षण करने का सबसे अच्छा तरीका क्या है, क्या यह सामान्य पायथन स्क्रिप्ट के साथ यूनिट परीक्षण के रूप में आसान हो सकता है?

फर्क सिर्फ इतना है कि जब आप एक स्क्रिप्ट के रूप में पायथन मॉड्यूल चलाने के लिए, अपने __name__ विशेषता '__main__' पर सेट किया जाता है। तो आम तौर पर, यदि आप कमांड लाइन से अपनी स्क्रिप्ट चलाने का इरादा यह प्रपत्र निम्नलिखित होना चाहिए:

import sys 

# function and class definitions, etc. 
# ... 
def foo(arg): 
    pass 

def main(): 
    """Entry point to the script""" 

    # Do parsing of command line arguments and other stuff here. And then 
    # make calls to whatever functions and classes that are defined in your 
    # module. For example: 
    foo(sys.argv[1]) 


if __name__ == '__main__': 
    main() 

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

-1

आप मानक unittest मॉड्यूल का उपयोग कर सकते हैं:

# python -m unittest <test module> 

या एक परीक्षण ढांचे के रूप में nose का उपयोग करें।बस अलग निर्देशिका में क्लासिक unittest फ़ाइलों को लिखें और चलाएं:

# nosetests <test modules directory> 

लेखन unittests आसान है। बस online manual for unittesting

1

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

तो, अपने आवेदन को पुन: स्थापित करें ताकि आप एपीआई का परीक्षण कर सकें और एप्लिकेशन को स्वयं नहीं। लेकिन, आपके पास एक कार्यात्मक परीक्षण हो सकता है जो वास्तव में पूर्ण एप्लिकेशन चलाता है और जांच करता है कि आउटपुट सही है।

संक्षेप में, हाँ कोड का परीक्षण किसी अन्य कोड का परीक्षण के रूप में ही है, लेकिन आप यह सुनिश्चित करें कि अपने परिवर्तनों को सब कुछ नहीं टूटते एक पूरे के रूप में उनके संयोजन के बजाय अलग अलग हिस्सों का परीक्षण करना चाहिए।

6

मुझे लगता है कि पूरे कार्यक्रम स्तर पर कार्यात्मक रूप से परीक्षण करना बिल्कुल ठीक है। प्रति परीक्षण एक पहलू/विकल्प का परीक्षण करना अभी भी संभव है। इस तरह आप सुनिश्चित कर सकते हैं कि कार्यक्रम वास्तव में पूरी तरह से काम करता है। लेखन इकाई-परीक्षण आमतौर पर इसका मतलब है कि आप अपने परीक्षणों को तेज़ी से निष्पादित करते हैं और विफलताओं को समझना/समझना आम तौर पर आसान होता है। लेकिन यूनिट-टेस्ट आमतौर पर कार्यक्रम संरचना से अधिक बंधे होते हैं, जब आप आंतरिक रूप से चीजों को बदलते हैं तो अधिक रिफैक्टरिंग प्रयास की आवश्यकता होती है।

वैसे भी, py.test का उपयोग कर, यहाँ pyconv ::

# content of test_pyconv.py 

import pytest 

# we reuse a bit of pytest's own testing machinery, this should eventually come 
# from a separatedly installable pytest-cli plugin. 
pytest_plugins = ["pytester"] 

@pytest.fixture 
def run(testdir): 
    def do_run(*args): 
     args = ["pyconv"] + list(args) 
     return testdir._run(*args) 
    return do_run 

def test_pyconv_latin1_to_utf8(tmpdir, run): 
    input = tmpdir.join("example.txt") 
    content = unicode("\xc3\xa4\xc3\xb6", "latin1") 
    with input.open("wb") as f: 
     f.write(content.encode("latin1")) 
    output = tmpdir.join("example.txt.utf8") 
    result = run("-flatin1", "-tutf8", input, "-o", output) 
    assert result.ret == 0 
    with output.open("rb") as f: 
     newcontent = f.read() 
    assert content.encode("utf8") == newcontent 

के लिए UTF8 रूपांतरण के लिए एक latin1 परीक्षण pytest स्थापित करने के बाद ("पिप pytest स्थापित") आप इसे इस तरह से चला सकते हैं के लिए एक छोटे से उदाहरण है ::

$ py.test test_pyconv.py 
=========================== test session starts ============================ 
platform linux2 -- Python 2.7.3 -- pytest-2.4.5dev1 
collected 1 items 

test_pyconv.py . 

========================= 1 passed in 0.40 seconds ========================= 

उदाहरण pytest की स्थिरता तंत्र का लाभ उठाकर pytest के स्वयं के परीक्षण के कुछ आंतरिक मशीनरी पुनः उपयोग कर लेता, http://pytest.org/latest/fixture.html देखते हैं। यदि आप एक पल के विवरण के बारे में भूल जाते हैं, तो आप केवल इस तथ्य से काम कर सकते हैं कि परीक्षण चलाने और चलाने में आपकी सहायता के लिए "रन" और "tmpdir" प्रदान किए जाते हैं। यदि आप खेलना चाहते हैं, तो आप एक असफल जोर-कथन डालने या बस "जोर दें" डालने का प्रयास कर सकते हैं और फिर एक पायथन प्रॉम्प्ट दर्ज करने के लिए ट्रेसबैक देखें या "py.test --pdb" जारी करें।

+0

क्या 'रन' स्थिरता के साथ stdin और stdin का उपयोग करना संभव है? –