Search code examples
pythonpytestpython-click

How to test click commands that expect files


I have a click command that does something with a file:

import click

@click.command()
@click.argument("file", type=click.File("r"))
def foo(file):
    print(file.read())

And I'd like to test it without creating temporary files, but I don't know which path to give the runner and can't find examples on the web. Something like this would be nice:

from click.testing import CliRunner

from magic_lib import magic_file

def test_foo():
    runner = CliRunner()
    fake_file = magic_file("Hello, world!")
    result = runner.invoke(foo, [fake_file.location])
    assert result.output == "Hello, world!\n"

Any way I can make click.File understand where I want it to look?


Solution

  • You can use pyfakefs. The usage depends on your testing framework; it's easiest to use with pytest because it automatically provides an fs fixture:

    def test_foo(fs):
        fake_file = fs.create_file('/foo/bar', contents="Hello, world!")
    
        runner = CliRunner()
        result = runner.invoke(foo, [fake_file.path])
        assert result.output == "Hello, world!\n"
    

    P.S.: Because the print in foo adds a newline, the file has to be created without \n at the end for the test to work.