0

I'm using pytest and want to test that a function writes some content to a file. So I have writer.py which includes:

MY_DIR = '/my/path/'

def my_function():
    with open('{}myfile.txt'.format(MY_DIR), 'w+') as file:
        file.write('Hello')
        file.close()

I want to test /my/path/myfile.txt is created and has the correct content:

import writer

class TestFile(object):

    def setup_method(self, tmpdir):
        self.orig_my_dir = writer.MY_DIR
        writer.MY_DIR = tmpdir

    def teardown_method(self):
        writer.MY_DIR = self.orig_my_dir

    def test_my_function(self):
        writer.my_function()

        # Test the file is created and contains 'Hello'

But I'm stuck with how to do this. Everything I try, such as something like:

        import os
        assert os.path.isfile('{}myfile.txt'.format(writer.MYDIR))

Generates errors which lead me to suspect I'm not understanding or using tmpdir correctly.

How should I test this? (If the rest of how I'm using pytest is also awful, feel free to tell me that too!)

Phil Gyford
  • 10,767
  • 11
  • 51
  • 112
  • 1
    There are two questions that address each part of what you are having difficulty I believe. Check them out and see if they provide any insight. Here is one on testing for writing to the file [here](https://stackoverflow.com/questions/20531072/writing-a-pytest-function-to-check-outputting-to-a-file-in-python) and [here](https://stackoverflow.com/questions/15801662/py-test-how-to-use-a-context-manager-in-a-funcarg-fixture) is one that shows how to use the proper fixture to deal with context managers. – idjaw Jun 19 '17 at 11:47
  • You should [mock `open()`](https://stackoverflow.com/questions/1289894/how-do-i-mock-an-open-used-in-a-with-statement-using-the-mock-framework-in-pyth) so you never actually open a file, but just check if it has been used correctly. – Nils Werner Jun 19 '17 at 11:56
  • Can we see more details? How do you generate tmpdir? What are errors? – phd Jun 19 '17 at 15:29
  • 1
    @phd `tmpdir` [is a pytest fixture](https://docs.pytest.org/en/latest/tmpdir.html). I don't like how it appears sort of like 'magic', rather than being imported from somewhere... doesn't feel very explicit. – Phil Gyford Jun 19 '17 at 15:43

1 Answers1

3

I've got a test to work by altering the function I'm testing so that it accepts a path to write to. This makes it easier to test. So writer.py is:

MY_DIR = '/my/path/'

def my_function(my_path):
    # This currently assumes the path to the file exists.
    with open(my_path, 'w+') as file:
        file.write('Hello')

my_function(my_path='{}myfile.txt'.format(MY_DIR))

And the test:

import writer

class TestFile(object):

    def test_my_function(self, tmpdir):

        test_path = tmpdir.join('/a/path/testfile.txt')

        writer.my_function(my_path=test_path)

        assert test_path.read() == 'Hello'
Phil Gyford
  • 10,767
  • 11
  • 51
  • 112