0

I am learning to use Python's unittest (first time) and having a bit of trouble. I have code that queries a database, sorts the data, and outputs the sorted data to a CSV file. It works just fine. However, when I try to generate the CSV from the test module, it never generates, and so the unit test fails, when it checks if the file was produced at the path.

In my other test functions, the functions to be tested are being called and are passing the unit tests. The CSV file is generated when I call it from another, non-test Python script, but it isn't generated from the test module, so the issue is in the test module.

Here is my code:

from my_code_to_be_tested import my_code_to_be_tested as mc

...

    @mock.patch('my_code_to_be_tested.my_code_to_be_tested.create_file')
    def test_create_file(self, mock_create_file):
        data = self._get_data(self)  # get the data to output, this works
        file_name = self._get_filename(self)  # also works 
        mc.create_file(data, file_name)  # this line never executes
        test_dir = os.path.dirname(os.path.abspath(__file__))
        file_path = os.path.join(test_dir, file_name)
        assert os.path.isfile(file_path)

The create_file function in the my_code_to_be_tested.py file is as follows:

def create_file(report: DataFrame, file_name: string) -> None:
    """
    Save data to .csv file
    Args:
        report: a sorted dataframe consisting of the requested columns
        file_name: the name of the report

    Returns:
        None
    """
 
    filename = f'{file_name}.csv'
    report.to_csv(filename, index=False)

I have checked various file paths to see if it was produced in a different folder, but it wasn't produced at all, so I must be calling it incorrectly. I called my other functions this way, and they worked; however, they all returned a value, so they had slightly different syntax.

Daniil Fajnberg
  • 12,753
  • 2
  • 10
  • 41
phoenix
  • 1
  • 1
  • I don't understand. You are _explicitly_ mocking that `create_file` function, but you are also wondering, why it isn't called? Do you know, what the `patch` decorator is for? – Daniil Fajnberg May 20 '23 at 13:41
  • @DaniilFajnberg, I'm new to using it. I thought that there is a mock object the represents what should happen, and then I call my function to test if that is what happened. From your comment, I take it that the mocking removes real functionality from occuring. How else do I test if the file creation occurs? Thanks – phoenix May 20 '23 at 18:31
  • A mock object is a stand-in for some _actual_ object/function. The entire point of mocking is to _not_ call the actual function. But it makes no sense to mock the function that is being _tested_. If you are testing `create_file`, you should actually call it. You mock 1) other functions you wrote yourself or 2) functions with side effects that are being called by the function under test. Your case seems to fall under option 2): You typically _don't_ want to actually create files, when running unit tests. – Daniil Fajnberg May 20 '23 at 20:45
  • 1
    So I would suggest mocking `DataFrame.to_csv`. Then you can call `create_file` in your test and check, if the mocked function was called by `create_file` _as expected_, i.e. with the desired parameters, e.g. with [`Mock.assert_called_once_with`](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.assert_called_once_with). – Daniil Fajnberg May 20 '23 at 20:52

0 Answers0