From 2c75a8fdf556329acf1a8442cd9ac5f1e94be8cc Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Fri, 5 Feb 2016 17:03:05 +0000 Subject: [PATCH 1/4] Extract helper methods for building config objects from dicts Signed-off-by: Aanand Prasad --- .pre-commit-config.yaml | 2 +- tests/helpers.py | 16 ++++++++++++ tests/integration/project_test.py | 43 +++++++++++++------------------ tests/unit/config/config_test.py | 7 +---- 4 files changed, 36 insertions(+), 32 deletions(-) create mode 100644 tests/helpers.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index db2b6506b..e37677c69 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,7 +10,7 @@ - id: end-of-file-fixer - id: flake8 - id: name-tests-test - exclude: 'tests/integration/testcases.py' + exclude: 'tests/(helpers\.py|integration/testcases\.py)' - id: requirements-txt-fixer - id: trailing-whitespace - repo: git://github.com/asottile/reorder_python_imports diff --git a/tests/helpers.py b/tests/helpers.py new file mode 100644 index 000000000..dd0b668ed --- /dev/null +++ b/tests/helpers.py @@ -0,0 +1,16 @@ +from __future__ import absolute_import +from __future__ import unicode_literals + +from compose.config.config import ConfigDetails +from compose.config.config import ConfigFile +from compose.config.config import load + + +def build_config(contents, **kwargs): + return load(build_config_details(contents, **kwargs)) + + +def build_config_details(contents, working_dir='working_dir', filename='filename.yml'): + return ConfigDetails( + working_dir, + [ConfigFile(filename, contents)]) diff --git a/tests/integration/project_test.py b/tests/integration/project_test.py index 8915733c3..8400ba1fa 100644 --- a/tests/integration/project_test.py +++ b/tests/integration/project_test.py @@ -7,6 +7,7 @@ import py import pytest from docker.errors import NotFound +from ..helpers import build_config from .testcases import DockerClientTestCase from compose.config import config from compose.config import ConfigurationError @@ -20,13 +21,6 @@ from compose.service import ConvergenceStrategy from tests.integration.testcases import v2_only -def build_service_dicts(service_config): - return config.load( - config.ConfigDetails( - 'working_dir', - [config.ConfigFile(None, service_config)])) - - class ProjectTest(DockerClientTestCase): def test_containers(self): @@ -67,19 +61,18 @@ class ProjectTest(DockerClientTestCase): ) def test_volumes_from_service(self): - service_dicts = build_service_dicts({ - 'data': { - 'image': 'busybox:latest', - 'volumes': ['/var/data'], - }, - 'db': { - 'image': 'busybox:latest', - 'volumes_from': ['data'], - }, - }) project = Project.from_config( name='composetest', - config_data=service_dicts, + config_data=build_config({ + 'data': { + 'image': 'busybox:latest', + 'volumes': ['/var/data'], + }, + 'db': { + 'image': 'busybox:latest', + 'volumes_from': ['data'], + }, + }), client=self.client, ) db = project.get_service('db') @@ -96,7 +89,7 @@ class ProjectTest(DockerClientTestCase): ) project = Project.from_config( name='composetest', - config_data=build_service_dicts({ + config_data=build_config({ 'db': { 'image': 'busybox:latest', 'volumes_from': ['composetest_data_container'], @@ -112,7 +105,7 @@ class ProjectTest(DockerClientTestCase): project = Project.from_config( name='composetest', client=self.client, - config_data=build_service_dicts({ + config_data=build_config({ 'version': V2_0, 'services': { 'net': { @@ -139,7 +132,7 @@ class ProjectTest(DockerClientTestCase): def get_project(): return Project.from_config( name='composetest', - config_data=build_service_dicts({ + config_data=build_config({ 'version': V2_0, 'services': { 'web': { @@ -174,7 +167,7 @@ class ProjectTest(DockerClientTestCase): def test_net_from_service_v1(self): project = Project.from_config( name='composetest', - config_data=build_service_dicts({ + config_data=build_config({ 'net': { 'image': 'busybox:latest', 'command': ["top"] @@ -198,7 +191,7 @@ class ProjectTest(DockerClientTestCase): def get_project(): return Project.from_config( name='composetest', - config_data=build_service_dicts({ + config_data=build_config({ 'web': { 'image': 'busybox:latest', 'net': 'container:composetest_net_container' @@ -469,7 +462,7 @@ class ProjectTest(DockerClientTestCase): def test_project_up_starts_depends(self): project = Project.from_config( name='composetest', - config_data=build_service_dicts({ + config_data=build_config({ 'console': { 'image': 'busybox:latest', 'command': ["top"], @@ -504,7 +497,7 @@ class ProjectTest(DockerClientTestCase): def test_project_up_with_no_deps(self): project = Project.from_config( name='composetest', - config_data=build_service_dicts({ + config_data=build_config({ 'console': { 'image': 'busybox:latest', 'command': ["top"], diff --git a/tests/unit/config/config_test.py b/tests/unit/config/config_test.py index c2ca8e6ee..04f299c62 100644 --- a/tests/unit/config/config_test.py +++ b/tests/unit/config/config_test.py @@ -11,6 +11,7 @@ from operator import itemgetter import py import pytest +from ...helpers import build_config_details from compose.config import config from compose.config.config import resolve_build_args from compose.config.config import resolve_environment @@ -43,12 +44,6 @@ def service_sort(services): return sorted(services, key=itemgetter('name')) -def build_config_details(contents, working_dir='working_dir', filename='filename.yml'): - return config.ConfigDetails( - working_dir, - [config.ConfigFile(filename, contents)]) - - class ConfigTest(unittest.TestCase): def test_load(self): service_dicts = config.load( From 575b48749d1eb8f8a583a5b1d2336003a6f12383 Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Fri, 5 Feb 2016 17:53:35 +0000 Subject: [PATCH 2/4] Remove unused global_options arg from dispatch() Signed-off-by: Aanand Prasad --- compose/cli/docopt_command.py | 8 ++++---- tests/unit/cli_test.py | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compose/cli/docopt_command.py b/compose/cli/docopt_command.py index d2900b392..5b50189c8 100644 --- a/compose/cli/docopt_command.py +++ b/compose/cli/docopt_command.py @@ -20,12 +20,12 @@ class DocoptCommand(object): return {'options_first': True} def sys_dispatch(self): - self.dispatch(sys.argv[1:], None) + self.dispatch(sys.argv[1:]) - def dispatch(self, argv, global_options): - self.perform_command(*self.parse(argv, global_options)) + def dispatch(self, argv): + self.perform_command(*self.parse(argv)) - def parse(self, argv, global_options): + def parse(self, argv): options = docopt_full_help(getdoc(self), argv, **self.docopt_options()) command = options['COMMAND'] diff --git a/tests/unit/cli_test.py b/tests/unit/cli_test.py index 26ae4e300..3fc0a9855 100644 --- a/tests/unit/cli_test.py +++ b/tests/unit/cli_test.py @@ -66,17 +66,17 @@ class CLITestCase(unittest.TestCase): def test_help(self): command = TopLevelCommand() with self.assertRaises(SystemExit): - command.dispatch(['-h'], None) + command.dispatch(['-h']) def test_command_help(self): with self.assertRaises(SystemExit) as ctx: - TopLevelCommand().dispatch(['help', 'up'], None) + TopLevelCommand().dispatch(['help', 'up']) self.assertIn('Usage: up', str(ctx.exception)) def test_command_help_nonexistent(self): with self.assertRaises(NoSuchCommand): - TopLevelCommand().dispatch(['help', 'nonexistent'], None) + TopLevelCommand().dispatch(['help', 'nonexistent']) @pytest.mark.xfail(IS_WINDOWS_PLATFORM, reason="requires dockerpty") @mock.patch('compose.cli.main.RunOperation', autospec=True) From 4644f2c0f998d7f3a27464cb965265c041a17e2a Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Fri, 5 Feb 2016 13:12:43 +0000 Subject: [PATCH 3/4] Remove environment-overriding unit test for 'run' There's already an acceptance test for it Signed-off-by: Aanand Prasad --- tests/unit/cli_test.py | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/tests/unit/cli_test.py b/tests/unit/cli_test.py index 3fc0a9855..cf3c8e8f2 100644 --- a/tests/unit/cli_test.py +++ b/tests/unit/cli_test.py @@ -110,39 +110,6 @@ class CLITestCase(unittest.TestCase): _, _, call_kwargs = mock_run_operation.mock_calls[0] assert call_kwargs['logs'] is False - @pytest.mark.xfail(IS_WINDOWS_PLATFORM, reason="requires dockerpty") - @mock.patch('compose.cli.main.PseudoTerminal', autospec=True) - def test_run_with_environment_merged_with_options_list(self, mock_pseudo_terminal): - command = TopLevelCommand() - mock_client = mock.create_autospec(docker.Client) - mock_project = mock.Mock(client=mock_client) - mock_project.get_service.return_value = Service( - 'service', - client=mock_client, - environment=['FOO=ONE', 'BAR=TWO'], - image='someimage') - - command.run(mock_project, { - 'SERVICE': 'service', - 'COMMAND': None, - '-e': ['BAR=NEW', 'OTHER=bär'.encode('utf-8')], - '--user': None, - '--no-deps': None, - '-d': True, - '-T': None, - '--entrypoint': None, - '--service-ports': None, - '--publish': [], - '--rm': None, - '--name': None, - }) - - _, _, call_kwargs = mock_client.create_container.mock_calls[0] - assert ( - sorted(call_kwargs['environment']) == - sorted(['FOO=ONE', 'BAR=NEW', 'OTHER=bär']) - ) - def test_run_service_with_restart_always(self): command = TopLevelCommand() mock_client = mock.create_autospec(docker.Client) From 20caf02bf6a99d316615769af558c7212e25927b Mon Sep 17 00:00:00 2001 From: Aanand Prasad Date: Fri, 5 Feb 2016 17:09:07 +0000 Subject: [PATCH 4/4] Create real Project objects in CLI unit tests Signed-off-by: Aanand Prasad --- tests/unit/cli_test.py | 62 +++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/tests/unit/cli_test.py b/tests/unit/cli_test.py index cf3c8e8f2..cbe9ea6f9 100644 --- a/tests/unit/cli_test.py +++ b/tests/unit/cli_test.py @@ -10,13 +10,14 @@ import pytest from .. import mock from .. import unittest +from ..helpers import build_config from compose.cli.command import get_project from compose.cli.command import get_project_name from compose.cli.docopt_command import NoSuchCommand from compose.cli.errors import UserError from compose.cli.main import TopLevelCommand from compose.const import IS_WINDOWS_PLATFORM -from compose.service import Service +from compose.project import Project class CLITestCase(unittest.TestCase): @@ -84,18 +85,19 @@ class CLITestCase(unittest.TestCase): def test_run_interactive_passes_logs_false(self, mock_pseudo_terminal, mock_run_operation): command = TopLevelCommand() mock_client = mock.create_autospec(docker.Client) - mock_project = mock.Mock(client=mock_client) - mock_project.get_service.return_value = Service( - 'service', + project = Project.from_config( + name='composetest', client=mock_client, - environment=['FOO=ONE', 'BAR=TWO'], - image='someimage') + config_data=build_config({ + 'service': {'image': 'busybox'} + }), + ) with pytest.raises(SystemExit): - command.run(mock_project, { + command.run(project, { 'SERVICE': 'service', 'COMMAND': None, - '-e': ['BAR=NEW', 'OTHER=bär'.encode('utf-8')], + '-e': [], '--user': None, '--no-deps': None, '-d': False, @@ -111,15 +113,21 @@ class CLITestCase(unittest.TestCase): assert call_kwargs['logs'] is False def test_run_service_with_restart_always(self): - command = TopLevelCommand() mock_client = mock.create_autospec(docker.Client) - mock_project = mock.Mock(client=mock_client) - mock_project.get_service.return_value = Service( - 'service', + + project = Project.from_config( + name='composetest', client=mock_client, - restart={'Name': 'always', 'MaximumRetryCount': 0}, - image='someimage') - command.run(mock_project, { + config_data=build_config({ + 'service': { + 'image': 'busybox', + 'restart': 'always', + } + }), + ) + + command = TopLevelCommand() + command.run(project, { 'SERVICE': 'service', 'COMMAND': None, '-e': [], @@ -140,14 +148,7 @@ class CLITestCase(unittest.TestCase): ) command = TopLevelCommand() - mock_client = mock.create_autospec(docker.Client) - mock_project = mock.Mock(client=mock_client) - mock_project.get_service.return_value = Service( - 'service', - client=mock_client, - restart='always', - image='someimage') - command.run(mock_project, { + command.run(project, { 'SERVICE': 'service', 'COMMAND': None, '-e': [], @@ -168,17 +169,16 @@ class CLITestCase(unittest.TestCase): def test_command_manula_and_service_ports_together(self): command = TopLevelCommand() - mock_client = mock.create_autospec(docker.Client) - mock_project = mock.Mock(client=mock_client) - mock_project.get_service.return_value = Service( - 'service', - client=mock_client, - restart='always', - image='someimage', + project = Project.from_config( + name='composetest', + client=None, + config_data=build_config({ + 'service': {'image': 'busybox'}, + }), ) with self.assertRaises(UserError): - command.run(mock_project, { + command.run(project, { 'SERVICE': 'service', 'COMMAND': None, '-e': [],