|
1 | 1 | import pytest |
| 2 | +from unittest.mock import patch, MagicMock |
2 | 3 | from click.testing import CliRunner |
3 | 4 |
|
4 | | -import logging |
5 | | - |
6 | 5 | from paths_cli.cli import * |
7 | 6 | from .null_command import NullCommandContext |
8 | 7 |
|
| 8 | + |
9 | 9 | class TestOpenPathSamplingCLI(object): |
| 10 | + # TODO: more thorough testing of private methods to find/register |
| 11 | + # plugins might be nice; so far we mainly focus on testing the API. |
| 12 | + # (Still have smoke tests covering everything, though.) |
10 | 13 | def setup(self): |
11 | | - # TODO: patch out the directory to fake the plugins |
12 | | - self.cli = OpenPathSamplingCLI() |
| 14 | + def make_mock(name, helpless=False): |
| 15 | + mock = MagicMock(return_value=name) |
| 16 | + if helpless: |
| 17 | + mock.short_help = None |
| 18 | + else: |
| 19 | + mock.short_help = name + " help" |
| 20 | + return mock |
| 21 | + |
| 22 | + self.plugin_dict = { |
| 23 | + 'foo': OPSPlugin(name='foo', |
| 24 | + filename='foo.py', |
| 25 | + func=make_mock('foo'), |
| 26 | + section='Simulation'), |
| 27 | + 'foo-bar': OPSPlugin(name='foo-bar', |
| 28 | + filename='foo_bar.py', |
| 29 | + func=make_mock('foobar', helpless=True), |
| 30 | + section='Miscellaneous') |
| 31 | + } |
| 32 | + self.fake_plugins = list(self.plugin_dict.values()) |
| 33 | + mock_plugins = MagicMock(return_value=self.fake_plugins) |
| 34 | + with patch.object(OpenPathSamplingCLI, '_load_plugin_files', |
| 35 | + mock_plugins): |
| 36 | + self.cli = OpenPathSamplingCLI() |
13 | 37 |
|
14 | 38 | def test_plugins(self): |
15 | | - pytest.skip() |
16 | | - pass |
| 39 | + assert self.cli.plugins == self.fake_plugins |
| 40 | + assert self.cli._sections['Simulation'] == ['foo'] |
| 41 | + assert self.cli._sections['Miscellaneous'] == ['foo-bar'] |
| 42 | + |
| 43 | + @pytest.mark.parametrize('name', ['foo', 'foo-bar']) |
| 44 | + def test_plugin_for_command(self, name): |
| 45 | + assert self.cli.plugin_for_command(name) == self.plugin_dict[name] |
| 46 | + |
| 47 | + def test_list_commands(self): |
| 48 | + assert self.cli.list_commands(ctx=None) == ['foo', 'foo-bar'] |
17 | 49 |
|
18 | | - def test_get_command(self): |
19 | | - # test renamings |
20 | | - pytest.skip() |
21 | | - pass |
| 50 | + @pytest.mark.parametrize('command', ['foo-bar', 'foo_bar']) |
| 51 | + def test_get_command(self, command): |
| 52 | + # this tests that renamings work |
| 53 | + cmd = self.cli.get_command(ctx=None, name=command) |
| 54 | + assert cmd() == 'foobar' |
22 | 55 |
|
23 | 56 | def test_format_commands(self): |
24 | | - pytest.skip() |
25 | | - # use a mock to get the formatter |
26 | | - # test that it skips a section if it is empty |
27 | | - pass |
| 57 | + class MockFormatter(object): |
| 58 | + def __init__(self): |
| 59 | + self.title = None |
| 60 | + self.contents = {} |
| 61 | + |
| 62 | + def section(self, title): |
| 63 | + self.title = title |
| 64 | + return MagicMock() |
| 65 | + |
| 66 | + def write_dl(self, rows): |
| 67 | + self.contents[self.title] = rows |
| 68 | + |
| 69 | + formatter = MockFormatter() |
| 70 | + # add a non-existent command; tests when get_command is None |
| 71 | + self.cli._sections['Workflow'] = ['baz'] |
| 72 | + self.cli.format_commands(ctx=None, formatter=formatter) |
| 73 | + foo_row = ('foo', 'foo help') |
| 74 | + foobar_row = ('foo-bar', '') |
| 75 | + assert formatter.contents['Simulation Commands'] == [foo_row] |
| 76 | + assert formatter.contents['Miscellaneous Commands'] == [foobar_row] |
| 77 | + assert len(formatter.contents) == 2 |
| 78 | + |
28 | 79 |
|
29 | 80 | @pytest.mark.parametrize('with_log', [True, False]) |
30 | 81 | def test_main_log(with_log): |
|
0 commit comments