Pytest: How to pytest raw_input calls

Created on 24 May 2018  路  6Comments  路  Source: pytest-dev/pytest

Pytest newbie here
Want to make three test cases that take in None, nonexistant filenames and whitespace filenames for raw_input in main(prompt), and assert the print output
Code in question

#!/usr/bin/env python
import os
import unittest.mock as mock
import pytest

'''Print file
'''
def main(prompt):
  filename = raw_input(prompt) #ask for filename using the given prompt
  if validate(filename):
    for line in open(filename.strip(), "r").readlines(): 
        print line
  else:
    print "The file you selected does not exist, please try again"
    main(prompt) #repeat this function if the use did not give valid input

def validate(input):
    input = input.strip()
    if input is None:
        return False
    elif input == '':
        return False
    elif not (os.path.exists(input)):
        return False
    else:
        return True

if __name__ == "__main__":
    main("Select file in current directory:")

Using: python 2.7, pytest latest version

question

All 6 comments

Hi @ridhwaans,

I think you want something like this (untested):

from mymodule import validate

def test_validate_none():
    assert validate(None) is None

def test_validate_empty():
    assert validate('') is False

def test_validate_f(tmpdir):
    assert validate(tmpdir.ensure('somefile'))

FWIW a function returning None, False or True is not a good approach because None and False are both, well, false, so it's easy to confuse them with one another. I realize that you are probably learning so that's fine.

This would naturally expand to a @pytest.mark.parametrize call, but given that you need the fixture to create the filename this complicates it a little bit so I'm keeping it simple for now.

Testing the actual raw_input call is more complicated, let me know if you want that as well.

Hope this helps

@nicoddemus yes the test cases are to cover the actual raw_input in main(), I dont care about validate()
I'm following this answer https://stackoverflow.com/a/35851524/ which suggests using mock module

Yep that's the recommended way. You can also use monkeypatch which is builtin in pytest.

I'm closing this for now but feel free to follow with further questions if you have any.

In the end, side_effect did it for me

# valid: 'print-file.py'
# invalid: None, '', 'nonexistent'
def test_01():
    with mock.patch.object(__builtin__, 'raw_input', side_effect=['print-file.py']):
        assert main("Enter filename") == "File exists"

def test_02():
    with mock.patch.object(__builtin__, 'raw_input', side_effect=['  ']):
        assert main("Enter filename") == "File does not exist"

def test_03():
    with mock.patch.object(__builtin__, 'raw_input', side_effect=[None]):
        assert main("Enter filename") == "File does not exist"

def test_04():
    with mock.patch.object(__builtin__, 'raw_input', side_effect=['nonexistent']):
        assert main("Enter filename") == "File does not exist"

> python -m pytest print-file.py
============================================================================================================ test session starts =============================================================================================================
platform darwin -- Python 2.7.12, pytest-3.6.0, py-1.5.3, pluggy-0.6.0
rootdir: <>, inifile:
collected 4 items

print-file.py ....                                                                                                                                                                                                                     [100%]

========================================================================================================== 4 passed in 0.06 seconds ==========================================================================================================

The solution and syntax for Python 3 can be found here
https://forum.learncodethehardway.com/t/testing-input-and-print/1757/3

Was this page helpful?
0 / 5 - 0 ratings