Skip to content

Commit

Permalink
change to LogCliRunner
Browse files Browse the repository at this point in the history
LogCliRunner extends CliRunner to reset the CliLog at the end of
invoke.
  • Loading branch information
n8pease committed Jul 14, 2020
1 parent 971e8b9 commit ea759ef
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 90 deletions.
1 change: 1 addition & 0 deletions python/lsst/daf/butler/cli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import click
import click.testing
from contextlib import contextmanager
import enum
import io
Expand Down
10 changes: 4 additions & 6 deletions python/lsst/daf/butler/tests/cliCmdTestBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,10 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import abc
import click
import click.testing
import copy
import os

from ..cli.utils import clickResultMsg, mockEnvVar, Mocker
from ..cli.utils import clickResultMsg, mockEnvVar, LogCliRunner, Mocker
from ..cli import butler


Expand Down Expand Up @@ -54,16 +52,16 @@ def cli(self):
return butler.cli

def setUp(self):
self.runner = click.testing.CliRunner(env=mockEnvVar)
self.runner = LogCliRunner(env=mockEnvVar)

def makeExpected(self, **kwargs):
expected = copy.copy(self.defaultExpected)
expected.update(kwargs)
return expected

def run_command(self, inputs):
"""Use the CliRunner with the mock environment variable set to execute
a butler subcommand and parameters specified in inputs.
"""Use the LogCliRunner with the mock environment variable set to
execute a butler subcommand and parameters specified in inputs.
Parameters
----------
Expand Down
35 changes: 16 additions & 19 deletions tests/test_cliCmdConfigDump.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,12 @@
"""Unit tests for daf_butler CLI config-dump command.
"""

import click
import click.testing
import unittest
import yaml

from lsst.daf.butler.cli import butler
from lsst.daf.butler.cli.cmd import config_dump
from lsst.daf.butler.cli.utils import clickResultMsg
from lsst.daf.butler.cli.utils import clickResultMsg, LogCliRunner
from lsst.daf.butler.tests import CliCmdTestBase


Expand All @@ -42,15 +40,17 @@ class ConfigDumpTest(CliCmdTestBase, unittest.TestCase):
class ConfigDumpUseTest(unittest.TestCase):
"""Test executing the command."""

def setUp(self):
self.runner = LogCliRunner()

def test_stdout(self):
"""Test dumping the config to stdout."""
runner = click.testing.CliRunner()
with runner.isolated_filesystem():
result = runner.invoke(butler.cli, ["create", "here"])
with self.runner.isolated_filesystem():
result = self.runner.invoke(butler.cli, ["create", "here"])
self.assertEqual(result.exit_code, 0, clickResultMsg(result))

# test dumping to stdout:
result = runner.invoke(butler.cli, ["config-dump", "here"])
result = self.runner.invoke(butler.cli, ["config-dump", "here"])
self.assertEqual(result.exit_code, 0, clickResultMsg(result))
# check for some expected keywords:
cfg = yaml.safe_load(result.stdout)
Expand All @@ -60,11 +60,10 @@ def test_stdout(self):

def test_file(self):
"""test dumping the config to a file."""
runner = click.testing.CliRunner()
with runner.isolated_filesystem():
result = runner.invoke(butler.cli, ["create", "here"])
with self.runner.isolated_filesystem():
result = self.runner.invoke(butler.cli, ["create", "here"])
self.assertEqual(result.exit_code, 0, clickResultMsg(result))
result = runner.invoke(butler.cli, ["config-dump", "here", "--file=there"])
result = self.runner.invoke(butler.cli, ["config-dump", "here", "--file=there"])
self.assertEqual(result.exit_code, 0, clickResultMsg(result))
# check for some expected keywords:
with open("there", "r") as f:
Expand All @@ -75,11 +74,10 @@ def test_file(self):

def test_subset(self):
"""Test selecting a subset of the config."""
runner = click.testing.CliRunner()
with runner.isolated_filesystem():
result = runner.invoke(butler.cli, ["create", "here"])
with self.runner.isolated_filesystem():
result = self.runner.invoke(butler.cli, ["create", "here"])
self.assertEqual(result.exit_code, 0, clickResultMsg(result))
result = runner.invoke(butler.cli, ["config-dump", "here", "--subset", "datastore"])
result = self.runner.invoke(butler.cli, ["config-dump", "here", "--subset", "datastore"])
self.assertEqual(result.exit_code, 0, clickResultMsg(result))
cfg = yaml.safe_load(result.stdout)
# count the keys in the datastore config
Expand All @@ -93,12 +91,11 @@ def test_subset(self):

def test_invalidSubset(self):
"""Test selecting a subset key that does not exist in the config."""
runner = click.testing.CliRunner()
with runner.isolated_filesystem():
result = runner.invoke(butler.cli, ["create", "here"])
with self.runner.isolated_filesystem():
result = self.runner.invoke(butler.cli, ["create", "here"])
self.assertEqual(result.exit_code, 0, clickResultMsg(result))
# test dumping to stdout:
result = runner.invoke(butler.cli, ["config-dump", "here", "--subset", "foo"])
result = self.runner.invoke(butler.cli, ["config-dump", "here", "--subset", "foo"])
self.assertEqual(result.exit_code, 1)
self.assertIn("Error: 'foo not found in config at here'", result.output)

Expand Down
23 changes: 12 additions & 11 deletions tests/test_cliCmdConfigValidate.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@
"""Unit tests for daf_butler CLI config-validate command.
"""

import click
import click.testing
import unittest

from lsst.daf.butler.cli import butler
from lsst.daf.butler.cli.cmd import config_validate
from lsst.daf.butler.cli.utils import LogCliRunner
from lsst.daf.butler.tests import CliCmdTestBase


Expand All @@ -40,26 +39,28 @@ class ValidateTest(CliCmdTestBase, unittest.TestCase):
class ConfigValidateUseTest(unittest.TestCase):
"""Test executing the command."""

def setUp(self):
self.runner = LogCliRunner()

def testConfigValidate(self):
"""Test validating a valid config."""
runner = click.testing.CliRunner()
with runner.isolated_filesystem():
result = runner.invoke(butler.cli, ["create", "here"])
with self.runner.isolated_filesystem():
result = self.runner.invoke(butler.cli, ["create", "here"])
self.assertEqual(result.exit_code, 0, result.stdout)
# verify the just-created repo validates without error
result = runner.invoke(butler.cli, ["config-validate", "here"])
result = self.runner.invoke(butler.cli, ["config-validate", "here"])
self.assertEqual(result.exit_code, 0, result.stdout)
self.assertEqual(result.stdout, "No problems encountered with configuration.\n")

def testConfigValidate_ignore(self):
"""Test the ignore flag"""
runner = click.testing.CliRunner()
with runner.isolated_filesystem():
result = runner.invoke(butler.cli, ["create", "here"])
with self.runner.isolated_filesystem():
result = self.runner.invoke(butler.cli, ["create", "here"])
self.assertEqual(result.exit_code, 0, result.stdout)
# verify the just-created repo validates without error
result = runner.invoke(butler.cli, ["config-validate", "here",
"--ignore", "storageClasses,repoTransferFormats", "-i", "dimensions"])
result = self.runner.invoke(butler.cli, ["config-validate", "here",
"--ignore", "storageClasses,repoTransferFormats",
"-i", "dimensions"])
self.assertEqual(result.exit_code, 0, result.stdout)
self.assertEqual(result.stdout, "No problems encountered with configuration.\n")

Expand Down
4 changes: 2 additions & 2 deletions tests/test_cliCmdQueryCollections.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@
"""Unit tests for daf_butler CLI query-collections command.
"""

import click
import unittest
import yaml

from lsst.daf.butler import Butler
from lsst.daf.butler.cli.butler import cli
from lsst.daf.butler.cli.cmd import query_collections
from lsst.daf.butler.cli.utils import LogCliRunner
from lsst.daf.butler.tests import CliCmdTestBase


Expand Down Expand Up @@ -63,7 +63,7 @@ def testGetCollections(self):
run = "ingest/run"
tag = "ingest"
expected = {"collections": [run, tag]}
runner = click.testing.CliRunner()
runner = LogCliRunner()
with runner.isolated_filesystem():
butlerCfg = Butler.makeRepo("here")
# the purpose of this call is to create some collections
Expand Down
5 changes: 2 additions & 3 deletions tests/test_cliCmdQueryDatasetTypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@
"""Unit tests for daf_butler CLI query-collections command.
"""

import click
import unittest
import yaml

from lsst.daf.butler import Butler, DatasetType, StorageClass
from lsst.daf.butler.cli.butler import cli
from lsst.daf.butler.cli.cmd import query_dataset_types
from lsst.daf.butler.cli.utils import clickResultMsg
from lsst.daf.butler.cli.utils import clickResultMsg, LogCliRunner
from lsst.daf.butler.tests import CliCmdTestBase


Expand Down Expand Up @@ -69,7 +68,7 @@ def testQueryDatasetTypes(self):
visitDimension = "visit"
storageClassName = "testDatasetType"
expectedNotVerbose = {"datasetTypes": [datasetName]}
runner = click.testing.CliRunner()
runner = LogCliRunner()
with runner.isolated_filesystem():
butlerCfg = Butler.makeRepo("here")
butler = Butler(butlerCfg, writeable=True)
Expand Down
37 changes: 18 additions & 19 deletions tests/test_cliPluginLoader.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
"""

import click
import click.testing
from collections import defaultdict
from contextlib import contextmanager
import os
Expand All @@ -32,7 +31,7 @@
import yaml

from lsst.daf.butler.cli import butler, cmd
from lsst.daf.butler.cli.utils import command_test_env
from lsst.daf.butler.cli.utils import command_test_env, LogCliRunner


@click.command()
Expand Down Expand Up @@ -60,11 +59,13 @@ def duplicate_command_test_env(runner):

class FailedLoadTest(unittest.TestCase):

def setUp(self):
self.runner = LogCliRunner()

def test_unimportablePlugin(self):
runner = click.testing.CliRunner()
with command_test_env(runner, "test_cliPluginLoader", "non-existant-command-function"):
with command_test_env(self.runner, "test_cliPluginLoader", "non-existant-command-function"):
with self.assertLogs() as cm:
result = runner.invoke(butler.cli, "--help")
result = self.runner.invoke(butler.cli, "--help")
self.assertEqual(result.exit_code, 0, f"output: {result.output} exception: {result.exception}")
expectedErrMsg = "Could not import plugin from " \
"test_cliPluginLoader.non_existant_command_function, skipping."
Expand All @@ -78,37 +79,36 @@ class FailCLI(butler.LoaderCLI):
def cli():
pass

runner = click.testing.CliRunner()
with self.assertLogs() as cm:
result = runner.invoke(cli)
result = self.runner.invoke(cli)
self.assertEqual(result.exit_code, 0, f"output: {result.output} exception: {result.exception}")
expectedErrMsg = f"Could not import plugin from {FailCLI.localCmdPkg}, skipping."
self.assertIn(expectedErrMsg, " ".join(cm.output))


class PluginLoaderTest(unittest.TestCase):

def setUp(self):
self.runner = LogCliRunner()

def test_loadAndExecutePluginCommand(self):
"""Test that a plugin command can be loaded and executed."""
runner = click.testing.CliRunner()
with command_test_env(runner, "test_cliPluginLoader", "command-test"):
result = runner.invoke(butler.cli, "command-test")
with command_test_env(self.runner, "test_cliPluginLoader", "command-test"):
result = self.runner.invoke(butler.cli, "command-test")
self.assertEqual(result.exit_code, 0, f"output: {result.output} exception: {result.exception}")
self.assertEqual(result.stdout, "test command\n")

def test_loadAndExecuteLocalCommand(self):
"""Test that a command in daf_butler can be loaded and executed."""
runner = click.testing.CliRunner()
with runner.isolated_filesystem():
result = runner.invoke(butler.cli, ["create", "test_repo"])
with self.runner.isolated_filesystem():
result = self.runner.invoke(butler.cli, ["create", "test_repo"])
self.assertEqual(result.exit_code, 0, f"output: {result.output} exception: {result.exception}")
self.assertTrue(os.path.exists("test_repo"))

def test_loadTopHelp(self):
"""Test that an expected command is produced by 'butler --help'"""
runner = click.testing.CliRunner()
with command_test_env(runner, "test_cliPluginLoader", "command-test"):
result = runner.invoke(butler.cli, "--help")
with command_test_env(self.runner, "test_cliPluginLoader", "command-test"):
result = self.runner.invoke(butler.cli, "--help")
self.assertEqual(result.exit_code, 0, f"output: {result.output} exception: {result.exception}")
self.assertIn("command-test", result.stdout)

Expand All @@ -134,9 +134,8 @@ def test_listCommands_duplicate(self):
present and verify it fails to run.
"""
self.maxDiff = None
runner = click.testing.CliRunner()
with duplicate_command_test_env(runner):
result = runner.invoke(butler.cli, ["create", "test_repo"])
with duplicate_command_test_env(self.runner):
result = self.runner.invoke(butler.cli, ["create", "test_repo"])
self.assertEqual(result.exit_code, 1, f"output: {result.output} exception: {result.exception}")
self.assertEqual(result.output, "Error: Command 'create' "
"exists in packages lsst.daf.butler.cli.cmd, test_cliPluginLoader. "
Expand Down
21 changes: 9 additions & 12 deletions tests/test_cliUtilSplitCommas.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@
"""

import click
import click.testing
import unittest
from unittest.mock import MagicMock

from lsst.daf.butler.cli.utils import clickResultMsg, split_commas
from lsst.daf.butler.cli.utils import clickResultMsg, LogCliRunner, split_commas

mock = MagicMock()

Expand All @@ -40,6 +39,9 @@ def cli(list_of_values):

class SplitCommasTestCase(unittest.TestCase):

def setUp(self):
self.runner = LogCliRunner()

def test_separate(self):
"""test the split_commas callback by itself"""
ctx = "unused"
Expand All @@ -50,40 +52,35 @@ def test_separate(self):

def test_single(self):
"""test the split_commas callback in an option with one value"""
runner = click.testing.CliRunner()
result = runner.invoke(cli, ["-l", "one"])
result = self.runner.invoke(cli, ["-l", "one"])
self.assertEqual(result.exit_code, 0, msg=clickResultMsg(result))
mock.assert_called_with(("one", ))

def test_multiple(self):
"""test the split_commas callback in an option with two single
values"""
runner = click.testing.CliRunner()
result = runner.invoke(cli, ["-l", "one", "-l", "two"])
result = self.runner.invoke(cli, ["-l", "one", "-l", "two"])
self.assertEqual(result.exit_code, 0, msg=clickResultMsg(result))
mock.assert_called_with(("one", "two"))

def test_singlePair(self):
"""test the split_commas callback in an option with one pair of
values"""
runner = click.testing.CliRunner()
result = runner.invoke(cli, ["-l", "one,two"])
result = self.runner.invoke(cli, ["-l", "one,two"])
self.assertEqual(result.exit_code, 0, msg=clickResultMsg(result))
mock.assert_called_with(("one", "two"))

def test_multiplePair(self):
"""test the split_commas callback in an option with two pairs of
values"""
runner = click.testing.CliRunner()
result = runner.invoke(cli, ["-l", "one,two", "-l", "three,four"])
result = self.runner.invoke(cli, ["-l", "one,two", "-l", "three,four"])
self.assertEqual(result.exit_code, 0, msg=clickResultMsg(result))
mock.assert_called_with(("one", "two", "three", "four"))

def test_none(self):
"""test that passing None does not fail and returns None, producing an
empty tuple in the command function call."""
runner = click.testing.CliRunner()
result = runner.invoke(cli, [])
result = self.runner.invoke(cli, [])
self.assertEqual(result.exit_code, 0, msg=clickResultMsg(result))
mock.assert_called_with(())

Expand Down

0 comments on commit ea759ef

Please sign in to comment.