Unittest for click module

I wrote a simple command line utility that accepts a text file and searches for a given word in it using the click module.

sfind.py

import click
@click.command()
@click.option('--name', prompt='Word or string')
@click.option('--filename', default='file.txt', prompt='file name')
@click.option('--param', default=1, prompt="Use 1 for save line and 2 for word, default: ")
def find(name, filename, param):
    """Simple program that find  word or string at text file and put it in new"""
    try:
        with open(filename) as f, open('result.txt', 'w') as f2:
            count = 0
            for line in f:
                if name in line:
                    if param == 1:
                        f2.write(line + '\n')
                    elif param == 2:
                        f2.write(name + '\n')
                    count += 1
            print("Find: {} sample".format(count))
            return count
    except FileNotFoundError:
        print('WARNING! ' + 'File: ' + filename + ' not found')


if __name__ == '__main__':
    find()

Now I need to write a test using unittest (using unittest is required).

test_sfind.py

import unittest
import sfind

class SfindTest(unittest.TestCase):
    def test_sfind(self):
        self.assertEqual(sfind.find(), 4)


if __name__ == '__main__' :
    unittest.main()

When I run the test:

python -m unittest test_sfind.py

I get an error

click.exceptions.UsageError: Got unexpected extra argument (test_sfind.py)

How can I test this click command?

1 answer

  • answered 2018-11-08 13:56 Stephen Rauch

    You can not simply call a click command and then expect it to return. The decorators applied to make a click command considerably change the behavior of the function. Fortunately the click frameworks provides for this through the CliRunner class.

    Your command can be tested via unittest with something like this:

    import unittest
    import sfind
    from click.testing import CliRunner
    
    class TestSfind(unittest.TestCase):
    
        def test_sfind(self):
    
            runner = CliRunner()
            result = runner.invoke(
                sfind.find, '--name url --filename good'.split(), input='2')
            self.assertEqual(0, result.exit_code)
            self.assertIn('Find: 3 sample', result.output)