Explorar el Código

Merge pull request #2832 from aanand/refactor-cli-unit-tests

Refactor CLI initialization and unit tests
Aanand Prasad hace 9 años
padre
commit
4ae71f41dd

+ 1 - 1
.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

+ 4 - 4
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']
 

+ 16 - 0
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)])

+ 18 - 25
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"],

+ 32 - 65
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):
@@ -66,17 +67,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)
@@ -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,
@@ -110,49 +112,22 @@ 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()
+    def test_run_service_with_restart_always(self):
         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'])
+        project = Project.from_config(
+            name='composetest',
+            client=mock_client,
+            config_data=build_config({
+                'service': {
+                    'image': 'busybox',
+                    'restart': 'always',
+                }
+            }),
         )
 
-    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',
-            client=mock_client,
-            restart={'Name': 'always', 'MaximumRetryCount': 0},
-            image='someimage')
-        command.run(mock_project, {
+        command.run(project, {
             'SERVICE': 'service',
             'COMMAND': None,
             '-e': [],
@@ -173,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': [],
@@ -201,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': [],

+ 1 - 6
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(