oslotest-3.2.0/0000775000175100017510000000000013225157271013421 5ustar zuulzuul00000000000000oslotest-3.2.0/tools/0000775000175100017510000000000013225157271014561 5ustar zuulzuul00000000000000oslotest-3.2.0/tools/oslo_run_cross_tests0000777000175100017510000000547413225157020021006 0ustar zuulzuul00000000000000#!/bin/bash # # Run cross-project tests # # Usage: # # oslo_run_cross_tests project_dir venv # Fail the build if any command fails set -e function usage { cat - < ./subunit_log.txt fi .tox/$venv/bin/python /usr/local/jenkins/slave_scripts/subunit2html.py ./subunit_log.txt testr_results.html gzip -9 ./subunit_log.txt gzip -9 ./testr_results.html export PYTHON=.tox/$venv/bin/python set -e rancount=$(.tox/$venv/bin/testr last | sed -ne 's/Ran \([0-9]\+\).*tests in.*/\1/p') if [ "$rancount" -eq "0" ] ; then echo echo "Zero tests were run. At least one test should have been run." echo "Failing this test as a result" echo exit 1 fi fi # If we make it this far, report status based on the tests that were # run. exit $result oslotest-3.2.0/tools/oslo_debug_helper0000777000175100017510000000217113225157020020163 0ustar zuulzuul00000000000000#!/bin/bash # oslo_debug_helper - Script that allows for debugging tests # # oslo_debug_helper [-t ] [] # # - may be a test suite, class, or function, if no value is # passed, then all tests are run. # -t - the name of the directory that houses the tests # relative to the project directory. If no value is passed, it is assumed # to be packagename/tests. TMP_DIR=`mktemp -d debug-$$-XXX` || exit 1 trap "rm -rf $TMP_DIR" EXIT ALL_TESTS=$TMP_DIR/all_tests TESTS_TO_RUN=$TMP_DIR/tests_to_run # Default to packagename/tests, i.e., keystone/tests PACKAGENAME=$(python setup.py --name) TEST_DIR=./$PACKAGENAME/tests # If a specific path is passed, use that one while getopts ":t:" opt; do case $opt in t) TEST_DIR=$OPTARG;; esac done python -m testtools.run discover -t ./ $TEST_DIR --list > $ALL_TESTS # getopts friendly way of determining if a positional arg has been passed ARG1=${@:$OPTIND:1} if [ "$ARG1" ]; then grep "$ARG1" < $ALL_TESTS > $TESTS_TO_RUN else mv $ALL_TESTS $TESTS_TO_RUN fi python -m testtools.run discover --load-list $TESTS_TO_RUN oslotest-3.2.0/tools/oslo_run_pre_release_tests0000777000175100017510000001503513225157020022135 0ustar zuulzuul00000000000000#!/usr/bin/env python # # 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. """Run unit tests for projects that use a library. """ from __future__ import print_function import glob import os import subprocess import sys from oslo_config import cfg from oslotest.tools import config as tconfig from pbr import packaging import pkg_resources def find_all_projects(repo_root): """Scan the checked out repositories for all available projects. """ pattern = os.path.join(repo_root, 'openstack/*') candidates = glob.glob(pattern) prefix_len = len(repo_root) return [ c[prefix_len:].lstrip('/') for c in candidates if os.path.isdir(c) ] def find_consuming_projects(lib_name, repo_root, projects): """Filter the list of projects to only include entries that use the library. """ for p in projects: consumer = False for base in packaging.get_requirements_files(): req_file = os.path.join(repo_root, p, base) for req in packaging.parse_requirements([req_file]): try: parsed_req = pkg_resources.Requirement.parse(req) req_name = parsed_req.project_name except ValueError: continue if req_name == lib_name: consumer = True yield p break if consumer: break def main(): conf = tconfig.get_config_parser() conf.register_cli_opt( cfg.StrOpt( 'library-under-test', short='l', default='', help=('the name of the library being tested; ' 'defaults to current dir'), ) ) conf.register_cli_opt( cfg.BoolOpt( 'update', short='u', default=False, help='update consumers before running tests', ) ) conf.register_cli_opt( cfg.BoolOpt( 'verbose', short='v', default=False, help='print verbose output', ) ) conf.register_cli_opt( cfg.StrOpt( 'ref', short='r', default='HEAD', help='the commit reference to test; defaults to HEAD', ) ) conf.register_cli_opt( cfg.MultiStrOpt( 'env', short='e', default=['py27', 'pep8'], help=('the name of the tox environment to test; ' 'defaults to py27 and pep8'), ) ) conf.register_cli_opt( cfg.MultiStrOpt( 'consumer', positional=True, default=[], help='the name of a project to test with; may be repeated', ) ) tconfig.parse_arguments(conf) repo_root = os.path.expanduser(conf.repo_root) # Figure out which library is being tested lib_name = conf.library_under_test if not lib_name: if conf.verbose: print('finding library name') lib_name = subprocess.check_output( ['python', 'setup.py', '--name'] ).strip() lib_dir = os.getcwd() else: lib_dir = os.path.join(repo_root, 'openstack', lib_name) print('testing %s in %s' % (lib_name, lib_dir)) projects = set(conf.consumer) if not projects: # TODO(dhellmann): Need to update this to look at gerrit, so # we can check out the projects we want to test with. if conf.verbose: print('defaulting to all projects under %s/openstack' % repo_root) projects = find_all_projects(repo_root) # Filter out projects that do not require the library under test before = len(projects) projects = list(find_consuming_projects(lib_name, repo_root, projects)) after = len(projects) if (after < before) and conf.verbose: print('ignoring %s projects that do not use %s' % (before - after, lib_name)) projects = list(sorted(projects)) if not projects: print('ERROR: found no projects using %s' % lib_name) return 1 if conf.verbose: print('preparing to test %s projects' % after) # Make sure the lib being tested is set to the reference intended. if conf.ref != 'HEAD': if conf.verbose: print('ensuring %s is updated to %s' % (lib_name, conf.ref)) subprocess.check_call( ['git', 'checkout', conf.ref], cwd=lib_dir, ) git_quiet = ['-q'] if not conf.verbose else [] failures = [] for p in projects: if conf.verbose: print() proj_dir = os.path.join(repo_root, p) if conf.update: if conf.verbose: print('updating %s with "git pull"' % p) subprocess.Popen( ['git', 'pull'] + git_quiet, cwd=proj_dir, ).communicate() p_log_name = p.split('/')[-1].replace('.', '-') for e in conf.env: log_name = 'cross-test-%s-%s.log' % (p_log_name, e) with open(log_name, 'w') as log_file: print('testing %s in %s, logging to %s' % (e, p, log_name), end=' ') sys.stdout.flush() command = ['oslo_run_cross_tests', proj_dir, e] log_file.write('running: %s\n' % ' '.join(command)) log_file.flush() # since Popen is going to use the fd directly cmd = subprocess.Popen( command, cwd=lib_dir, stdout=log_file, stderr=log_file ) cmd.communicate() log_file.write('\nexit code: %s\n' % cmd.returncode) if cmd.returncode: print('FAIL') failures.append((p, e, cmd.returncode)) else: print('PASS') if failures: print('\nFAILED %d jobs' % len(failures)) return 1 print('\nPASSED all jobs') return 0 if __name__ == '__main__': sys.exit(main()) oslotest-3.2.0/oslotest/0000775000175100017510000000000013225157271015275 5ustar zuulzuul00000000000000oslotest-3.2.0/oslotest/functional.py0000666000175100017510000000510413225157020020003 0ustar zuulzuul00000000000000# Copyright (c) 2015 Hewlett-Packard Development Company, L.P. # # 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. from debtcollector import removals import os_client_config removals.removed_module("oslotest.functional", version="2.9.0", removal_version="3.0", message="oslotest.functional will be removed.") def _get_openstack_auth(openstack_config, cloud_name, override_name): try: cloud_config = openstack_config.get_one_cloud(cloud_name) except os_client_config.exceptions.OpenStackConfigException: try: cloud_config = openstack_config.get_one_cloud( 'devstack', auth=dict( username=override_name, project_name=override_name)) except os_client_config.exceptions.OpenStackConfigException: try: cloud_config = openstack_config.get_one_cloud('envvars') except os_client_config.exceptions.OpenStackConfigException: cloud_config = None return cloud_config class FunctionalAuth(object): def __init__(self): # Collecting of credentials: # # Grab the cloud config from a user's clouds.yaml file. # First look for a functional_admin cloud, as this is a cloud # that the user may have defined for functional testing that has # admin credentials. # # If that is not found, get the devstack config and override the # username and project_name to be admin so that admin credentials # will be used. # # Finally, fall back to looking for environment variables to support # existing users running these the old way. openstack_config = os_client_config.config.OpenStackConfig() self._cloud_config = {} self._cloud_config['admin'] = _get_openstack_auth( openstack_config, 'functional_admin', 'admin') self._cloud_config['user'] = _get_openstack_auth( openstack_config, 'functional_user', 'demo') def get_auth_info(self, name): return self._cloud_config[name].config['auth'] oslotest-3.2.0/oslotest/tools/0000775000175100017510000000000013225157271016435 5ustar zuulzuul00000000000000oslotest-3.2.0/oslotest/tools/__init__.py0000666000175100017510000000000013225157020020526 0ustar zuulzuul00000000000000oslotest-3.2.0/oslotest/tools/config.py0000666000175100017510000000246613225157020020256 0ustar zuulzuul00000000000000# # 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. """Utilities functions for working with oslo.config from the tool scripts. """ import os from oslo_config import cfg DEFAULT_CONFIG_FILES = [ './oslo.conf', os.path.expanduser('~/.oslo.conf'), ] def get_config_parser(): conf = cfg.ConfigOpts() conf.register_cli_opt( cfg.StrOpt( 'repo_root', default='.', help='directory containing the git repositories', ) ) return conf def parse_arguments(conf): # Look for a few configuration files, and load the ones we find. default_config_files = [ f for f in DEFAULT_CONFIG_FILES if os.path.exists(f) ] return conf( project='oslo', default_config_files=default_config_files, ) oslotest-3.2.0/oslotest/tests/0000775000175100017510000000000013225157271016437 5ustar zuulzuul00000000000000oslotest-3.2.0/oslotest/tests/__init__.py0000666000175100017510000000121113225157020020535 0ustar zuulzuul00000000000000# 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 six six.add_move(six.MovedModule('mock', 'mock', 'unittest.mock')) oslotest-3.2.0/oslotest/tests/unit/0000775000175100017510000000000013225157271017416 5ustar zuulzuul00000000000000oslotest-3.2.0/oslotest/tests/unit/test_timeout.py0000666000175100017510000000333113225157020022507 0ustar zuulzuul00000000000000# -*- coding: utf-8 -*- # 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. from six.moves import mock import testtools from oslotest import timeout class TimeoutTestCase(testtools.TestCase): @mock.patch('os.environ.get') @mock.patch.object(timeout.Timeout, 'useFixture') @mock.patch('fixtures.Timeout') def test_timeout(self, fixture_timeout_mock, fixture_mock, env_get_mock): env_get_mock.return_value = 1 tc = timeout.Timeout() tc.setUp() env_get_mock.assert_called_once_with('OS_TEST_TIMEOUT', 0) fixture_timeout_mock.assert_called_once_with(1, gentle=True) self.assertEqual(1, fixture_mock.call_count) @mock.patch('os.environ.get') @mock.patch.object(timeout.Timeout, 'useFixture') @mock.patch('fixtures.Timeout') def test_no_timeout(self, fixture_timeout_mock, fixture_mock, env_get_mock): # Returning 0 means we don't install the timeout env_get_mock.return_value = 0 tc = timeout.Timeout() tc.setUp() env_get_mock.assert_called_once_with('OS_TEST_TIMEOUT', 0) self.assertEqual(0, fixture_timeout_mock.call_count) self.assertEqual(0, fixture_mock.call_count) oslotest-3.2.0/oslotest/tests/unit/test_modules.py0000666000175100017510000000162613225157020022476 0ustar zuulzuul00000000000000# 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. from oslotest import base from oslotest import modules class CreateDisableModuleTest(base.BaseTestCase): def test_disable_module(self): s = __import__('sys') self.assertTrue(s) with modules.DisableModuleFixture('sys'): self.assertRaises(ImportError, __import__, 'sys') s = __import__('sys') self.assertTrue(s) oslotest-3.2.0/oslotest/tests/unit/test_moxstubout.py0000666000175100017510000000217213225157020023254 0ustar zuulzuul00000000000000# Copyright 2014 IBM Corp. # # 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. from oslotest import base from oslotest import moxstubout class TestMoxStubout(base.BaseTestCase): def _stubable(self): pass def test_basic_stubout(self): f = self.useFixture(moxstubout.MoxStubout()) before = TestMoxStubout._stubable f.mox.StubOutWithMock(TestMoxStubout, '_stubable') after = TestMoxStubout._stubable self.assertNotEqual(before, after) f.cleanUp() after2 = TestMoxStubout._stubable self.assertEqual(before, after2) f._clear_cleanups() oslotest-3.2.0/oslotest/tests/unit/test_base.py0000666000175100017510000001604213225157020021736 0ustar zuulzuul00000000000000# -*- coding: utf-8 -*- # Copyright 2014 Deutsche Telekom AG # # 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 logging import os import unittest import fixtures import six from six.moves import mock import testtools from oslotest import base class TestBaseTestCase(testtools.TestCase): class FakeTestCase(base.BaseTestCase): def test_fake_test(self): pass @mock.patch('os.environ.get') @mock.patch('oslotest.timeout.Timeout.useFixture') @mock.patch('fixtures.Timeout') def test_timeout(self, fixture_timeout_mock, fixture_mock, env_get_mock): env_get_mock.return_value = 1 tc = self.FakeTestCase("test_fake_test") tc._set_timeout() env_get_mock.assert_called_once_with('OS_TEST_TIMEOUT', 0) fixture_timeout_mock.assert_called_once_with(1, gentle=True) self.assertEqual(1, fixture_mock.call_count) @mock.patch('os.environ.get') def test_fake_logs_default(self, env_get_mock): # without debug and log capture env_get_mock.side_effect = lambda value, default=None: { 'OS_DEBUG': 0, 'OS_LOG_CAPTURE': 0}.get(value, default) tc = self.FakeTestCase("test_fake_test") tc.setUp() env_get_mock.assert_any_call('OS_LOG_CAPTURE') env_get_mock.assert_any_call('OS_DEBUG') self.assertFalse(tc.log_fixture.capture_logs) self.assertIsNone(tc.log_fixture.logger) @mock.patch('os.environ.get') @mock.patch('logging.basicConfig') def test_fake_logs_with_debug(self, basic_logger_mock, env_get_mock): env_get_mock.side_effect = lambda value, default=None: { 'OS_DEBUG': 'True', 'OS_LOG_CAPTURE': 0}.get(value, default) tc = self.FakeTestCase("test_fake_test") tc.setUp() env_get_mock.assert_any_call('OS_LOG_CAPTURE') env_get_mock.assert_any_call('OS_DEBUG') basic_logger_mock.assert_called_once_with(format=base._LOG_FORMAT, level=logging.DEBUG) @mock.patch('os.environ.get') @mock.patch.object(FakeTestCase, 'useFixture') def test_fake_logs_with_log_cap(self, fixture_mock, env_get_mock): env_get_mock.side_effect = lambda value: {'OS_DEBUG': 0, 'OS_LOG_CAPTURE': 'True' }[value] tc = self.FakeTestCase("test_fake_test") tc.setUp() env_get_mock.assert_any_call('OS_LOG_CAPTURE') env_get_mock.assert_any_call('OS_DEBUG') self.assertEqual(5, fixture_mock.call_count) def test_mock_patch_cleanup_on_teardown(self): # create an object and save its reference class Sub(object): pass obj = Sub() obj.value = obj.backup = object() # patch the object mock.patch.object(obj, 'value').start() self.assertNotEqual(obj.backup, obj.value) # run a test case loader = unittest.defaultTestLoader suite = loader.loadTestsFromTestCase(self.FakeTestCase) suite.run(unittest.TestResult()) # check that mock patches are cleaned up self.assertEqual(obj.backup, obj.value) @mock.patch('os.environ') def test_capture_output_disabled(self, mock_env): mock_env.get.return_value = '' tc = self.FakeTestCase("test_fake_test") tc.setUp() self.assertIsNone(tc.output_fixture.stdout) self.assertIsNone(tc.output_fixture.stderr) @mock.patch('os.environ') def test_enabled(self, mock_env): mock_env.get.return_value = 'True' tc = self.FakeTestCase("test_fake_test") tc.setUp() self.assertIsNotNone(tc.output_fixture.stdout) self.assertIsNotNone(tc.output_fixture.stderr) class TestManualMock(base.BaseTestCase): def setUp(self): # Create a cleanup to undo a patch() call *before* calling the # base class version of setup(). patcher = mock.patch('os.environ.keys') patcher.start() self.addCleanup(patcher.stop) super(TestManualMock, self).setUp() self.useFixture(fixtures.MockPatch('fixtures.Timeout')) self.unstopped = mock.patch('os.environ.put') def tearDown(self): super(TestManualMock, self).tearDown() self.assertRaises( RuntimeError, self.unstopped.stop, ) def test_mock_patch_manually(self): # Verify that if a test instance creates its own mock and # calls start/stop itself we don't get an error. patcher = mock.patch('os.environ.get') patcher.start() self.addCleanup(patcher.stop) class TestTempFiles(base.BaseTestCase): def test_create_unicode_files(self): files = [["no_approve", u'ಠ_ಠ']] temps = self.create_tempfiles(files) self.assertEqual(1, len(temps)) with open(temps[0], 'rb') as f: contents = f.read() self.assertEqual(u'ಠ_ಠ', six.text_type(contents, encoding='utf-8')) def test_create_unicode_files_encoding(self): files = [["embarrassed", u'⊙﹏⊙', 'utf-8']] temps = self.create_tempfiles(files) self.assertEqual(1, len(temps)) with open(temps[0], 'rb') as f: contents = f.read() self.assertEqual(u'⊙﹏⊙', six.text_type(contents, encoding='utf-8')) def test_create_unicode_files_multi_encoding(self): files = [ ["embarrassed", u'⊙﹏⊙', 'utf-8'], ['abc', 'abc', 'ascii'], ] temps = self.create_tempfiles(files) self.assertEqual(2, len(temps)) for i, (basename, raw_contents, raw_encoding) in enumerate(files): with open(temps[i], 'rb') as f: contents = f.read() if not isinstance(raw_contents, six.text_type): raw_contents = six.text_type(raw_contents, encoding=raw_encoding) self.assertEqual(six.text_type(contents, encoding=raw_encoding), raw_contents) def test_create_bad_encoding(self): files = [["hrm", u'ಠ~ಠ', 'ascii']] self.assertRaises(UnicodeError, self.create_tempfiles, files) def test_prefix(self): files = [["testing", '']] temps = self.create_tempfiles(files) self.assertEqual(1, len(temps)) basename = os.path.basename(temps[0]) self.assertTrue(basename.startswith('testing')) def test_wrong_length(self): files = [["testing"]] self.assertRaises(ValueError, self.create_tempfiles, files) oslotest-3.2.0/oslotest/tests/unit/__init__.py0000666000175100017510000000000013225157020021507 0ustar zuulzuul00000000000000oslotest-3.2.0/oslotest/tests/unit/test_mock_fixture.py0000666000175100017510000000750013225157046023532 0ustar zuulzuul00000000000000# Copyright 2017 Cloudbase Solutions Srl # 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 mock import testtools from oslotest import mock_fixture # NOTE(claudiub): this needs to be called before any mock.patch calls are # being done, and especially before the test class loads. This fixes # the mock.patch autospec issue: # https://github.com/testing-cabal/mock/issues/396 # TODO(claudiub): Remove this once the fix has been merged and released. mock_fixture.patch_mock_module() class Foo(object): def bar(self, a, b, c, d=None): pass @classmethod def classic_bar(cls, a, b, c, d=None): pass @staticmethod def static_bar(a, b, c, d=None): pass class MockSanityTestCase(testtools.TestCase): def setUp(self): super(MockSanityTestCase, self).setUp() self.useFixture(mock_fixture.MockAutospecFixture()) def _check_autospeced_foo(self, foo): for method_name in ['bar', 'classic_bar', 'static_bar']: mock_method = getattr(foo, method_name) # check that the methods are callable with correct args. mock_method(mock.sentinel.a, mock.sentinel.b, mock.sentinel.c) mock_method(mock.sentinel.a, mock.sentinel.b, mock.sentinel.c, d=mock.sentinel.d) mock_method.assert_has_calls([ mock.call(mock.sentinel.a, mock.sentinel.b, mock.sentinel.c), mock.call(mock.sentinel.a, mock.sentinel.b, mock.sentinel.c, d=mock.sentinel.d)]) # assert that TypeError is raised if the method signature is not # respected. self.assertRaises(TypeError, mock_method) self.assertRaises(TypeError, mock_method, mock.sentinel.a) self.assertRaises(TypeError, mock_method, a=mock.sentinel.a) self.assertRaises(TypeError, mock_method, mock.sentinel.a, mock.sentinel.b, mock.sentinel.c, e=mock.sentinel.e) # assert that AttributeError is raised if the method does not exist. self.assertRaises(AttributeError, getattr, foo, 'lish') def test_mock_autospec_all_members(self): for spec in [Foo, Foo()]: foo = mock.Mock(autospec=spec) self._check_autospeced_foo(foo) @mock.patch.object(Foo, 'static_bar') @mock.patch.object(Foo, 'classic_bar') @mock.patch.object(Foo, 'bar') def test_patch_autospec_class(self, mock_meth, mock_cmeth, mock_smeth): foo = Foo() self._check_autospeced_foo(foo) @mock.patch.object(Foo, 'static_bar', autospec=False) @mock.patch.object(Foo, 'classic_bar', autospec=False) @mock.patch.object(Foo, 'bar', autospec=False) def test_patch_autospec_class_false(self, mock_meth, mock_cmeth, mock_smeth): foo = Foo() # we're checking that method signature is not enforced. foo.bar() mock_meth.assert_called_once_with() foo.classic_bar() mock_cmeth.assert_called_once_with() foo.static_bar() mock_smeth.assert_called_once_with() @mock.patch.object(Foo, 'lish', create=True) def test_patch_create(self, mock_lish): foo = Foo() foo.lish() mock_lish.assert_called_once_with() oslotest-3.2.0/oslotest/tests/unit/test_createfile.py0000666000175100017510000000377113225157020023134 0ustar zuulzuul00000000000000# -*- coding: utf-8 -*- # Copyright 2014 Deutsche Telekom AG # # 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 six from oslotest import base from oslotest import createfile class CreateFileWithContentTest(base.BaseTestCase): def test_create_unicode_files(self): f = createfile.CreateFileWithContent( "no_approve", u'ಠ_ಠ', ) f.setUp() with open(f.path, 'rb') as f: contents = f.read() self.assertEqual(u'ಠ_ಠ', six.text_type(contents, encoding='utf-8')) def test_create_unicode_files_encoding(self): f = createfile.CreateFileWithContent( "embarrassed", u'⊙﹏⊙', encoding='utf-8', ) f.setUp() with open(f.path, 'rb') as f: contents = f.read() self.assertEqual(u'⊙﹏⊙', six.text_type(contents, encoding='utf-8')) def test_create_bad_encoding(self): f = createfile.CreateFileWithContent( "hrm", u'ಠ~ಠ', encoding='ascii', ) self.assertRaises(UnicodeError, f.setUp) def test_prefix(self): f = createfile.CreateFileWithContent('testing', '') f.setUp() basename = os.path.basename(f.path) self.assertTrue(basename.startswith('testing')) def test_ext(self): f = createfile.CreateFileWithContent('testing', '', ext='.ending') f.setUp() basename = os.path.basename(f.path) self.assertTrue(basename.endswith('.ending')) oslotest-3.2.0/oslotest/tests/unit/test_mockpatch.py0000666000175100017510000000173313225157020022776 0ustar zuulzuul00000000000000# Copyright 2014 IBM Corp. # # 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 fixtures from oslotest import base class TestMockPatchSymbols(base.BaseTestCase): def test_reference(self): # Applications expect these public symbols to be available until the # deprecated module is removed. self.assertTrue(fixtures.MockPatchObject) self.assertTrue(fixtures.MockPatch) self.assertTrue(fixtures.MockPatchMultiple) oslotest-3.2.0/oslotest/tests/unit/test_log.py0000666000175100017510000000777413225157020021621 0ustar zuulzuul00000000000000# -*- coding: utf-8 -*- # Copyright 2014 Deutsche Telekom AG # # 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 logging from six.moves import mock import testtools from oslotest import log class ConfigureLoggingTestCase(testtools.TestCase): @mock.patch('os.environ.get') def test_fake_logs_default(self, env_get_mock): # without debug and log capture env_get_mock.side_effect = lambda value, default=None: { 'OS_DEBUG': 0, 'OS_LOG_CAPTURE': 0}.get(value, default) f = log.ConfigureLogging() f.setUp() env_get_mock.assert_any_call('OS_LOG_CAPTURE') env_get_mock.assert_any_call('OS_DEBUG') self.assertFalse(f.capture_logs) self.assertIsNone(f.logger) @mock.patch('os.environ.get') @mock.patch('logging.basicConfig') def test_fake_logs_with_debug(self, basic_logger_mock, env_get_mock): env_get_mock.side_effect = lambda value, default=None: { 'OS_DEBUG': 'True', 'OS_LOG_CAPTURE': 0}.get(value, default) f = log.ConfigureLogging() f.setUp() env_get_mock.assert_any_call('OS_LOG_CAPTURE') env_get_mock.assert_any_call('OS_DEBUG') basic_logger_mock.assert_called_once_with( format=log.ConfigureLogging.DEFAULT_FORMAT, level=logging.DEBUG) @mock.patch('os.environ.get') @mock.patch('logging.basicConfig') def test_fake_logs_with_warning(self, basic_logger_mock, env_get_mock): env_get_mock.side_effect = lambda value, default=None: { 'OS_DEBUG': 'WARNING', 'OS_LOG_CAPTURE': 0}.get(value, default) f = log.ConfigureLogging() f.setUp() env_get_mock.assert_any_call('OS_LOG_CAPTURE') env_get_mock.assert_any_call('OS_DEBUG') basic_logger_mock.assert_called_once_with( format=log.ConfigureLogging.DEFAULT_FORMAT, level=logging.WARNING) @mock.patch('os.environ.get') @mock.patch('logging.basicConfig') def test_fake_logs_with_trace_int(self, basic_logger_mock, env_get_mock): env_get_mock.side_effect = lambda value, default=None: { 'OS_DEBUG': '5', 'OS_LOG_CAPTURE': 0}.get(value, default) f = log.ConfigureLogging() f.setUp() env_get_mock.assert_any_call('OS_LOG_CAPTURE') env_get_mock.assert_any_call('OS_DEBUG') basic_logger_mock.assert_called_once_with( format=log.ConfigureLogging.DEFAULT_FORMAT, level=5) @mock.patch('os.environ.get') @mock.patch('logging.basicConfig') def test_fake_logs_with_debug_int(self, basic_logger_mock, env_get_mock): env_get_mock.side_effect = lambda value, default=None: { 'OS_DEBUG': '10', 'OS_LOG_CAPTURE': 0}.get(value, default) f = log.ConfigureLogging() f.setUp() env_get_mock.assert_any_call('OS_LOG_CAPTURE') env_get_mock.assert_any_call('OS_DEBUG') basic_logger_mock.assert_called_once_with( format=log.ConfigureLogging.DEFAULT_FORMAT, level=logging.DEBUG) @mock.patch('os.environ.get') def test_fake_logs_with_log_capture(self, env_get_mock): env_get_mock.side_effect = lambda value: {'OS_DEBUG': 0, 'OS_LOG_CAPTURE': 'True' }[value] f = log.ConfigureLogging() f.setUp() env_get_mock.assert_any_call('OS_LOG_CAPTURE') env_get_mock.assert_any_call('OS_DEBUG') self.assertIsNotNone(f.logger) oslotest-3.2.0/oslotest/tests/unit/test_output.py0000666000175100017510000000255513225157020022370 0ustar zuulzuul00000000000000# -*- coding: utf-8 -*- # 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 sys from oslotest import output from six.moves import mock import testtools class CaptureOutputTest(testtools.TestCase): @mock.patch('os.environ') def test_disabled(self, mock_env): mock_env.get.return_value = '' f = output.CaptureOutput() f.setUp() self.assertIsNone(f.stdout) self.assertIsNone(f.stderr) self.assertIsNot(sys.stdout, f.stdout) self.assertIsNot(sys.stderr, f.stderr) @mock.patch('os.environ') def test_enabled(self, mock_env): mock_env.get.return_value = 'True' f = output.CaptureOutput() f.setUp() self.assertIsNotNone(f.stdout) self.assertIsNotNone(f.stderr) self.assertIs(sys.stdout, f.stdout) self.assertIs(sys.stderr, f.stderr) oslotest-3.2.0/oslotest/timeout.py0000666000175100017510000000214113225157020017325 0ustar zuulzuul00000000000000# 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 fixtures import os class Timeout(fixtures.Fixture): """Set the maximum length of time for the test to run. Uses OS_TEST_TIMEOUT to get the timeout. """ def setUp(self): super(Timeout, self).setUp() test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0) try: test_timeout = int(test_timeout) except ValueError: # If timeout value is invalid do not set a timeout. test_timeout = 0 if test_timeout > 0: self.useFixture(fixtures.Timeout(test_timeout, gentle=True)) oslotest-3.2.0/oslotest/mock_fixture.py0000666000175100017510000001545613225157046020363 0ustar zuulzuul00000000000000 # Copyright 2017 Cloudbase Solutions Srl # 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 functools import fixtures import mock def _lazy_autospec_method(mocked_method, original_method, eat_self): if mocked_method._mock_check_sig.__dict__.get('autospeced'): return _lazy_autospec = mock.create_autospec(original_method) if eat_self: # consume self argument. _lazy_autospec = functools.partial(_lazy_autospec, None) def _autospeced(*args, **kwargs): _lazy_autospec(*args, **kwargs) # _mock_check_sig is called by the mock's __call__ method. # which means that if a method is not called, _autospeced is not # called. _autospeced.__dict__['autospeced'] = True mocked_method._mock_check_sig = _autospeced class _AutospecMockMixin(object): """Mock object that lazily autospecs the given spec's methods.""" def __init__(self, *args, **kwargs): super(_AutospecMockMixin, self).__init__(*args, **kwargs) self.__dict__['_autospec'] = kwargs.get('autospec') _mock_methods = self.__dict__['_mock_methods'] if _mock_methods: # this will allow us to be able to set _mock_check_sig if # the spec_set argument has been given. _mock_methods.append('_mock_check_sig') def __getattr__(self, name): attr = super(_AutospecMockMixin, self).__getattr__(name) original_spec = self.__dict__['_autospec'] if not original_spec: return attr if not hasattr(original_spec, name): raise AttributeError(name) # check if the original attribute is callable, and the mock was not # autospeced already. original_attr = getattr(original_spec, name) if callable(original_attr): # lazily autospec callable attribute. eat_self = mock.mock._must_skip(original_spec, name, isinstance(original_spec, type)) _lazy_autospec_method(attr, original_attr, eat_self) return attr class _AutospecMock(_AutospecMockMixin, mock.Mock): pass class _AutospecMagicMock(_AutospecMockMixin, mock.MagicMock): pass class MockAutospecFixture(fixtures.Fixture): """A fixture to add / fix the autospec feature into the mock library. The current version of the mock library has a few unaddressed issues, which can lead to erroneous unit tests, and can hide actual issues. This fixture is to be removed once these issues have been addressed in the mock library. Issue addressed by the fixture: * mocked method's signature checking: - https://github.com/testing-cabal/mock/issues/393 - mock can only accept a spec object / class, and it makes sure that that attribute exists, but it does not check whether the given attribute is callable, or if its signature is respected in any way. - adds autospec argument. If the autospec argument is given, the mocked method's signature is also checked. """ def setUp(self): super(MockAutospecFixture, self).setUp() # patch both external and internal usage of Mock / MagicMock. self.useFixture(fixtures.MonkeyPatch('mock.Mock', _AutospecMock)) self.useFixture(fixtures.MonkeyPatch('mock.mock.Mock', _AutospecMock)) self.useFixture(fixtures.MonkeyPatch('mock.mock.MagicMock', _AutospecMagicMock)) self.useFixture(fixtures.MonkeyPatch('mock.mock.MagicMock', _AutospecMagicMock)) class _patch(mock.mock._patch): """Patch class with working autospec functionality. Currently, mock.patch functionality doesn't handle the autospec parameter properly (the self argument is not consumed, causing assertions to fail). Until the issue is addressed in the mock library, this should be used instead. https://github.com/testing-cabal/mock/issues/396 """ def __init__(self, *args, **kwargs): super(_patch, self).__init__(*args, **kwargs) # By default, autospec is None. We will consider it as True. autospec = True if self.autospec is None else self.autospec # in some cases, autospec cannot be set to True. skip_autospec = (getattr(self, attr) for attr in ['new_callable', 'create', 'spec']) # NOTE(claudiub): The "new" argument is always mock.DEFAULT, unless # explicitly set otherwise. if self.new is not mock.DEFAULT or any(skip_autospec): # cannot autospec if new, new_callable, or create arguments given. autospec = False elif self.attribute: target = getattr(self.getter(), self.attribute, None) if isinstance(target, mock.Mock): # NOTE(claudiub): shouldn't autospec already mocked targets. # this can cause some issues. There are quite a few tests # which patch mocked methods. autospec = False # NOTE(claudiub): reset the self.autospec property, so we can handle # the autospec scenario ourselves. self._autospec = autospec self.autospec = None def __enter__(self): if self._autospec: target = self.getter() original_attr = getattr(target, self.attribute) eat_self = mock.mock._must_skip(target, self.attribute, isinstance(target, type)) new = super(_patch, self).__enter__() _lazy_autospec_method(new, original_attr, eat_self) return new else: return super(_patch, self).__enter__() def _safe_attribute_error_wrapper(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except AttributeError: pass return wrapper def patch_mock_module(): """Replaces the mock.patch class.""" mock.mock._patch = _patch # NOTE(claudiub): mock cannot autospec partial functions properly, # especially those created by LazyLoader objects (scheduler client), # as it will try to copy the partial function's __name__ (which they do # not have). mock.mock._copy_func_details = _safe_attribute_error_wrapper( mock.mock._copy_func_details) oslotest-3.2.0/oslotest/__init__.py0000666000175100017510000000121113225157020017373 0ustar zuulzuul00000000000000# 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 six six.add_move(six.MovedModule('mock', 'mock', 'unittest.mock')) oslotest-3.2.0/oslotest/createfile.py0000666000175100017510000000453113225157020017747 0ustar zuulzuul00000000000000# 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 tempfile import fixtures import six class CreateFileWithContent(fixtures.Fixture): """Create a temporary file with the given content. Creates a file using a predictable name, to be used by tests for code that need a filename to load data or otherwise interact with the real filesystem. .. warning:: It is the responsibility of the caller to ensure that the file is removed. Users of this fixture may also want to use :class:`fixtures.NestedTempfile` to set the temporary directory somewhere safe and to ensure the files are cleaned up. .. py:attribute:: path The canonical name of the file created. :param filename: Base file name or full literal path to the file to be created. :param contents: The data to write to the file. Unicode data will be encoded before being written. :param ext: An extension to add to filename. :param encoding: An encoding to use for unicode data (ignored for byte strings). """ def __init__(self, filename, contents, ext='.conf', encoding='utf-8'): self._filename = filename self._contents = contents self._ext = ext self._encoding = encoding def setUp(self): super(CreateFileWithContent, self).setUp() contents = self._contents if isinstance(contents, six.text_type): contents = contents.encode(self._encoding) if not os.path.isabs(self._filename): (fd, self.path) = tempfile.mkstemp(prefix=self._filename, suffix=self._ext) else: self.path = self._filename + self._ext fd = os.open(self.path, os.O_CREAT | os.O_WRONLY) try: os.write(fd, contents) finally: os.close(fd) oslotest-3.2.0/oslotest/moxstubout.py0000666000175100017510000000232113225157020020070 0ustar zuulzuul00000000000000# Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # Copyright 2013 Hewlett-Packard Development Company, L.P. # 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 fixtures from mox3 import mox class MoxStubout(fixtures.Fixture): """Deal with code around mox and stubout as a fixture.""" def setUp(self): super(MoxStubout, self).setUp() # emulate some of the mox stuff, we can't use the metaclass # because it screws with our generators self.mox = mox.Mox() self.stubs = self.mox.stubs self.addCleanup(self.mox.UnsetStubs) self.addCleanup(self.mox.VerifyAll) oslotest-3.2.0/oslotest/base.py0000666000175100017510000001355213225157020016561 0ustar zuulzuul00000000000000# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # 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. """Common utilities used in testing""" import logging import fixtures from oslotest import createfile from oslotest import log from oslotest import output from oslotest import timeout from six.moves import mock import testtools LOG = logging.getLogger(__name__) _TRUE_VALUES = ('True', 'true', '1', 'yes') _LOG_FORMAT = "%(levelname)8s [%(name)s] %(message)s" class BaseTestCase(testtools.TestCase): """Base class for unit test classes. If the environment variable ``OS_TEST_TIMEOUT`` is set to an integer value, a timer is configured to control how long individual test cases can run. This lets tests fail for taking too long, and prevents deadlocks from completely hanging test runs. If the environment variable ``OS_STDOUT_CAPTURE`` is set, a fake stream replaces ``sys.stdout`` so the test can look at the output it produces. If the environment variable ``OS_STDERR_CAPTURE`` is set, a fake stream replaces ``sys.stderr`` so the test can look at the output it produces. If the environment variable ``OS_DEBUG`` is set to a true value, debug logging is enabled. Alternatively, the ``OS_DEBUG`` environment variable can be set to a valid log level. If the environment variable ``OS_LOG_CAPTURE`` is set to a true value, a logging fixture is installed to capture the log output. Uses the fixtures_ module to configure a :class:`NestedTempFile` to ensure that all temporary files are created in an isolated location. Uses the fixtures_ module to configure a :class:`TempHomeDir` to change the ``HOME`` environment variable to point to a temporary location. PLEASE NOTE: Usage of this class may change the log level globally by setting the environment variable ``OS_DEBUG``. A mock of ``time.time`` will be called many more times than might be expected because it's called often by the logging module. A usage of such a mock should be avoided when a test needs to verify logging behavior or counts the number of invocations. A workaround is to overload the ``_fake_logs`` function in a base class but this will deactivate fake logging globally. .. _fixtures: https://pypi.python.org/pypi/fixtures """ def __init__(self, *args, **kwds): super(BaseTestCase, self).__init__(*args, **kwds) # This is the number of characters shown when two objects do not # match for assertDictEqual, assertMultiLineEqual, and # assertSequenceEqual. The default is 640 which is too # low for comparing most dicts self.maxDiff = 10000 def addCleanup(self, function, *args, **kwargs): # NOTE(dims): This is a hack for Mitaka. We'll need to undo this as # early as possible in Newton and advertise that this hack will not # be supported anymore. if (hasattr(self, '_cleanups') and isinstance(self._cleanups, list)): if not self._cleanups: # Ensure that the mock.patch.stopall cleanup is registered # before any addCleanup() methods have a chance to register # other things to be cleaned up, so it is called last. This # allows tests to register their own cleanups with a mock.stop # method so those mocks are not included in the stopall set. super(BaseTestCase, self).addCleanup(mock.patch.stopall) else: LOG.error('Unable to patch test case. ' 'mock.patch.stopall cleanup was not registered.') super(BaseTestCase, self).addCleanup(function, *args, **kwargs) def setUp(self): super(BaseTestCase, self).setUp() self._set_timeout() self._fake_output() self._fake_logs() self.useFixture(fixtures.NestedTempfile()) self.useFixture(fixtures.TempHomeDir()) def _set_timeout(self): self.useFixture(timeout.Timeout()) def _fake_output(self): self.output_fixture = self.useFixture(output.CaptureOutput()) def _fake_logs(self): self.log_fixture = self.useFixture(log.ConfigureLogging()) def create_tempfiles(self, files, ext='.conf', default_encoding='utf-8'): """Safely create temporary files. :param files: Sequence of tuples containing (filename, file_contents). :type files: list of tuple :param ext: File name extension for the temporary file. :type ext: str :param default_encoding: Default file content encoding when it is not provided, used to decode the tempfile contents from a text string into a binary string. :type default_encoding: str :return: A list of str with the names of the files created. """ tempfiles = [] for f in files: if len(f) == 3: basename, contents, encoding = f else: basename, contents = f encoding = default_encoding fix = self.useFixture(createfile.CreateFileWithContent( filename=basename, contents=contents, ext=ext, encoding=encoding, )) tempfiles.append(fix.path) return tempfiles oslotest-3.2.0/oslotest/log.py0000666000175100017510000000604313225157020016425 0ustar zuulzuul00000000000000# 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 logging import os import fixtures _TRUE_VALUES = ('True', 'true', '1', 'yes') _FALSE_VALUES = ('False', 'false', '0', 'no') _BASE_LOG_LEVELS = ('DEBUG', 'INFO', 'WARN', 'WARNING', 'ERROR', 'CRITICAL') _LOG_LEVELS = dict((n, getattr(logging, n)) for n in _BASE_LOG_LEVELS) _LOG_LEVELS.update({ 'TRACE': 5, }) def _try_int(value): """Try to make some value into an int.""" try: return int(value) except (ValueError, TypeError): return None class ConfigureLogging(fixtures.Fixture): """Configure logging. The behavior is managed through two environment variables. If ``OS_DEBUG`` is true then the logging level is set to debug. If ``OS_LOG_CAPTURE`` is true a FakeLogger is configured. Alternatively, ``OS_DEBUG`` can be set to an explicit log level, such as ``INFO``. "True" values include ``True``, ``true``, ``1`` and ``yes``. Valid log levels include ``DEBUG``, ``INFO``, ``WARNING``, ``ERROR``, ``TRACE`` and ``CRITICAL`` (or any other valid integer logging level). .. py:attribute:: logger The logger fixture, if it is created. .. py:attribute:: level ``logging.DEBUG`` if debug logging is enabled, otherwise the log level specified by ``OS_DEBUG``, otherwise ``None``. :param format: The logging format string to use. """ DEFAULT_FORMAT = "%(levelname)8s [%(name)s] %(message)s" """Default log format""" def __init__(self, format=DEFAULT_FORMAT): super(ConfigureLogging, self).__init__() self._format = format self.level = None _os_debug = os.environ.get('OS_DEBUG') _os_level = _try_int(_os_debug) if _os_debug in _TRUE_VALUES: self.level = logging.DEBUG elif _os_level is not None: self.level = _os_level elif _os_debug in _LOG_LEVELS: self.level = _LOG_LEVELS[_os_debug] elif _os_debug and _os_debug not in _FALSE_VALUES: raise ValueError('OS_DEBUG=%s is invalid.' % (_os_debug)) self.capture_logs = os.environ.get('OS_LOG_CAPTURE') in _TRUE_VALUES self.logger = None def setUp(self): super(ConfigureLogging, self).setUp() if self.capture_logs: self.logger = self.useFixture( fixtures.FakeLogger( format=self._format, level=self.level, nuke_handlers=True, ) ) else: logging.basicConfig(format=self._format, level=self.level) oslotest-3.2.0/oslotest/modules.py0000666000175100017510000000322313225157020017311 0ustar zuulzuul00000000000000# 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 sys import fixtures class DisableModuleFixture(fixtures.Fixture): """A fixture to provide support for unloading/disabling modules.""" def __init__(self, module, *args, **kwargs): super(DisableModuleFixture, self).__init__(*args, **kwargs) self.module = module def setUp(self): """Ensure ImportError for the specified module.""" super(DisableModuleFixture, self).setUp() cleared_modules = {} for name in list(sys.modules.keys()): if name == self.module or name.startswith(self.module + '.'): cleared_modules[name] = sys.modules.pop(name) finder = _NoModuleFinder(self.module) sys.meta_path.insert(0, finder) self.addCleanup(sys.meta_path.remove, finder) self.addCleanup(sys.modules.update, cleared_modules) class _NoModuleFinder(object): """Disallow further imports of 'module'.""" def __init__(self, module): self.module = module def find_module(self, fullname, path): if fullname == self.module or fullname.startswith(self.module + '.'): raise ImportError oslotest-3.2.0/oslotest/output.py0000666000175100017510000000366413225157020017212 0ustar zuulzuul00000000000000# 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 fixtures _TRUE_VALUES = ('True', 'true', '1', 'yes') class CaptureOutput(fixtures.Fixture): """Optionally capture the output streams. The behavior is managed through two environment variables. If ``OS_STDOUT_CAPTURE`` is true then stdout is captured and if ``OS_STDERR_CAPTURE`` is true then stderr is captured. "True" values include ``True``, ``true``, ``1``, and ``yes``. .. py:attribute:: stdout The ``stream`` attribute from a :class:`StringStream` instance replacing stdout. .. py:attribute:: stderr The ``stream`` attribute from a :class:`StringStream` instance replacing stderr. """ def __init__(self): super(CaptureOutput, self).__init__() self.stdout = None self.stderr = None def setUp(self): super(CaptureOutput, self).setUp() if os.environ.get('OS_STDOUT_CAPTURE') in _TRUE_VALUES: self._stdout_fixture = fixtures.StringStream('stdout') self.stdout = self.useFixture(self._stdout_fixture).stream self.useFixture(fixtures.MonkeyPatch('sys.stdout', self.stdout)) if os.environ.get('OS_STDERR_CAPTURE') in _TRUE_VALUES: self._stderr_fixture = fixtures.StringStream('stderr') self.stderr = self.useFixture(self._stderr_fixture).stream self.useFixture(fixtures.MonkeyPatch('sys.stderr', self.stderr)) oslotest-3.2.0/HACKING.rst0000666000175100017510000000022513225157020015210 0ustar zuulzuul00000000000000 Style Commandments =============================================== Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/oslotest-3.2.0/test-requirements.txt0000666000175100017510000000106413225157020017655 0ustar zuulzuul00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 # when we can require tox>= 1.4, this can go into tox.ini: # [testenv:cover] # deps = {[testenv]deps} coverage coverage!=4.4,>=4.0 # Apache-2.0 # this is required for the docs build jobs sphinx>=1.6.2 # BSD openstackdocstheme>=1.17.0 # Apache-2.0 oslo.config>=5.1.0 # Apache-2.0 reno>=2.5.0 # Apache-2.0 oslotest-3.2.0/CONTRIBUTING.rst0000666000175100017510000000103213225157020016050 0ustar zuulzuul00000000000000If you would like to contribute to the development of OpenStack, you must follow the steps in this page: http://docs.openstack.org/infra/manual/developers.html Once those steps have been completed, changes to OpenStack should be submitted for review via the Gerrit tool, following the workflow documented at: http://docs.openstack.org/infra/manual/developers.html#development-workflow Pull requests submitted through GitHub will be ignored. Bugs should be filed on Launchpad, not GitHub: https://bugs.launchpad.net/oslotestoslotest-3.2.0/oslotest.egg-info/0000775000175100017510000000000013225157271016767 5ustar zuulzuul00000000000000oslotest-3.2.0/oslotest.egg-info/requires.txt0000664000175100017510000000021413225157270021363 0ustar zuulzuul00000000000000fixtures>=3.0.0 python-subunit>=1.0.0 six>=1.10.0 testrepository>=0.0.18 testtools>=2.2.0 mock>=2.0.0 mox3>=0.20.0 os-client-config>=1.28.0 oslotest-3.2.0/oslotest.egg-info/SOURCES.txt0000664000175100017510000000364513225157271020663 0ustar zuulzuul00000000000000.coveragerc .mailmap .testr.conf AUTHORS CONTRIBUTING.rst ChangeLog HACKING.rst LICENSE README.rst requirements.txt setup.cfg setup.py test-requirements.txt tox.ini doc/source/conf.py doc/source/index.rst doc/source/contributor/index.rst doc/source/install/index.rst doc/source/reference/index.rst doc/source/user/cross-testing.rst doc/source/user/debugging.rst doc/source/user/features.rst doc/source/user/history.rst doc/source/user/index.rst doc/source/user/mock-autospec.rst doc/source/user/resources.rst doc/source/user/testing.rst oslotest/__init__.py oslotest/base.py oslotest/createfile.py oslotest/functional.py oslotest/log.py oslotest/mock_fixture.py oslotest/modules.py oslotest/moxstubout.py oslotest/output.py oslotest/timeout.py oslotest.egg-info/PKG-INFO oslotest.egg-info/SOURCES.txt oslotest.egg-info/dependency_links.txt oslotest.egg-info/not-zip-safe oslotest.egg-info/pbr.json oslotest.egg-info/requires.txt oslotest.egg-info/top_level.txt oslotest/tests/__init__.py oslotest/tests/unit/__init__.py oslotest/tests/unit/test_base.py oslotest/tests/unit/test_createfile.py oslotest/tests/unit/test_log.py oslotest/tests/unit/test_mock_fixture.py oslotest/tests/unit/test_mockpatch.py oslotest/tests/unit/test_modules.py oslotest/tests/unit/test_moxstubout.py oslotest/tests/unit/test_output.py oslotest/tests/unit/test_timeout.py oslotest/tools/__init__.py oslotest/tools/config.py releasenotes/notes/add-reno-996dd44974d53238.yaml releasenotes/notes/deprecate-functional-module-fbed600d2fa026fc.yaml releasenotes/notes/mock-autospec-fix-9042c30dbb74032f.yaml releasenotes/notes/remove_mockpatch-80fec29f28da5d5c.yaml releasenotes/source/conf.py releasenotes/source/index.rst releasenotes/source/ocata.rst releasenotes/source/pike.rst releasenotes/source/unreleased.rst releasenotes/source/_static/.placeholder releasenotes/source/_templates/.placeholder tools/oslo_debug_helper tools/oslo_run_cross_tests tools/oslo_run_pre_release_testsoslotest-3.2.0/oslotest.egg-info/pbr.json0000664000175100017510000000005613225157270020445 0ustar zuulzuul00000000000000{"git_version": "4f7f49a", "is_release": true}oslotest-3.2.0/oslotest.egg-info/dependency_links.txt0000664000175100017510000000000113225157270023034 0ustar zuulzuul00000000000000 oslotest-3.2.0/oslotest.egg-info/not-zip-safe0000664000175100017510000000000113225157226021215 0ustar zuulzuul00000000000000 oslotest-3.2.0/oslotest.egg-info/PKG-INFO0000664000175100017510000000320313225157270020061 0ustar zuulzuul00000000000000Metadata-Version: 1.1 Name: oslotest Version: 3.2.0 Summary: Oslo test framework Home-page: https://docs.openstack.org/oslotest/latest/ Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description-Content-Type: UNKNOWN Description: ======================== Team and repository tags ======================== .. image:: http://governance.openstack.org/badges/oslotest.svg :target: http://governance.openstack.org/reference/tags/index.html .. Change things from this point on ======================================================= oslotest -- OpenStack Testing Framework and Utilities ======================================================= The Oslo Test framework provides common fixtures, support for debugging, and better support for mocking results. * Free software: Apache license * Documentation: https://docs.openstack.org/oslotest/latest/ * Source: https://git.openstack.org/cgit/openstack/oslotest * Bugs: https://bugs.launchpad.net/oslotest Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Information Technology Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 oslotest-3.2.0/oslotest.egg-info/top_level.txt0000664000175100017510000000001113225157270021510 0ustar zuulzuul00000000000000oslotest oslotest-3.2.0/ChangeLog0000664000175100017510000002200413225157270015170 0ustar zuulzuul00000000000000CHANGES ======= 3.2.0 ----- * Adds mock autospec fixture 3.1.0 ----- * Remove -U from pip install * Avoid tox\_install.sh for constraints support * Updated from global requirements * Remove setting of version/release from releasenotes * Updated from global requirements 3.0.0 ----- 2.18.1 ------ 2.18.0 ------ * Updated from global requirements * Updated from global requirements * Deprecate oslotest.functional * Remove oslotest.mockpatch * Updated from global requirements * Updated from global requirements * Update reno for stable/pike * Updated from global requirements 2.17.0 ------ * Update URLs in documents according to document migration * Use assertIsNone(...) instead of assertIs(None,...) * rearrange content to fit the new standard layout * Using fixtures instead of deprecated mockpatch module 2.16.1 ------ * Switch from oslosphinx to openstackdocstheme 2.16.0 ------ * Updated from global requirements * Trivial fix style in document * Updated from global requirements * Remove pbr warnerrors in favor of sphinx check * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements 2.15.0 ------ * Updated from global requirements * Remove support for py34 2.14.0 ------ * Updated from global requirements * [Fix gate]Update test requirement * Updated from global requirements * Update reno for stable/ocata * Updated from global requirements 2.13.0 ------ * Add Constraints support * Show team and repo badges on README 2.12.0 ------ * Updated from global requirements * Add reno for release notes management * Updated from global requirements * Updated from global requirements * Changed the home-page link 2.11.0 ------ * Remove testscenarios from requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements 2.10.0 ------ * Updated from global requirements 2.9.0 ----- * Updated from global requirements 2.8.0 ----- * Import mock so that it works on Python 3.x * Fix parameters of assertEqual are misplaced * Updated from global requirements * Add Python 3.5 classifier and venv * A DisableModules fixture that removes modules from path 2.7.0 ----- * Updated from global requirements 2.6.0 ----- * Updated from global requirements 2.5.0 ----- * Remove mockpatch re-implementations * Updated from global requirements * Updated from global requirements * Updated from global requirements 2.3.0 ----- * Add some gitignore files 2.2.0 ----- * move unit tests into the oslotest package * Updated from global requirements * Hack to get back stopall cleanup behavior feature * Fix misspelling 2.1.0 ----- * Updated from global requirements * Updated from global requirements * Updated from global requirements * Trival: Remove 'MANIFEST.in' 2.0.0 ----- * Updated from global requirements * Remove Python 2.6 classifier * mockpatch: deprecate in favor of native fixtures * Remove python 2.6 and cleanup tox.ini * Updated from global requirements 1.12.0 ------ * Fix coverage configuration and execution * Updated from global requirements * Add documentation about using oslo\_debug\_helper * add oslo.config a test requirement * clean up readme and doc title * clean up toctree * auto-generate API documentation * Fix the home-page with Oslotest wikipage * Fixup docstrings * Updated from global requirements 1.11.0 ------ * Updated from global requirements 1.10.0 ------ * Allow TRACE and integer logging levels for 'OS\_DEBUG' * Updated from global requirements * Updated from global requirements * Updated from global requirements 1.9.0 ----- * Fix use of mock * Updated from global requirements * Add documentation for cross-project unit testing * Updated from global requirements * Fix build break with Fixtures 1.3 * Updated from global requirements 1.8.0 ----- * Updated from global requirements * Allow \`\`OS\_DEBUG\`\` environment variable to specify log level * Updated from global requirements * always rebuild cross-test venv * Add CreateFileWithContent fixture * Create ConfigureLogging fixture * Create CaptureOutput fixture * Create Timeout wrapper fixture * Document the mock attribute for mockpatch 1.7.0 ----- * Updated from global requirements * Fix argument handling in oslo\_run\_cross\_tests * Add class to deal with clouds.yaml support * Remove unneeded runtime pbr dep * Updated from global requirements * Advertise support for Python3.4 / Remove support for Python 3.3 * Do not sync run\_cross\_tests.sh * Remove unused discover dependency 1.6.0 ----- * Uncap library requirements for liberty * Cleanup README.rst and setup.cfg * mockpatch: factorize code * Update to latest hacking * Updated from global requirements * mockpatch: fix a potential race condition 1.5.1 ----- 1.5.0 ----- * Force rebuild egg-info before running cross tests * Restore missing module for pre-release test script * Updated from global requirements 1.4.0 ----- * Set a higher default for maxDiff * Move the script for running pre-releases into oslotest * Update docs for new script name * Publish cross-test runner as part of oslotest * Remove six.moves call * Fix for mktemp failure on osx * Activate pep8 check that \_ is imported * Workflow documentation is now in infra-manual * Fix the URL for reporting bugs in the README 1.3.0 ----- * Updated from global requirements * Updated from global requirements * Updated from global requirements * Add pbr to installation requirements * Clean up the docs for oslo\_debug\_helper 1.2.0 ----- * Updated from global requirements * Set install\_command in tox to avoid pre-releases * Add an extra parameter for test directory in debugger script * Handle tempfile content encoding * Work toward Python 3.4 support and testing * Add links to best practices video and etherpad * Updated from global requirements * Drop .sh extension from oslo\_debug\_helper.sh * Add history/changelog to docs * fix typo and formatting in contributing docs 1.1.0 ----- * warn against sorting requirements * Add fixture for mock.patch.multiple * Ensure that mock.patch.stopall is called last * Remove differences between Python 2.x and 3.x versions * Require six * Add documentation for running oslo\_debug\_heler.sh * Restructure oslotest docs * Add pdb support to tox with debug helper shell script * Updated from global requirements * Cleaning up index.rst file * Add known issue about time.time mocking * Updated from global requirements * Add API documentation * Moving to use the mock module found in Python3 1.1.0.0a1 --------- * Update to hacking 0.9.2 * Cleanup mock patches on BaseTestCase tearDown() * Add unit test for olsotest base class * fix .gitreview after rename * Sync new sphinx requirement spec * Set log level to default value * Updated from global requirements * Update cross-test directions * Update project name in doc build 1.0.0 ----- * Import run\_cross\_tests.sh from oslo-incubator * Fix up documentation files * Fake logger as instance attribute * Require testrepository and other tools at runtime * Updated from global requirements * Add tool to run cross-project tests 0.1 --- * Rename oslo.test to oslotest * Add test for moxstubout * Switch to oslosphinx * Sync requirements and fix pep8 errors * Remove oslo.test.fixture * Remove unused tempdirs attribute * Remove translations infrastructure * apply oslo-cookiecutter * Differentiate runtime and test requirements * flatten package hierarchy * remove dependency on oslo.config to avoid cycle * Remove lockutils fixture from this library * Run python 3.3 tests first to set testr db type * Add packaging and test control files * rearrange files into the proper package * Generalize base test case into common code * Add 'new' parameter to mock.Patch and mock.PatchObject classes * Make the log capture in tests more configurable * log all test messages not just oslo ones * Fix violations of H302:import only modules * Trivial: Make vertical white space after license header consistent * Remove vim header * Fix copyright header on test module * Use cleaner version from cookiecutter OpenStack template * Add TempHomeDir fixture which is already part of cookiecutter template * Fix typos in oslo * Move LockFixture into a fixtures module * Consolidate the use of stubs * Make openstack.common.fixture.config Py3 compliant * Using NestedTempfile in new BaseTestCase class * Bump hacking to 0.7.0 * Add a fixture for dealing with config * Add common part of test-related tools to oslo * Add eclipse project files to .gitignore * Add .testrepository to .gitignore * Ignore backup files in .gitignore * Add join\_consumer\_pool() to RPC connections * Add a fixture for dealing with mock patching * Start adding reusable test fixtures * updating sphinx documentation * Correcting openstack-common mv to oslo-incubator * Update .gitreview for oslo * .gitignore updates for generated files * Updated tox config for multi-python testing * Added .gitreview file * ignore cover's html directory * Rajaram/Vinkesh|increased tests for Request and Response serializers * Rajaram/Vinkesh|Added nova's serializaiton classes into common * Initial skeleton project oslotest-3.2.0/requirements.txt0000666000175100017510000000067613225157020016710 0ustar zuulzuul00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. fixtures>=3.0.0 # Apache-2.0/BSD python-subunit>=1.0.0 # Apache-2.0/BSD six>=1.10.0 # MIT testrepository>=0.0.18 # Apache-2.0/BSD testtools>=2.2.0 # MIT mock>=2.0.0 # BSD mox3>=0.20.0 # Apache-2.0 os-client-config>=1.28.0 # Apache-2.0 oslotest-3.2.0/LICENSE0000666000175100017510000002363613225157020014432 0ustar zuulzuul00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. oslotest-3.2.0/AUTHORS0000664000175100017510000000433113225157270014471 0ustar zuulzuul00000000000000Alessio Ababilov Alex Meade Alexander Gorodnev Andreas Jaeger Angus Salkeld Ben Nemec Brant Knudson Chang Bo Guo ChangBo Guo(gcb) Christian Berendt Chuck Short Claudiu Belu Danek Duvall Davanum Srinivas Davanum Srinivas Dirk Mueller Doug Hellmann Doug Hellmann Flavio Percoco George Peristerakis Ihar Hrachyshka Ilya Pekelny James Carey Jamie Lennox Jason Kölker Jay Pipes Jeremy Stanley Joe Gordon Joe Heck Jon Grimm Joshua Harlow Julien Danjou Luis A. Garcia Luong Anh Tuan Marc Koderer Mark McLoughlin Masayuki Igawa Mauro S. M. Rodrigues Monty Taylor Noorul Islam K M OpenStack Release Bot Rajaram Mallya Ronald Bradford Sergey Kraynev Soren Hansen Steve Martinelli Thomas Bechtold Tony Breeds Van Hung Pham Victor Stinner Vu Cong Tuan Yuriy Taraday Zhongyue Luo Zuul kavithahr lingyongxu melissaml ricolin venkatamahesh yan.haifeng oslotest-3.2.0/PKG-INFO0000664000175100017510000000320313225157271014514 0ustar zuulzuul00000000000000Metadata-Version: 1.1 Name: oslotest Version: 3.2.0 Summary: Oslo test framework Home-page: https://docs.openstack.org/oslotest/latest/ Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description-Content-Type: UNKNOWN Description: ======================== Team and repository tags ======================== .. image:: http://governance.openstack.org/badges/oslotest.svg :target: http://governance.openstack.org/reference/tags/index.html .. Change things from this point on ======================================================= oslotest -- OpenStack Testing Framework and Utilities ======================================================= The Oslo Test framework provides common fixtures, support for debugging, and better support for mocking results. * Free software: Apache license * Documentation: https://docs.openstack.org/oslotest/latest/ * Source: https://git.openstack.org/cgit/openstack/oslotest * Bugs: https://bugs.launchpad.net/oslotest Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Information Technology Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 oslotest-3.2.0/tox.ini0000666000175100017510000000153013225157020014725 0ustar zuulzuul00000000000000[tox] minversion = 2.0 distribute = False envlist = py35,py27,pep8 [testenv] install_command = pip install {opts} {packages} deps = -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} -r{toxinidir}/test-requirements.txt -r{toxinidir}/requirements.txt commands = python setup.py testr --slowest --testr-args='{posargs}' [testenv:pep8] commands = flake8 [testenv:cover] commands = python setup.py test --coverage --testr-args='{posargs}' [testenv:venv] commands = {posargs} [testenv:docs] commands = python setup.py build_sphinx [flake8] show-source = True exclude = .tox,dist,doc,*.egg,build [hacking] import_exceptions = six.moves.mock [testenv:releasenotes] commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html oslotest-3.2.0/.mailmap0000666000175100017510000000013013225157020015026 0ustar zuulzuul00000000000000# Format is: # # oslotest-3.2.0/releasenotes/0000775000175100017510000000000013225157271016112 5ustar zuulzuul00000000000000oslotest-3.2.0/releasenotes/source/0000775000175100017510000000000013225157271017412 5ustar zuulzuul00000000000000oslotest-3.2.0/releasenotes/source/conf.py0000666000175100017510000002144713225157020020713 0ustar zuulzuul00000000000000# -*- coding: utf-8 -*- # 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. # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'openstackdocstheme', 'reno.sphinxext', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'oslotest Release Notes' copyright = u'2016, oslotest Developers' # Release notes do not need a version in the title, they span # multiple versions. # The full version, including alpha/beta/rc tags. release = '' # The short X.Y version. version = '' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all # documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. # keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'openstackdocs' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' html_last_updated_fmt = '%Y-%m-%d %H:%M' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'oslotestReleaseNotesDoc' # openstackdocstheme options repository_name = 'openstack/oslotest' bug_project = 'oslotest' bug_tag = '' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # 'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ('index', 'oslotestReleaseNotes.tex', u'oslotest Release Notes Documentation', u'oslotest Developers', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. # latex_show_pagerefs = False # If true, show URL addresses after external links. # latex_show_urls = False # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'oslotestReleaseNotes', u'oslotest Release Notes Documentation', [u'oslotest Developers'], 1) ] # If true, show URL addresses after external links. # man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'oslotestReleaseNotes', u'oslotest Release Notes Documentation', u'oslotest Developers', 'oslotestReleaseNotes', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. # texinfo_appendices = [] # If false, no module index is generated. # texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. # texinfo_no_detailmenu = False # -- Options for Internationalization output ------------------------------ locale_dirs = ['locale/'] oslotest-3.2.0/releasenotes/source/_static/0000775000175100017510000000000013225157271021040 5ustar zuulzuul00000000000000oslotest-3.2.0/releasenotes/source/_static/.placeholder0000666000175100017510000000000013225157020023303 0ustar zuulzuul00000000000000oslotest-3.2.0/releasenotes/source/unreleased.rst0000666000175100017510000000016013225157020022262 0ustar zuulzuul00000000000000============================== Current Series Release Notes ============================== .. release-notes:: oslotest-3.2.0/releasenotes/source/index.rst0000666000175100017510000000021513225157020021243 0ustar zuulzuul00000000000000======================== oslotest Release Notes ======================== .. toctree:: :maxdepth: 1 unreleased pike ocata oslotest-3.2.0/releasenotes/source/ocata.rst0000666000175100017510000000023013225157020021220 0ustar zuulzuul00000000000000=================================== Ocata Series Release Notes =================================== .. release-notes:: :branch: origin/stable/ocata oslotest-3.2.0/releasenotes/source/_templates/0000775000175100017510000000000013225157271021547 5ustar zuulzuul00000000000000oslotest-3.2.0/releasenotes/source/_templates/.placeholder0000666000175100017510000000000013225157020024012 0ustar zuulzuul00000000000000oslotest-3.2.0/releasenotes/source/pike.rst0000666000175100017510000000021713225157020021066 0ustar zuulzuul00000000000000=================================== Pike Series Release Notes =================================== .. release-notes:: :branch: stable/pike oslotest-3.2.0/releasenotes/notes/0000775000175100017510000000000013225157271017242 5ustar zuulzuul00000000000000oslotest-3.2.0/releasenotes/notes/remove_mockpatch-80fec29f28da5d5c.yaml0000666000175100017510000000021713225157020026032 0ustar zuulzuul00000000000000--- upgrade: - | As announced in Nov 2015, the oslotest.mockpatch module got removed now. Please use fixtures.Mock* classes instead. oslotest-3.2.0/releasenotes/notes/add-reno-996dd44974d53238.yaml0000666000175100017510000000007213225157020023632 0ustar zuulzuul00000000000000--- other: - Introduce reno for deployer release notes. oslotest-3.2.0/releasenotes/notes/deprecate-functional-module-fbed600d2fa026fc.yaml0000666000175100017510000000015013225157020030115 0ustar zuulzuul00000000000000--- deprecations: - | oslotest.functional is deprecated and will be removed with oslotest 3.0.0 . oslotest-3.2.0/releasenotes/notes/mock-autospec-fix-9042c30dbb74032f.yaml0000666000175100017510000000021613225157046025605 0ustar zuulzuul00000000000000--- other: - | Oslotest now contains the mock_fixture module, which offers fixes to the autospec functionality in the mock library. oslotest-3.2.0/.coveragerc0000666000175100017510000000015313225157020015533 0ustar zuulzuul00000000000000[run] branch = True source = oslotest omit = oslotest/tests/* [report] ignore_errors = True precision = 2 oslotest-3.2.0/.testr.conf0000666000175100017510000000047613225157020015510 0ustar zuulzuul00000000000000[DEFAULT] test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \ ${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION test_id_option=--load-list $IDFILE test_list_option=--listoslotest-3.2.0/README.rst0000666000175100017510000000132713225157020015105 0ustar zuulzuul00000000000000======================== Team and repository tags ======================== .. image:: http://governance.openstack.org/badges/oslotest.svg :target: http://governance.openstack.org/reference/tags/index.html .. Change things from this point on ======================================================= oslotest -- OpenStack Testing Framework and Utilities ======================================================= The Oslo Test framework provides common fixtures, support for debugging, and better support for mocking results. * Free software: Apache license * Documentation: https://docs.openstack.org/oslotest/latest/ * Source: https://git.openstack.org/cgit/openstack/oslotest * Bugs: https://bugs.launchpad.net/oslotest oslotest-3.2.0/doc/0000775000175100017510000000000013225157271014166 5ustar zuulzuul00000000000000oslotest-3.2.0/doc/source/0000775000175100017510000000000013225157271015466 5ustar zuulzuul00000000000000oslotest-3.2.0/doc/source/user/0000775000175100017510000000000013225157271016444 5ustar zuulzuul00000000000000oslotest-3.2.0/doc/source/user/debugging.rst0000666000175100017510000000106713225157020021127 0ustar zuulzuul00000000000000=============== Debugging Tests =============== Running tests through testrepository_ makes it difficult to use pdb for debugging them. oslotest includes ``oslo_debug_helper`` to make using pdb simpler/possible. First, add a pdb call to the test code:: import pdb; pdb.set_trace() Then run the tests through ``oslo_debug_helper`` like :: $ oslo_debug_helper [tests to run] or :: $ tox -e venv -- oslo_debug_helper [tests to run] .. seealso:: * https://wiki.openstack.org/wiki/Testr .. _testrepository: https://pypi.python.org/pypi/testrepository oslotest-3.2.0/doc/source/user/history.rst0000666000175100017510000000004013225157020020663 0ustar zuulzuul00000000000000.. include:: ../../../ChangeLog oslotest-3.2.0/doc/source/user/resources.rst0000666000175100017510000000052513225157020021204 0ustar zuulzuul00000000000000====================== Other Useful Resources ====================== * Mock_ library documentation * OpenStack Bootstrapping Hour: Mock Best Practices: `video `__ and `etherpad `__ .. _Mock: http://www.voidspace.org.uk/python/mock/ oslotest-3.2.0/doc/source/user/cross-testing.rst0000666000175100017510000001011513225157020021772 0ustar zuulzuul00000000000000========================== Cross-project Unit Testing ========================== Libraries in OpenStack have an unusual ability to introduce breaking changes. All of the projects are run together from source in one form or another during the integration tests, but they are not combined from source when unit tests are run. The server applications do not generally import code from other projects, so their unit tests are isolated. The libraries, however, are fundamentally intended to be used during unit tests as well as integration tests. Testing the full cross-product of libraries and consuming projects would consume all available test servers, and so we cannot run all of the tests on all patches to the libraries. As an alternative, we have a few scripts in ``oslotest`` for running the unit tests in serial. The result takes far too long (usually overnight) to run in the OpenStack infrastructure. Instead, they are usually run by hand on a dedicated system. A cloud VM works well for this purpose, especially considering how much of it is now automated. Check Out OpenStack Source ========================== The first step for all of the cross-project unit tests tools is to ensure that you have a full copy of the OpenStack source checked out. You can do this yourself through gerrit's ssh API, or you can use the ``clone_openstack.sh`` command in the tools directory of the ``openstack/oslo-incubator`` repository. For example:: $ mkdir -p ~/repos/openstack $ cd ~/repos/openstack $ git clone git://git.openstack.org/openstack/oslo-incubator $ cd ~/repos $ ./openstack/oslo-incubator/tools/clone_openstack.sh The first time the script runs it will take quite some time, since it has to download the entire history of every OpenStack project. Testing One Project =================== ``oslo_run_cross_tests`` runs one set of unit tests for one library against all of the consuming projects. It should be run from the directory with the library to be tested, and passed arguments telling it about another project whose tests should be run. For example, to run the ``py27`` test suite from nova using the currently checked out sources for ``oslo.config``, run:: $ cd ~/repos/openstack/oslo.config $ tox -e venv -- oslo_run_cross_tests ~/repos/openstack/nova py27 Testing All Consumers ===================== ``oslo_run_pre_release_tests`` builds on ``oslo_run_cross_tests`` to find all of the consuming projects and run their tests automatically. The pre-release script needs to know where the source has been checked out, so the first step is to create its configuration file. Edit ``~/.oslo.conf`` to contain:: [DEFAULT] repo_root = /path/to/repos Replace ``/path/to/repos`` with the full, expanded, absolute path to the location where the source code was checked out. For example, if you followed the instructions above using ``clone_openstack.sh`` in ``~/repos`` and your user name is ``theuser`` the path would be ``/home/theuser/repos``. Returning to the earlier example, to test ``oslo.config`` with all of the projects that use it, go to the ``oslo.config`` source directory and run ``oslo_run_pre_release_tests``. :: $ cd ~/repos/openstack/oslo.config $ tox -e venv -- oslo_run_pre_release_tests The output for each test set is logged to a separate file in the current directory, to make them easy to examine. Use the ``--update`` or ``-u`` option to force a ``git pull`` for each consuming projects before running its tests (useful for maintaining a long-running system to host these tests). Use the ``--verbose`` or ``-v`` option to report more verbosely about what is happening, including the number of projects being tested. Use ``--env`` or ``-e`` to add a tox environment to test. By default the ``py27`` and ``pep8`` environments are used because those have been shown to provide a good balance between finding problems and running the tests quickly. Use the ``--ref`` option to test a specific commit reference of the library under test. The default is to leave the source directory untouched, but if this option is specified ``git checkout`` is used to force the source tree to the specified reference. oslotest-3.2.0/doc/source/user/testing.rst0000666000175100017510000000121413225157020020643 0ustar zuulzuul00000000000000======= Testing ======= Cross-testing With Other Projects ================================= The oslotest package can be cross-tested against its consuming projects to ensure that no changes to the library break the tests in those other projects. In the Gate ----------- Refer to the instructions in https://wiki.openstack.org/wiki/Oslo/UsingALibrary for setting up cross-test jobs in the gate. Locally ------- To run the cross-tests locally, invoke the script directly, passing the path to the other source repository and the tox environment name to use: :: $ cd oslo.test $ ./tools/oslo_run_cross_tests ~/repos/openstack/oslo.config py27 oslotest-3.2.0/doc/source/user/index.rst0000666000175100017510000000025113225157046020305 0ustar zuulzuul00000000000000============== Using oslotest ============== .. toctree:: :maxdepth: 2 features debugging testing mock-autospec cross-testing resources historyoslotest-3.2.0/doc/source/user/mock-autospec.rst0000666000175100017510000000616713225157046021764 0ustar zuulzuul00000000000000============= Mock autospec ============= In typical unit tests, almost all of the dependencies are mocked or patched (``mock.patch``), without any guarantee that the mocked methods actually exist, or if their signatures are respected. Because of this, actual issues can be easily overlooked and missed, as the unit tests are wrongfully passing. The ``mock.Mock`` class accepts a spec as an argument, which only solves half the problem: it only checks if an attribute exists, based on the given spec. It does not guarantee that the given attribute is actually a method, or if its signature is respected. The Mock class does not accept an autospec argument [1]. ``mock.patch``, ``mock.patch.object``, ``mock.patch.multiple`` accept an autospec argument, but because of a bug [2], it cannot be used properly. oslotest offers a solution for problems mentioned above. 1. https://github.com/testing-cabal/mock/issues/393 2. https://github.com/testing-cabal/mock/issues/396 Patching the ``mock`` module ============================ The ``oslotest.mock_fixture`` module contains 2 components: - patch_mock_module - MockAutospecFixture Both components need to be used in order to fix various issues within ``mock`` regarding autospec. patch_mock_module ----------------- At the moment, ``mock.patch``, ``mock.patch.object``, ``mock.patch.multiple`` accepts the ``autospec`` argument, but it does not correctly consume the self / cls argument of methods or class methods. ``patch_mock_module`` addresses this issue. In order to make sure that the original version of ``mock.patch`` is not used by the unit tests, this function has to be called as early as possible within the test module, or the base test module. E.g.:: nova/test.py ... from oslotest import mock_fixture mock_fixture.patch_mock_module() Additionally, this function will set the ``autospec`` argument's value to ``True``, unless otherwise specified or these arguments are passed in: ``new_callable, create, spec``. MockAutospecFixture ------------------- ``mock.Mock`` and ``mock.MagicMock`` classes do not accept any ``autospec`` argument. This fixture will replace the ``mock.Mock`` and ``mock.MagicMock`` classes with subclasses which accepts the said argument. The fixture can be used in the test ``setUp`` method. E.g.:: nova/test.py ... from oslotest import mock_fixture class TestCase(testtools.TestCase): def setUp(self): super(TestCase, self).setUp() self.useFixture(mock_fixture.MockAutospecFixture()) Mock autospec usage =================== Consider the following class as an example:: class Foo(object): def bar(self, a, b, c, d=None): pass Using the setup described above, the following unit tests will now pass correctly:: class FooTestCase(TestCase): def test_mock_bar(self): mock_foo = mock.Mock(autospec=Foo) self.assertRaises(TypeError, mock_foo.bar, invalid='argument') @mock.patch.object(Foo, 'bar', autospec=True) def test_patch_bar(self, mock_bar): foo = Foo() self.assertRaises(TypeError, foo.bar, invalid='argument') oslotest-3.2.0/doc/source/user/features.rst0000666000175100017510000000340013225157020021003 0ustar zuulzuul00000000000000======== Features ======== Debugging with oslo_debug_helper ================================ The oslotest package also distributes a shell file that may be used to assist in debugging python code. The shell file uses testtools, and supports debugging with `pdb `_. Adding breakpoints to the code ------------------------------ The typical usage to break into the debugger from a running program is to insert: .. code-block:: python import pdb; pdb.set_trace() Update tox.ini -------------- Within the ``tox.ini`` file of your project add the following:: [testenv:debug] commands = oslo_debug_helper {posargs} If the project name, and the module that precedes the tests directory do not match, then consider passing a `-t` argument to `oslo_debug_helper` to indicate the directory where tests are located. For example, the ``python-keystoneclient`` project has tests in ``keystoneclient/tests``, thus it would have to pass in:: [testenv:debug] commands = oslo_debug_helper -t keystoneclient/tests {posargs} Similarly, most ``oslo`` projects have the tests at the package level, it would have to pass in:: [testenv:debug] commands = oslo_debug_helper -t tests {posargs} Debugging with tox ------------------ To enable debugging, run tox with the ``debug`` environment: .. code-block:: bash $ tox -e debug $ tox -e debug test_notifications $ tox -e debug test_notifications.NotificationsTestCase $ tox -e debug test_notifications.NotificationsTestCase.test_send_notification Which results in an interactive prompt: .. code-block:: bash > /opt/stack/ceilometer/ceilometer/tests/identity/test_notifications.py(106)notification_for_role_change() -> action_name = '%s.%s' % (action, ROLE_ASSIGNMENT) (Pdb) oslotest-3.2.0/doc/source/conf.py0000777000175100017510000000537213225157020016771 0ustar zuulzuul00000000000000# -*- coding: utf-8 -*- # 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 sys sys.path.insert(0, os.path.abspath('../..')) # -- General configuration ---------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'sphinx.ext.autodoc', #'sphinx.ext.intersphinx', 'openstackdocstheme', ] # autodoc generation is a bit aggressive and a nuisance when doing heavy # text edit cycles. # execute "export SPHINX_DEBUG=1" in your terminal to disable modindex_common_prefix = ['oslotest.'] # The suffix of source filenames. source_suffix = '.rst' # The master toctree document. master_doc = 'index' # General information about the project. project = u'oslotest' copyright = u'2014, OpenStack Foundation' # If true, '()' will be appended to :func: etc. cross-reference text. add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). add_module_names = True # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # -- Options for HTML output -------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. # html_theme_path = ["."] # html_static_path = ['static'] html_theme = 'openstackdocs' # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' html_last_updated_fmt = '%Y-%m-%d %H:%M' # Output file base name for HTML help builder. htmlhelp_basename = '%sdoc' % project # openstackdocstheme options repository_name = 'openstack/oslotest' bug_project = 'oslotest' bug_tag = '' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass # [howto/manual]). latex_documents = [ ('index', '%s.tex' % project, u'%s Documentation' % project, u'OpenStack Foundation', 'manual'), ] # Example configuration for intersphinx: refer to the Python standard library. #intersphinx_mapping = {'http://docs.python.org/': None} oslotest-3.2.0/doc/source/install/0000775000175100017510000000000013225157271017134 5ustar zuulzuul00000000000000oslotest-3.2.0/doc/source/install/index.rst0000666000175100017510000000013213225157020020763 0ustar zuulzuul00000000000000============ Installation ============ At the command line:: $ pip install oslotest oslotest-3.2.0/doc/source/index.rst0000666000175100017510000000054413225157020017324 0ustar zuulzuul00000000000000===================================================== oslotest -- OpenStack Testing Framework and Utilities ===================================================== .. toctree:: :maxdepth: 2 install/index contributor/index user/index reference/index Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` oslotest-3.2.0/doc/source/reference/0000775000175100017510000000000013225157271017424 5ustar zuulzuul00000000000000oslotest-3.2.0/doc/source/reference/index.rst0000666000175100017510000000010313225157020021251 0ustar zuulzuul00000000000000.. _using: API === .. toctree:: :maxdepth: 1 api/autoindexoslotest-3.2.0/doc/source/contributor/0000775000175100017510000000000013225157271020040 5ustar zuulzuul00000000000000oslotest-3.2.0/doc/source/contributor/index.rst0000666000175100017510000000011713225157020021672 0ustar zuulzuul00000000000000============ Contributing ============ .. include:: ../../../CONTRIBUTING.rst oslotest-3.2.0/setup.cfg0000666000175100017510000000203013225157271015237 0ustar zuulzuul00000000000000[metadata] name = oslotest summary = Oslo test framework description-file = README.rst author = OpenStack author-email = openstack-dev@lists.openstack.org home-page = https://docs.openstack.org/oslotest/latest/ classifier = Environment :: OpenStack Intended Audience :: Developers Intended Audience :: Information Technology License :: OSI Approved :: Apache Software License Operating System :: POSIX :: Linux Programming Language :: Python Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.5 [files] packages = oslotest scripts = tools/oslo_debug_helper tools/oslo_run_cross_tests tools/oslo_run_pre_release_tests [build_sphinx] source-dir = doc/source build-dir = doc/build all_files = 1 warning-is-error = 1 [upload_sphinx] upload-dir = doc/build/html [pbr] autodoc_index_modules = true api_doc_dir = reference/api autodoc_exclude_modules = oslotest.tests.* [wheel] universal = true [egg_info] tag_build = tag_date = 0 oslotest-3.2.0/setup.py0000666000175100017510000000200613225157020015123 0ustar zuulzuul00000000000000# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # 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. # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools # In python < 2.7.4, a lazy loading of package `pbr` will break # setuptools if some other modules registered functions in `atexit`. # solution from: http://bugs.python.org/issue15881#msg170215 try: import multiprocessing # noqa except ImportError: pass setuptools.setup( setup_requires=['pbr>=2.0.0'], pbr=True)