2011-02-01 17 views
5

मैं पायथन का उपयोग कर शुरुआत प्रोग्रामिंग कक्षा के लिए एक ग्रेडर हूं। मेरा पायथन-फू खुद इतना मजबूत नहीं है, लेकिन मैं कुछ ग्रेडिंग स्वचालित करने की कोशिश करना चाहता हूं।मैं शुरुआती छात्र पायथन कार्यक्रमों का परीक्षण कैसे करूं जो इनपुट() (शायद unittest के साथ?) का उपयोग करें?

ऑनलाइन देख रहे हैं, मुझे PyUnit परीक्षण सूट पसंद है, हालांकि यह संभवतः मेरे इच्छित चीज़ों के लिए थोड़ा अधिक है।

मेरी समस्या यह है कि मुझे यकीन नहीं है कि मैं छात्र इनपुट के लिए इच्छित इनपुट इनपुट कैसे पास कर सकता हूं, क्योंकि वे कमांड लाइन तर्क या यहां तक ​​कि कई फ़ंक्शंस का उपयोग नहीं कर रहे हैं, लेकिन input() फ़ंक्शन के माध्यम से उपयोगकर्ता इनपुट प्राप्त कर रहे हैं।

एक मूर्खतापूर्ण उदाहरण:

#/usr/bin/python3.1 
# A silly example python program 
def main(): 
    a = int(input("Enter an integer: ")) 
    b = int(input("Enter another integer: ")) 
    c = a+b 
    print("The sum is %d" % c) 

if __name__ == '__main__' 
    main() 

मेरी मूर्खतापूर्ण उदाहरण के लिए, मैं कैसे एक इकाई परीक्षण है कि कई अलग अलग इनपुट के लिए उत्पादन की जांच कर सकता लिखना चाहते हैं? (यानी, यदि मैं इनपुट में 2 और 3 पास करता हूं, तो आउटपुट स्ट्रिंग "योग 5 है")

+0

दो इनपुट लाइनों में दाएं कोष्ठक गायब हैं। – Javier

+0

@ जेवियर: फिक्स्ड। धन्यवाद, किसी ने मेरे प्रश्न को संपादित किया और 'eval (' लेकिन दूसरी तरफ बंद नहीं किया। – Jason

उत्तर

8

संपादित करें: उदाहरण के बाद से इसका प्रस्ताव केवल एकजुट नहीं है (और मैं मान रहा हूं शुरुआती छात्रों को केवल बाधा से उलझन में डाल दिया जाएगा)

यदि आप आउटपुट से संबंधित हैं जो आप खोज रहे हैं, तो क्यों न केवल कुछ "मूर्ख" बैश का उपयोग करें? की तरह कुछ:

echo -e "2\n3" | python test.py | grep -q "The sum is 5" && echo "Success" 

आप इस तरह अपेक्षाकृत मामूली कार्यक्रमों कर रहे हैं, तो यह एक पर्याप्त, या काफी अच्छा, समाधान है कि छोटे से प्रयास की आवश्यकता है होना चाहिए।

+0

यह वास्तव में मेरे लिए सबसे उपयोगी है। आप सही हैं कि एक टेस्टेबल प्रोग्राम बनाना छात्रों के सिखाए जाने के भीतर नहीं है (यह एक बहुत ही परिचय स्तर वर्ग है), लेकिन ऐसा कुछ वास्तव में सबसे अच्छा होगा। – Jason

+0

@ जेसन - मुझे जवाब देने से पहले पूरी तरह से प्रश्न पढ़ना चाहिए। * sigh * – Omnifarious

4

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

def my_input(prompt): 
    return input(prompt) 

def main(): 
    a = int(eval(my_input("Enter an integer: ")) 

आदि अब आप अपने परीक्षण कर सकते हैं बंदर-पैच myscript.my_input मूल्यों आप चाहते हैं वापस जाने के लिए।

+0

स्पष्टीकरण के लिए धन्यवाद। परीक्षण उद्देश्यों के लिए ऐसा कुछ बनाना मैंने जो पढ़ा था उसके संदर्भ में बहुत सारी समझ। – Jason

2

यदि आपको echo के साथ प्रदान किए जा सकने वाले कमांड लाइन प्रोग्राम के साथ अधिक जटिल बातचीत की आवश्यकता है तो आप expect पर देख सकते हैं।

2

docs से:

वस्तुओं sys.stdin, sys.stdout और sys.stderr वस्तुओं दुभाषिया के मानक इनपुट, आउटपुट और त्रुटि धाराओं के लिए इसी फाइल करने के लिए प्रारंभ कर रहे हैं।

तो इस तर्क के बाद, ऐसा कुछ काम करने लगता है।अपने आवश्यक इनपुट के साथ एक फ़ाइल बनाएँ:

$ cat sample_stdin.txt 
hello 
world 

फिर उस फ़ाइल को इंगित करने sys.stdin अनुप्रेषित:

#!/usr/bin/env python 
import sys 

fh = open('sample_stdin.txt', 'r') 
sys.stdin = fh 

line1 = raw_input('foo: ') 
line2 = raw_input('bar: ') 

print line1 
print line2 

आउटपुट:

$python redirecting_stdin.py 
foo: bar: hello 
world 
2

कम जवाब यह है कि ऐसा नहीं करते हैं। आपको टेस्टेबिलिटी के लिए डिज़ाइन करना होगा। इसका मतलब सिस्टम संसाधनों से बात करने के लिए उपयोग करने के लिए इंटरफेस प्रदान करने का एक आसान तरीका प्रदान करना है ताकि परीक्षण के दौरान आप उन इंटरफेस के वैकल्पिक कार्यान्वयन प्रदान कर सकें।

दूसरे उत्तर में वर्णित बंदर पैचिंग समाधान काम करता है, लेकिन यह आपके विकल्पों का सबसे प्राचीन है। व्यक्तिगत रूप से, मैं उपयोगकर्ता इंटरैक्शन के लिए एक इंटरफेस क्लास लिखूंगा। उदाहरण के लिए:

class UserInteraction(object): 
    def get_input(self): 
     raise NotImplementedError() 
    def send_output(self, output): 
     raise NotImplementedError() 

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

इस तरह, मैं सिंगलटन से नफरत करता हूं (जिसे वास्तव में पाइथन में वास्तव में लागू नहीं किया जा सकता है)। यह एक उदाहरण बनाकर परीक्षण करने की आपकी क्षमता को नष्ट कर देता है जो वैश्विक रूप से सुलभ है जिसे परीक्षण के लिए स्टब संस्करण से बाहर नहीं किया जा सकता है।

0

आप अपने परीक्षण वातावरण से इनपुट की आपूर्ति के लिए input फ़ंक्शन का नकल करने में सक्षम हो सकते हैं।

ऐसा लगता है कि यह काम कर सकता है। यह अवांछित है।

class MockInput(object): 
    def __init__(self, *values): 
     self.values= list(values) 
     self.history= [] 
    def __call__(self, *args, **kw): 
     try: 
      response= self.values.pop(0) 
      self.history.append((args, kw, response)) 
      return response 
     except IndexError: 
      raise EOFError() 

class TestSomething(unittest.TestCase): 
    def test_when_input_invalid(self): 
     input= MockInput("this", "and", "that") 
     # some test case based on the input function 
0

एक स्ट्रिंगियो (या cStringIO) ऑब्जेक्ट के साथ sys.stdin को बदलें।

2

मेरे सुझाव दो चौखटे कि अजगर इकाई-परीक्षण के लिए प्रदान करता है का उपयोग कर अपने कोड refactor करने के लिए है: unittest (उर्फ PyUnit) और doctest

इस का उपयोग कर एक उदाहरण है unittest:

import unittest 

def adder(a, b): 
    "Return the sum of two numbers as int" 
    return int(a) + int(b) 

class TestAdder(unittest.TestCase): 
    "Testing adder() with two int" 
    def test_adder_int(self): 
     self.assertEqual(adder(2,3), 5) 

    "Testing adder() with two float" 
    def test_adder_float(self): 
     self.assertEqual(adder(2.0, 3.0), 5) 

    "Testing adder() with two str - lucky case" 
    def test_adder_str_lucky(self): 
     self.assertEqual(adder('4', '1'), 5) 

    "Testing adder() with two str" 
    def test_adder_str(self): 
     self.assertRaises(ValueError, adder, 'x', 'y') 

if __name__ == '__main__': 
    unittest.main() 

और यह एक उदाहरण का उपयोग करते हुए doctest है:

# adder.py 

def main(a, b): 
    """This program calculate the sum of two numbers. 
    It prints an int (see %d in print()) 

    >>> main(2, 3) 
    The sum is 5 

    >>> main(3, 2) 
    The sum is 5 

    >>> main(2.0, 3) 
    The sum is 5 

    >>> main(2.0, 3.0) 
    The sum is 5 

    >>> main('2', '3') 
    Traceback (most recent call last): 
     ... 
    TypeError: %d format: a number is required, not str 
    """ 
    c = a + b 
    print("The sum is %d" % c) 

def _test(): 
    import doctest, adder 
    return doctest.testmod(adder) 

if __name__ == '__main__': 
    _test() 
doctest मैं इनपुट का उपयोग कर एक और उदाहरण के साथ यह

() (मुझे लगता है कि आप पाइथन 3 का उपयोग कर रहे हैं।एक्स):

# adder_ugly.py 

def main(): 
    """This program calculate the sum of two numbers. 
    It prints an int (see %d in print()) 

    >>> main() 
    The sum is 5 
    """ 
    a = int(input("Enter an integer: ")) 
    b = int(input("Enter another integer: ")) 
    c = a+b 
    print("The sum is %d" % c) 


def _test(): 
    import doctest, adder_ugly 
    return doctest.testmod(adder_ugly) 

if __name__ == '__main__': 
    _test() 

मैं के ऊपर -v विकल्प के साथ उदाहरण उल्लेख प्रत्येक चलाने होगा:

http://docs.python.org/py3k/library/unittest.html?highlight=unittest#unittest

और

:

python adder_ugly.py -v 

आपके संदर्भ देखें http://docs.python.org/py3k/library/doctest.html#module-doctest