rally/tests/verification/verifiers/test_tempest.py
Andrey Kurilin b9a1fab7a0 Refactor tempest config generator
Use `requests` library instead of `urllib2` & `httplib`
Main profit from `requests` library:
- `requests` is HTTP for Humans;
- `requests` is well documented[1];
- `requests` can save downloaded files by parts, so usage of memory
is less(useful when downloading big data, for example - some images)
- `requests` has same name as in Python 2x and Python 3x

Use `inspect.getmembers`[2][3] for discovery of each function for section
generator. Profit : decrease lines of code

Add checks for existence of subnet in 'network' section.

Move function `_write_config`[4] from class `Tempest`[5] to `TempestConf`.
Reason: this function not related to verifier for Tempest.

Fix message for exception when user doesn't have admin role.

Move name of section into kwargs to each section function.
Profit: less string objects with section names

[1] - http://docs.python-requests.org/en/latest/
[2] - https://docs.python.org/2/library/inspect.html#types-and-members
[3] - https://docs.python.org/3.3/library/inspect.html#types-and-members
[4] - http://git.io/E1zPOQ
[5] - http://git.io/8Ru-Yw

Change-Id: I8307ec33dd93ef055450f58d7cd55bf6b200f249
2014-06-20 17:01:19 +03:00

201 lines
8.2 KiB
Python

# Copyright 2014: Mirantis Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import mock
from rally.openstack.common import jsonutils
from rally.verification.verifiers.tempest import subunit2json
from rally.verification.verifiers.tempest import tempest
from tests import test
TEMPEST_PATH = 'rally.verification.verifiers.tempest'
class TempestTestCase(test.TestCase):
def setUp(self):
super(TempestTestCase, self).setUp()
self.verifier = tempest.Tempest('fake_deploy_id',
verification=mock.MagicMock())
self.verifier.tempest_path = '/tmp'
self.verifier.config_file = '/tmp/tempest.conf'
self.verifier.log_file_raw = '/tmp/subunit.stream'
self.regex = None
@mock.patch('os.path.exists')
def test_is_installed(self, mock_exists):
mock_exists.return_value = True
result = self.verifier.is_installed()
mock_exists.assert_called_once_with(
os.path.join(self.verifier.tempest_path, '.venv'))
self.assertTrue(result)
@mock.patch('rally.verification.verifiers.tempest.tempest.subprocess')
def test__clone(self, mock_sp):
self.verifier._clone()
mock_sp.check_call.assert_called_once_with(
['git', 'clone', 'https://github.com/openstack/tempest',
tempest.Tempest.tempest_base_path])
@mock.patch(TEMPEST_PATH + '.tempest.Tempest._initialize_testr')
@mock.patch(TEMPEST_PATH + '.tempest.Tempest._install_venv')
@mock.patch(TEMPEST_PATH + '.tempest.subprocess')
@mock.patch('os.path.exists')
@mock.patch('shutil.copytree')
def test_install(
self, mock_copytree, mock_exists, mock_sp, mock_venv, mock_testr):
mock_exists.side_effect = (False, True, False)
# simulate tempest is clonned but is not installed for current deploy
self.verifier.install()
mock_copytree.assert_called_once_with(
tempest.Tempest.tempest_base_path,
self.verifier.tempest_path)
mock_sp.check_call.assert_called_once_with(
'git checkout master; git remote update; git pull',
cwd=os.path.join(self.verifier.tempest_path, 'tempest'),
shell=True)
@mock.patch('rally.verification.verifiers.tempest.tempest.shutil')
@mock.patch('os.path.exists')
def test_uninstall(self, mock_exists, mock_shutil):
mock_exists.return_value = True
self.verifier.uninstall()
mock_shutil.rmtree.assert_called_once_with(self.verifier.tempest_path)
@mock.patch(TEMPEST_PATH + '.tempest.Tempest.env')
@mock.patch(TEMPEST_PATH + '.tempest.subprocess')
def test_run(self, mock_sp, mock_env):
self.verifier.run('tempest.api.image')
fake_call = (
'%(venv)s testr run --parallel --subunit tempest.api.image '
'| tee %(tempest_path)s/subunit.stream '
'| %(venv)s subunit-2to1 '
'| %(venv)s %(tempest_path)s/tools/colorizer.py' % {
'venv': self.verifier.venv_wrapper,
'tempest_path': self.verifier.tempest_path})
mock_sp.check_call.assert_called_once_with(
fake_call, env=mock_env, cwd=self.verifier.tempest_path,
shell=True)
@mock.patch(TEMPEST_PATH + '.tempest.os.remove')
@mock.patch(TEMPEST_PATH + '.tempest.Tempest.discover_tests')
@mock.patch(TEMPEST_PATH + '.tempest.Tempest._initialize_testr')
@mock.patch(TEMPEST_PATH + '.tempest.Tempest.run')
@mock.patch(TEMPEST_PATH + '.config.TempestConf')
@mock.patch('rally.db.deployment_get')
@mock.patch('rally.osclients.Clients')
@mock.patch('rally.objects.endpoint.Endpoint')
def test_verify(self, mock_endpoint, mock_osclients, mock_get, mock_conf,
mock_run, mock_testr_init, mock_discover, mock_os):
self.verifier.verify("smoke", None)
mock_conf().generate.assert_called_once_with(self.verifier.config_file)
mock_run.assert_called_once_with("smoke")
@mock.patch('os.environ')
def test__generate_env(self, mock_env):
expected_env = {'PATH': '/some/path'}
mock_env.copy.return_value = expected_env.copy()
expected_env.update({
'TEMPEST_CONFIG': 'tempest.conf',
'TEMPEST_CONFIG_DIR': self.verifier.tempest_path,
'OS_TEST_PATH': os.path.join(self.verifier.tempest_path,
'tempest/test_discover')})
self.assertIsNone(self.verifier._env)
self.verifier._generate_env()
self.assertEqual(expected_env, self.verifier._env)
@mock.patch('os.path.isdir')
@mock.patch(TEMPEST_PATH + '.tempest.subprocess')
def test__venv_install_when_venv_exists(self, mock_sp, mock_isdir):
mock_isdir.return_value = True
self.verifier._install_venv()
mock_isdir.assert_called_once_with(
os.path.join(self.verifier.tempest_path, '.venv'))
self.assertFalse(mock_sp.called)
@mock.patch('os.path.isdir')
@mock.patch(TEMPEST_PATH + '.tempest.subprocess.check_call')
def test__venv_install_when_venv_not_exist(self, mock_sp, mock_isdir):
mock_isdir.return_value = False
self.verifier._install_venv()
mock_isdir.assert_called_once_with(
os.path.join(self.verifier.tempest_path, '.venv'))
mock_sp.assert_has_calls([
mock.call('python ./tools/install_venv.py', shell=True,
cwd=self.verifier.tempest_path),
mock.call('%s python setup.py install' %
self.verifier.venv_wrapper, shell=True,
cwd=self.verifier.tempest_path)])
@mock.patch('os.path.isdir')
@mock.patch(TEMPEST_PATH + '.tempest.subprocess')
def test__initialize_testr_when_testr_already_initialized(
self, mock_sp, mock_isdir):
mock_isdir.return_value = True
self.verifier._initialize_testr()
mock_isdir.assert_called_once_with(
os.path.join(self.verifier.tempest_path, '.testrepository'))
self.assertFalse(mock_sp.called)
@mock.patch('os.path.isdir')
@mock.patch(TEMPEST_PATH + '.tempest.subprocess.check_call')
def test__initialize_testr_when_testr_not_initialized(
self, mock_sp, mock_isdir):
mock_isdir.return_value = False
self.verifier._initialize_testr()
mock_isdir.assert_called_once_with(
os.path.join(self.verifier.tempest_path, '.testrepository'))
mock_sp.assert_called_once_with(
'%s testr init' % self.verifier.venv_wrapper, shell=True,
cwd=self.verifier.tempest_path)
@mock.patch('xml.dom.minidom.parse')
@mock.patch('os.path.isfile')
def test__save_results_without_log_file(self, mock_isfile, mock_parse):
mock_isfile.return_value = False
self.verifier._save_results()
mock_isfile.assert_called_once_with(self.verifier.log_file_raw)
self.assertEqual(0, mock_parse.call_count)
@mock.patch('os.path.isfile')
def test__save_results_with_log_file(self, mock_isfile):
with mock.patch.object(subunit2json, 'main') as mock_main:
mock_isfile.return_value = True
data = {'total': True, 'test_cases': True}
mock_main.return_value = jsonutils.dumps(data)
self.verifier.log_file_raw = os.path.join(
os.path.dirname(__file__),
'subunit.stream')
self.verifier._save_results()
mock_isfile.assert_called_once_with(self.verifier.log_file_raw)
mock_main.assert_called_once_with(
self.verifier.log_file_raw)
self.assertEqual(
1, self.verifier.verification.finish_verification.call_count)