4
votes

I'm trying to understand how to use unittest framework of python

I have a piece of code that looks like this --

while True:
    filename = raw_input('Enter file')
    if os.path.exists(filename):
        break
    else:
        print "That file does not exist"
return filename

Can somebody help me out in developing the unittest module to test this. I'm asking this question in order to learn how to use unittesting (i'm trying to learn TTD: Test-Driven Development)

So far I've come up with this ... import unittest import os.path

class TestFunctions(unittest.TestCase):

def setUp(self):
    self.prompt = 'Enter filename: '

def test_get_file(self):

    # TODO make sure empty filename argument requests for new filename
    filename = find_author.get_valid_filename(self.prompt)
    self.assertTrue(<EXPRESSION?>)

    # TODO make sure valid filename returns the "filename"
    # TODO make sure invalid filename prompts that file does not exit and requests new filename 

if name == "main": unittest.main()

2

2 Answers

5
votes

One simple way to do this is to monkey-patch raw_input.

For example, in your testing module (since you should split your testee and tester into separate files), you might have:

import module_being_tested
... run tests ...

Before you run your tests, you can simply do:

import module_being_tested

def mock_raw_input(s):
    return 'data.txt'

module_being_tested.raw_input = mock_raw_input

... run tests ....

Now, when your testee module calls raw_input, it will actually be calling mock_raw_input, and will always get 'data.txt' back.

1
votes

Expanding on vgel's answer to this question, I had the need to simulate different consecutive inputs, so always returning the same string wasn't enough. This is how I solved it:

import module_being_tested

mock_raw_input_counter = 0
mock_raw_input_values = []
def mock_raw_input(s):
    global mock_raw_input_counter
    global mock_raw_input_values
    mock_raw_input_counter += 1
    return mock_raw_input_values[mock_raw_input_counter - 1]

module_being_tested.raw_input = mock_raw_input

Then in the test you want to use this multi-input capability:

def test_interactive_sequence_selection_dummy_2_99_0_Z_1(self):
    global mock_raw_input_counter
    global mock_raw_input_values
    mock_raw_input_counter = 0
    mock_raw_input_values = ["2", "99", "0", "Z", "1", ""]
    new_sequences = module_being_tested.interactive_sequence_selection(["A", "B", "C"], [None])
    self.assertEqual(new_sequences, ["C", "A", "B"])

That will simulate the entry of the following values:

2[ENTER]
99[ENTER]
0[ENTER]
Z[ENTER]
1[ENTER]
[ENTER] (no input, just pressing Enter)

(the code in interactive_sequence_selection uses a while s != "": loop to ask the user to input various values and terminate with an empty Enter press)