Jekson
Jekson

Reputation: 3252

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?

Upvotes: 7

Views: 4819

Answers (2)

cryanbhu
cryanbhu

Reputation: 5254

For those wanting to test exceptions in a click command, I have found this way to do it:

def test_download_artifacts(
        self,
    ):
        runner = CliRunner()
        # test exception raised for invalid dir format
        result = runner.invoke(
            my_module.download_artifacts,
            '--bucket_name my_bucket \
            --artifact_dir artifact_dir'.split(),
            input='2')
        print(f"result.exception: {result.exception}")
        assert "Enter artifact_dir ending" in str(result.exception)

Upvotes: 2

Stephen Rauch
Stephen Rauch

Reputation: 49774

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)

Upvotes: 13

Related Questions