如何在python中使用print语句测试文件写入

时间:2017-09-06 16:38:20

标签: python file-io mocking

我想测试以下声明

with open('test.txt', 'w') as f:
    print(['abc', 20], end='', file=f)

我试过

  from __future__ import print_function                                              
  from mock import patch, mock_open                                                  


  def f():                                                                           
      with open('test.txt', 'w') as f:                                               

          # f.write(str(['abc', 20]))                                                 
          print(['abc', 20], end='', file=f)                                         


  @patch('__builtin__.open', new_callable=mock_open)                                 
  def test(mock_f):                                                                  
      f()                                                                            
      mock_f.assert_called_with('test.txt', 'w')                                     
      handle = mock_f()                                                              
      handle.write.assert_called_once_with(str(['abc', 20])) 

它抱怨永远不会调用write,这是有道理的。在这种情况下,检查内容写入的正确方法是什么?

我还尝试使用f.write(str(['abc', 20]))代替通过测试的print语句。使用print只是一个坏主意吗?

1 个答案:

答案 0 :(得分:1)

Python 3.6:

如果您检查模拟对象,您可以看到您正在寻找的东西就在那里。

from unittest.mock import mock_open, patch

def f():                                                                           
    with open('test.txt', 'w') as f:                                               

        print(['abc', 20], end='', file=f)                                         

@patch('__main__.__builtins__.open', new_callable=mock_open)                                 
def test(mock_f):
    f()
    mock_f.assert_called_with('test.txt', 'w')
    print('calls to open:\n', mock_f.mock_calls, end ='\n\n')
    handle = mock_f()
    print('calls to the file:\n', handle.mock_calls, end ='\n\n')
    print('calls to write:\n', handle.write.mock_calls, end ='\n\n')
    handle.write.assert_called_once_with(str(['abc', 20]))

>>> test()
calls to open:
 [call('test.txt', 'w'),
 call().__enter__(),
 call().write("['abc', 20]"),
 call().write(''),
 call().__exit__(None, None, None)]

calls to the file:
 [call.__enter__(),
 call.write("['abc', 20]"),
 call.write(''),
 call.__exit__(None, None, None)]

calls to write:
 [call("['abc', 20]"), call('')]

Traceback (most recent call last):
  File "<pyshell#98>", line 1, in <module>
    test()
  File "C:\Python36\lib\unittest\mock.py", line 1179, in patched
    return func(*args, **keywargs)
  File "C:/pyProjects33/test_tmp.py", line 30, in test
    handle.write.assert_called_once_with(str(['abc', 20]))
  File "C:\Python36\lib\unittest\mock.py", line 824, in assert_called_once_with
    raise AssertionError(msg)
AssertionError: Expected 'write' to be called once. Called 2 times.
>>> 
由于您传递了.write()参数,

''end第二次调用 - 您可以通过使用该参数来验证这一点。

如何测试?您可以使用assert_any_call()

    handle.write.assert_any_call(str(['abc', 20]))

或者,如果您要验证end参数,assert_has_calls()

from unittest.mock import call

....
        calls = [call(str(['abc', 20])), call('')]
        handle.write.assert_has_calls(calls)

您问过Is it just a bad idea to use print? |也许其他人可以插话,但在我有限的经验中,我从未考虑过使用print()来写一个文件。