How can I simulate input to stdin for pyunit?

前端 未结 5 1014
清酒与你
清酒与你 2020-12-03 10:56

I\'m trying to test a function that takes input from stdin, which I\'m currently testing with something like this:

cat /usr/share/dict/words | .         


        
5条回答
  •  时光说笑
    2020-12-03 11:28

    Update -- using unittest.mock.patch

    Since python 3.3 there is new submodule for unittest called mock that does exactly what you need to do. For those using python 2.6 or above there is a backport of mock found here.

    import unittest
    from unittest.mock import patch
    
    import module_under_test
    
    
    class MyTestCase(unittest.TestCase):
    
        def setUp(self):
            # raw_input is untouched before test
            assert module_under_test.raw_input is __builtins__.raw_input
    
        def test_using_with(self):
            input_data = "123"
            expected = int(input_data)
    
            with patch.object(module_under_test, "raw_input", create=True, 
                    return_value=expected):
                # create=True is needed as raw_input is not in the globals of 
                # module_under_test, but actually found in __builtins__ .
                actual = module_under_test.function()
    
            self.assertEqual(expected, actual)
    
        @patch.object(module_under_test, "raw_input", create=True)
        def test_using_decorator(self, raw_input):
            raw_input.return_value = input_data = "123"
            expected = int(input_data)
    
            actual = module_under_test.function()
    
            self.assertEqual(expected, actual)
    
        def tearDown(self):
            # raw input is restored after test
            assert module_under_test.raw_input is __builtins__.raw_input
    
    if __name__ == "__main__":
        unittest.main()
    # where module_under_test.function is:
    def function():
        return int(raw_input("prompt> "))
    

    Previous answer -- replacing sys.stdin

    I think the sys module might be what you're looking for.

    You can do something like

    import sys
    
    # save actual stdin in case we need it again later
    stdin = sys.stdin
    
    sys.stdin = open('simulatedInput.txt','r') 
    # or whatever else you want to provide the input eg. StringIO
    

    raw_input will now read from simulatedInput.txt whenever it is called. If the contents of simulatedInput was

    hello
    bob
    

    then the first call to raw_input would return "hello", the second "bob" and third would throw an EOFError as there was no more text to read.

提交回复
热议问题