2010-11-19 10 views
9

सभी,परीक्षण कंसोल आधारित अनुप्रयोग/प्रोग्राम - जावा

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

मैं कार्यक्षमताओं कि मैं लागू कर दिया है, लेकिन यह पता लगाने की मेरी JUnit परीक्षण तरीकों कि उन मूल्यों को जब मेरी वास्तविक आपूर्ति करेगा में कुछ करने के लिए कार्यान्वयन कोड में System.in रीडायरेक्ट करने के लिए कैसे सक्षम नहीं से प्रत्येक के लिए JUnit परीक्षण मामलों लिखने के लिए कोशिश कर रहा हूँ कोड उपयोगकर्ता इनपुट के लिए बंद हो जाता है?

उदाहरण:

मेरे कार्यान्वयन कोड है:

BufferedReader is = new BufferedReader (new InputStreamReader(System.in)); 
System.out.println("Please enter your name:"); 
String name = is.readLine();    // My test cases stop at this line. How can I pass command line values i.e. redirect System.in to my test based values? 

आशा है कि यह भावना

+0

आप यहां जो वर्णन करते हैं, उसे करने के लिए आप कुछ नमूना कोड पा सकते हैं: http://illegalargumentexception.blogspot.com/2010/09/java-systemconsole-ides-and-testing.html लेकिन यह बड़े पैमाने पर ऑक्सबो_लेक्स को लागू करने का एक तरीका है उनके जवाब में वर्णन करता है। – McDowell

उत्तर

11

क्यों आपके आवेदन एक Reader इनपुट के रूप में लेने के लिए नहीं लिखा है? इस तरह, आप आसानी से एक FileReader(testFile)

public class Processor { 
    void processInput(Reader r){ ... } 
} 

और फिर दो उदाहरणों के साथ एक InputStreamReader(System.in) की जगह ले सकता:

Processor live = new Processor(new InputStreamReader(System.in)); 
Processor test = new Processor(new FileReader("C:/tmp/tests.txt"); 

एक अंतरफलक के लिए कोडिंग अपने कार्यक्रमों के लगभग हर पहलू में महान लाभ लाएगा करने के लिए इस्तेमाल हो रही है!

ध्यान दें कि Reader जावा प्रोग्राम में चरित्र-आधारित इनपुट को संसाधित करने के लिए बेवकूफ तरीका है। InputStream एस कच्चे बाइट-स्तरीय प्रसंस्करण के लिए आरक्षित होना चाहिए।

+0

मुझे आपको समझ में नहीं आया। उपरोक्त कोड मेरे उदाहरण में कैसे काम करता है? तो अगर मुझे अपनी टेस्ट विधि में कमांड लाइन मान पास करना है, तो मुझे फ़ाइल 'test.txt' फ़ाइल का उपयोग करना होगा? यदि ऐसा है, तो मैं मूल्यों को पास करने के लिए फ़ाइलों को बनाने के बजाय अपनी परीक्षण विधि के माध्यम से मूल्यों को पारित करना चाहता हूं। –

+0

दो 'रीडर' का एक ही इंटरफ़ेस है। आप अपने यूनिट परीक्षणों के लिए 'FileReader' का उपयोग करते हैं क्योंकि इसके लिए कोई उपयोगकर्ता इनपुट की आवश्यकता नहीं होती है (आप अलग-अलग इनपुट का परीक्षण करने के उद्देश्य से टेक्स्ट फाइलें तैयार करते हैं)। जब आप प्रोग्राम को लाइव करते हैं तो आप 'इनपुटस्ट्रीम रीडर (System.in)' का उपयोग करते हैं, इसलिए यह अभी भी उपयोगकर्ता इनपुट के लिए सीधे पूछेगा। – Santa

3
+0

क्या आप कृपया अपना उत्तर विस्तृत कर सकते हैं? मैं "input.txt" फ़ाइल का उपयोग क्यों करूं ?? –

+1

@ darkie15: यह सिर्फ एक उदाहरण है। – thejh

+0

@ darkie15: आप 'PipedInputStream' और' PipedOutputStream' या तो 'के साथ भी काम कर सकते हैं। – thejh

3

मैं सुझाव है कि आप तीन भागों में कोड को अलग करने:

  • पढ़ें इनपुट (अपने उदाहरण में name की तरह)
  • आपको लगता है कि इनपुट के साथ
  • प्रिंट परिणाम क्या करने की जरूरत क्या

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

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

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

अपने मामले में, आप किसी भी तरह name का उपयोग करते हैं। यदि यह एकमात्र पैरामीटर है, तो एक विधि बनाएं - चलो इसे nameConsumer पर कॉल करें - वह वह नाम लेता है, कुछ करता है और इसके परिणाम देता है।

@Test 
public void testNameConsumer() { 
    // Prepare inputs 
    String name = "Jon"; 
    String result = nameConsumer(name); 
    assertEquals("Doe", result); 
} 

अन्य तरीकों के लिए अपने println और readLine कॉल ले जाएँ और अपने इकाई परीक्षण में nameConsumer के आसपास है, लेकिन नहीं का उपयोग करें: अपने इकाई परीक्षण में, कुछ इस तरह से करते हैं।

इस बारे में यहाँ और अधिक पढ़ें:

रख सरल, इसे बंद कर देता है।

2

लाइब्रेरी System Rules जुनीट परीक्षणों में इनपुट अनुकरण करने के लिए नियम TextFromStandardInputStream प्रदान करता है।

public class YourAppTest { 
    @Rule 
    public TextFromStandardInputStream systemInMock = emptyStandardInputStream(); 

    @Test 
    public void test() { 
    systemInMock.provideText("name\nsomething else\n"); 
    YourApp.main(); 
    //assertSomething 
    } 
} 

जानकारी के लिए System Rules documentation पर एक नजर है।

+0

बहुत उपयोगी पुस्तकालय! इसे यहां इस्तेमाल किया गया: https://github.com/binwiederhier/syncany/blob/7ee6174877a646c78e2f5faa36115d01bf6cc9ec/syncany-cli/src/test/java/org/syncany/tests/cli/InitCommandTest.java#L137 – binwiederhier

1

यह basic looping console application लेता है और oxbow_lakes' answer से विचारों का उपयोग करके इसे परीक्षण योग्य बनाता है।

वर्ग उचित:

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintStream; 

public class TestableLoopingConsoleExample { 

    public static final String INPUT_LINE_PREFIX = "> "; 
    public static final String EXIT_COMMAND = "exit"; 
    public static final String RESPONSE_PLACEHOLDER = "...response goes here..."; 
    public static final String EXIT_RESPONSE = "Exiting."; 

    public static void main(String[] cmdLineParams_ignored) throws IOException { 
     BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 
     PrintStream out = new PrintStream(System.out); 
     PrintStream err = new PrintStream(System.err); 

     try { 
     new TestableLoopingConsoleExample().main(cmdLineParams_ignored, in, out); 
     } catch (Exception e) { //For real use, catch only the exactly expected types 
     err.println(e.toString()); 
     } 
    } 

... जारी रखा ...

public void main(String[] cmdLineParams_ignored, BufferedReader in, PrintStream out) 
     throws IOException { 

     System.out.println("Enter some text, or '" + EXIT_COMMAND + "' to quit"); 

     while (true) { 

     out.print(INPUT_LINE_PREFIX); 
     String input = in.readLine(); 
     out.println(input); 

     if (input.length() == EXIT_COMMAND.length() && 
      input.toLowerCase().equals(EXIT_COMMAND)) { 

      out.println(EXIT_RESPONSE); 
      return; 
     } 

     out.println(RESPONSE_PLACEHOLDER); 
     } 
    } 
} 

परीक्षण (JUnit4):

import static org.junit.Assert.assertEquals; 
import static testableloopingconsoleapp.TestableLoopingConsoleExample.EXIT_COMMAND; 
import static testableloopingconsoleapp.TestableLoopingConsoleExample.EXIT_RESPONSE; 
import static testableloopingconsoleapp.TestableLoopingConsoleExample.INPUT_LINE_PREFIX; 
import static testableloopingconsoleapp.TestableLoopingConsoleExample.RESPONSE_PLACEHOLDER; 

import org.junit.Before; 
import org.junit.Test; 

import java.io.BufferedReader; 
import java.io.ByteArrayOutputStream; 
import java.io.PrintStream; 
import java.io.StringReader; 

public class TestableLoopingConsoleExampleTest { 

    private final ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    private final ByteArrayOutputStream err = new ByteArrayOutputStream(); 

    @Before 
    public final void resetOutputStreams() { 
    out.reset(); 
    err.reset(); 
    } 

... जारी रखा ...

@Test 
    public void testableMain_validInputFromString_outputAsExpected() throws Exception { 
    String line1 = "input line 1\n"; 
    String line2 = "input line 2\n"; 
    String line3 = "input line 3\n"; 
    String exitLine = EXIT_COMMAND + "\n"; 

    BufferedReader in = new BufferedReader(new StringReader(
     line1 + line2 + line3 + exitLine 
    )); 
    String expectedOutput = 
     INPUT_LINE_PREFIX + line1 + 
     RESPONSE_PLACEHOLDER + "\n" + 
     INPUT_LINE_PREFIX + line2 + 
     RESPONSE_PLACEHOLDER + "\n" + 
     INPUT_LINE_PREFIX + line3 + 
     RESPONSE_PLACEHOLDER + "\n" + 
     INPUT_LINE_PREFIX + exitLine + 
     EXIT_RESPONSE + "\n"; 

    String[] ignoredCommandLineParams = null; 

    new TestableLoopingConsoleExample().main(ignoredCommandLineParams, in, new PrintStream(out)); 

    assertEquals(expectedOutput, out.toString()); 
    } 

} 
+0

फ़ॉवाआ .... कि कुछ परीक्षणों के रूप में सुंदर नहीं हो सकता है। उल्टा, thx! – Crowie

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