mirror of https://github.com/docker/docs.git
Merge pull request #2832 from aanand/refactor-cli-unit-tests
Refactor CLI initialization and unit tests
This commit is contained in:
commit
4ae71f41dd
|
@ -10,7 +10,7 @@
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: flake8
|
- id: flake8
|
||||||
- id: name-tests-test
|
- id: name-tests-test
|
||||||
exclude: 'tests/integration/testcases.py'
|
exclude: 'tests/(helpers\.py|integration/testcases\.py)'
|
||||||
- id: requirements-txt-fixer
|
- id: requirements-txt-fixer
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- repo: git://github.com/asottile/reorder_python_imports
|
- repo: git://github.com/asottile/reorder_python_imports
|
||||||
|
|
|
@ -20,12 +20,12 @@ class DocoptCommand(object):
|
||||||
return {'options_first': True}
|
return {'options_first': True}
|
||||||
|
|
||||||
def sys_dispatch(self):
|
def sys_dispatch(self):
|
||||||
self.dispatch(sys.argv[1:], None)
|
self.dispatch(sys.argv[1:])
|
||||||
|
|
||||||
def dispatch(self, argv, global_options):
|
def dispatch(self, argv):
|
||||||
self.perform_command(*self.parse(argv, global_options))
|
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())
|
options = docopt_full_help(getdoc(self), argv, **self.docopt_options())
|
||||||
command = options['COMMAND']
|
command = options['COMMAND']
|
||||||
|
|
||||||
|
|
|
@ -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)])
|
|
@ -7,6 +7,7 @@ import py
|
||||||
import pytest
|
import pytest
|
||||||
from docker.errors import NotFound
|
from docker.errors import NotFound
|
||||||
|
|
||||||
|
from ..helpers import build_config
|
||||||
from .testcases import DockerClientTestCase
|
from .testcases import DockerClientTestCase
|
||||||
from compose.config import config
|
from compose.config import config
|
||||||
from compose.config import ConfigurationError
|
from compose.config import ConfigurationError
|
||||||
|
@ -20,13 +21,6 @@ from compose.service import ConvergenceStrategy
|
||||||
from tests.integration.testcases import v2_only
|
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):
|
class ProjectTest(DockerClientTestCase):
|
||||||
|
|
||||||
def test_containers(self):
|
def test_containers(self):
|
||||||
|
@ -67,19 +61,18 @@ class ProjectTest(DockerClientTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_volumes_from_service(self):
|
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(
|
project = Project.from_config(
|
||||||
name='composetest',
|
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,
|
client=self.client,
|
||||||
)
|
)
|
||||||
db = project.get_service('db')
|
db = project.get_service('db')
|
||||||
|
@ -96,7 +89,7 @@ class ProjectTest(DockerClientTestCase):
|
||||||
)
|
)
|
||||||
project = Project.from_config(
|
project = Project.from_config(
|
||||||
name='composetest',
|
name='composetest',
|
||||||
config_data=build_service_dicts({
|
config_data=build_config({
|
||||||
'db': {
|
'db': {
|
||||||
'image': 'busybox:latest',
|
'image': 'busybox:latest',
|
||||||
'volumes_from': ['composetest_data_container'],
|
'volumes_from': ['composetest_data_container'],
|
||||||
|
@ -112,7 +105,7 @@ class ProjectTest(DockerClientTestCase):
|
||||||
project = Project.from_config(
|
project = Project.from_config(
|
||||||
name='composetest',
|
name='composetest',
|
||||||
client=self.client,
|
client=self.client,
|
||||||
config_data=build_service_dicts({
|
config_data=build_config({
|
||||||
'version': V2_0,
|
'version': V2_0,
|
||||||
'services': {
|
'services': {
|
||||||
'net': {
|
'net': {
|
||||||
|
@ -139,7 +132,7 @@ class ProjectTest(DockerClientTestCase):
|
||||||
def get_project():
|
def get_project():
|
||||||
return Project.from_config(
|
return Project.from_config(
|
||||||
name='composetest',
|
name='composetest',
|
||||||
config_data=build_service_dicts({
|
config_data=build_config({
|
||||||
'version': V2_0,
|
'version': V2_0,
|
||||||
'services': {
|
'services': {
|
||||||
'web': {
|
'web': {
|
||||||
|
@ -174,7 +167,7 @@ class ProjectTest(DockerClientTestCase):
|
||||||
def test_net_from_service_v1(self):
|
def test_net_from_service_v1(self):
|
||||||
project = Project.from_config(
|
project = Project.from_config(
|
||||||
name='composetest',
|
name='composetest',
|
||||||
config_data=build_service_dicts({
|
config_data=build_config({
|
||||||
'net': {
|
'net': {
|
||||||
'image': 'busybox:latest',
|
'image': 'busybox:latest',
|
||||||
'command': ["top"]
|
'command': ["top"]
|
||||||
|
@ -198,7 +191,7 @@ class ProjectTest(DockerClientTestCase):
|
||||||
def get_project():
|
def get_project():
|
||||||
return Project.from_config(
|
return Project.from_config(
|
||||||
name='composetest',
|
name='composetest',
|
||||||
config_data=build_service_dicts({
|
config_data=build_config({
|
||||||
'web': {
|
'web': {
|
||||||
'image': 'busybox:latest',
|
'image': 'busybox:latest',
|
||||||
'net': 'container:composetest_net_container'
|
'net': 'container:composetest_net_container'
|
||||||
|
@ -469,7 +462,7 @@ class ProjectTest(DockerClientTestCase):
|
||||||
def test_project_up_starts_depends(self):
|
def test_project_up_starts_depends(self):
|
||||||
project = Project.from_config(
|
project = Project.from_config(
|
||||||
name='composetest',
|
name='composetest',
|
||||||
config_data=build_service_dicts({
|
config_data=build_config({
|
||||||
'console': {
|
'console': {
|
||||||
'image': 'busybox:latest',
|
'image': 'busybox:latest',
|
||||||
'command': ["top"],
|
'command': ["top"],
|
||||||
|
@ -504,7 +497,7 @@ class ProjectTest(DockerClientTestCase):
|
||||||
def test_project_up_with_no_deps(self):
|
def test_project_up_with_no_deps(self):
|
||||||
project = Project.from_config(
|
project = Project.from_config(
|
||||||
name='composetest',
|
name='composetest',
|
||||||
config_data=build_service_dicts({
|
config_data=build_config({
|
||||||
'console': {
|
'console': {
|
||||||
'image': 'busybox:latest',
|
'image': 'busybox:latest',
|
||||||
'command': ["top"],
|
'command': ["top"],
|
||||||
|
|
|
@ -10,13 +10,14 @@ import pytest
|
||||||
|
|
||||||
from .. import mock
|
from .. import mock
|
||||||
from .. import unittest
|
from .. import unittest
|
||||||
|
from ..helpers import build_config
|
||||||
from compose.cli.command import get_project
|
from compose.cli.command import get_project
|
||||||
from compose.cli.command import get_project_name
|
from compose.cli.command import get_project_name
|
||||||
from compose.cli.docopt_command import NoSuchCommand
|
from compose.cli.docopt_command import NoSuchCommand
|
||||||
from compose.cli.errors import UserError
|
from compose.cli.errors import UserError
|
||||||
from compose.cli.main import TopLevelCommand
|
from compose.cli.main import TopLevelCommand
|
||||||
from compose.const import IS_WINDOWS_PLATFORM
|
from compose.const import IS_WINDOWS_PLATFORM
|
||||||
from compose.service import Service
|
from compose.project import Project
|
||||||
|
|
||||||
|
|
||||||
class CLITestCase(unittest.TestCase):
|
class CLITestCase(unittest.TestCase):
|
||||||
|
@ -66,17 +67,17 @@ class CLITestCase(unittest.TestCase):
|
||||||
def test_help(self):
|
def test_help(self):
|
||||||
command = TopLevelCommand()
|
command = TopLevelCommand()
|
||||||
with self.assertRaises(SystemExit):
|
with self.assertRaises(SystemExit):
|
||||||
command.dispatch(['-h'], None)
|
command.dispatch(['-h'])
|
||||||
|
|
||||||
def test_command_help(self):
|
def test_command_help(self):
|
||||||
with self.assertRaises(SystemExit) as ctx:
|
with self.assertRaises(SystemExit) as ctx:
|
||||||
TopLevelCommand().dispatch(['help', 'up'], None)
|
TopLevelCommand().dispatch(['help', 'up'])
|
||||||
|
|
||||||
self.assertIn('Usage: up', str(ctx.exception))
|
self.assertIn('Usage: up', str(ctx.exception))
|
||||||
|
|
||||||
def test_command_help_nonexistent(self):
|
def test_command_help_nonexistent(self):
|
||||||
with self.assertRaises(NoSuchCommand):
|
with self.assertRaises(NoSuchCommand):
|
||||||
TopLevelCommand().dispatch(['help', 'nonexistent'], None)
|
TopLevelCommand().dispatch(['help', 'nonexistent'])
|
||||||
|
|
||||||
@pytest.mark.xfail(IS_WINDOWS_PLATFORM, reason="requires dockerpty")
|
@pytest.mark.xfail(IS_WINDOWS_PLATFORM, reason="requires dockerpty")
|
||||||
@mock.patch('compose.cli.main.RunOperation', autospec=True)
|
@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):
|
def test_run_interactive_passes_logs_false(self, mock_pseudo_terminal, mock_run_operation):
|
||||||
command = TopLevelCommand()
|
command = TopLevelCommand()
|
||||||
mock_client = mock.create_autospec(docker.Client)
|
mock_client = mock.create_autospec(docker.Client)
|
||||||
mock_project = mock.Mock(client=mock_client)
|
project = Project.from_config(
|
||||||
mock_project.get_service.return_value = Service(
|
name='composetest',
|
||||||
'service',
|
|
||||||
client=mock_client,
|
client=mock_client,
|
||||||
environment=['FOO=ONE', 'BAR=TWO'],
|
config_data=build_config({
|
||||||
image='someimage')
|
'service': {'image': 'busybox'}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
with pytest.raises(SystemExit):
|
with pytest.raises(SystemExit):
|
||||||
command.run(mock_project, {
|
command.run(project, {
|
||||||
'SERVICE': 'service',
|
'SERVICE': 'service',
|
||||||
'COMMAND': None,
|
'COMMAND': None,
|
||||||
'-e': ['BAR=NEW', 'OTHER=bär'.encode('utf-8')],
|
'-e': [],
|
||||||
'--user': None,
|
'--user': None,
|
||||||
'--no-deps': None,
|
'--no-deps': None,
|
||||||
'-d': False,
|
'-d': False,
|
||||||
|
@ -110,49 +112,22 @@ class CLITestCase(unittest.TestCase):
|
||||||
_, _, call_kwargs = mock_run_operation.mock_calls[0]
|
_, _, call_kwargs = mock_run_operation.mock_calls[0]
|
||||||
assert call_kwargs['logs'] is False
|
assert call_kwargs['logs'] is False
|
||||||
|
|
||||||
@pytest.mark.xfail(IS_WINDOWS_PLATFORM, reason="requires dockerpty")
|
def test_run_service_with_restart_always(self):
|
||||||
@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_client = mock.create_autospec(docker.Client)
|
||||||
mock_project = mock.Mock(client=mock_client)
|
|
||||||
mock_project.get_service.return_value = Service(
|
project = Project.from_config(
|
||||||
'service',
|
name='composetest',
|
||||||
client=mock_client,
|
client=mock_client,
|
||||||
environment=['FOO=ONE', 'BAR=TWO'],
|
config_data=build_config({
|
||||||
image='someimage')
|
'service': {
|
||||||
|
'image': 'busybox',
|
||||||
command.run(mock_project, {
|
'restart': 'always',
|
||||||
'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()
|
command = TopLevelCommand()
|
||||||
mock_client = mock.create_autospec(docker.Client)
|
command.run(project, {
|
||||||
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, {
|
|
||||||
'SERVICE': 'service',
|
'SERVICE': 'service',
|
||||||
'COMMAND': None,
|
'COMMAND': None,
|
||||||
'-e': [],
|
'-e': [],
|
||||||
|
@ -173,14 +148,7 @@ class CLITestCase(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
command = TopLevelCommand()
|
command = TopLevelCommand()
|
||||||
mock_client = mock.create_autospec(docker.Client)
|
command.run(project, {
|
||||||
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, {
|
|
||||||
'SERVICE': 'service',
|
'SERVICE': 'service',
|
||||||
'COMMAND': None,
|
'COMMAND': None,
|
||||||
'-e': [],
|
'-e': [],
|
||||||
|
@ -201,17 +169,16 @@ class CLITestCase(unittest.TestCase):
|
||||||
|
|
||||||
def test_command_manula_and_service_ports_together(self):
|
def test_command_manula_and_service_ports_together(self):
|
||||||
command = TopLevelCommand()
|
command = TopLevelCommand()
|
||||||
mock_client = mock.create_autospec(docker.Client)
|
project = Project.from_config(
|
||||||
mock_project = mock.Mock(client=mock_client)
|
name='composetest',
|
||||||
mock_project.get_service.return_value = Service(
|
client=None,
|
||||||
'service',
|
config_data=build_config({
|
||||||
client=mock_client,
|
'service': {'image': 'busybox'},
|
||||||
restart='always',
|
}),
|
||||||
image='someimage',
|
|
||||||
)
|
)
|
||||||
|
|
||||||
with self.assertRaises(UserError):
|
with self.assertRaises(UserError):
|
||||||
command.run(mock_project, {
|
command.run(project, {
|
||||||
'SERVICE': 'service',
|
'SERVICE': 'service',
|
||||||
'COMMAND': None,
|
'COMMAND': None,
|
||||||
'-e': [],
|
'-e': [],
|
||||||
|
|
|
@ -11,6 +11,7 @@ from operator import itemgetter
|
||||||
import py
|
import py
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from ...helpers import build_config_details
|
||||||
from compose.config import config
|
from compose.config import config
|
||||||
from compose.config.config import resolve_build_args
|
from compose.config.config import resolve_build_args
|
||||||
from compose.config.config import resolve_environment
|
from compose.config.config import resolve_environment
|
||||||
|
@ -43,12 +44,6 @@ def service_sort(services):
|
||||||
return sorted(services, key=itemgetter('name'))
|
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):
|
class ConfigTest(unittest.TestCase):
|
||||||
def test_load(self):
|
def test_load(self):
|
||||||
service_dicts = config.load(
|
service_dicts = config.load(
|
||||||
|
|
Loading…
Reference in New Issue