From cc57067355db081f66de04664f1f88a76cd0f16d Mon Sep 17 00:00:00 2001 From: Doug Hellmann Date: Thu, 11 Jun 2015 20:08:29 +0000 Subject: [PATCH] Add CreateFileWithContent fixture Add a fixture for creating real files on the filesystem with contents, to replace the implementation inside the test base class. Blueprint oslotest-refactor-test-base-class Change-Id: Ibca716d1054da973583e5bb4694ef1d64750d50a --- doc/source/api.rst | 7 ++++ oslotest/base.py | 24 ++++-------- oslotest/createfile.py | 70 +++++++++++++++++++++++++++++++++++ tests/unit/test_createfile.py | 62 +++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 16 deletions(-) create mode 100644 oslotest/createfile.py create mode 100644 tests/unit/test_createfile.py diff --git a/doc/source/api.rst b/doc/source/api.rst index bf6ac0c..fbd3965 100644 --- a/doc/source/api.rst +++ b/doc/source/api.rst @@ -10,6 +10,13 @@ oslotest.base .. autoclass:: oslotest.base.BaseTestCase :members: +oslotest.createfile +=================== + +.. automodule:: oslotest.createfile + :members: + :special-members: + oslotest.log ============ diff --git a/oslotest/base.py b/oslotest/base.py index aa162f8..b77f846 100644 --- a/oslotest/base.py +++ b/oslotest/base.py @@ -15,15 +15,12 @@ """Common utilities used in testing""" -import os -import tempfile - import fixtures +from oslotest import createfile from oslotest import log from oslotest import output from oslotest import timeout -import six from six.moves import mock import testtools @@ -128,16 +125,11 @@ class BaseTestCase(testtools.TestCase): else: basename, contents = f encoding = default_encoding - if isinstance(contents, six.text_type): - contents = contents.encode(encoding) - if not os.path.isabs(basename): - (fd, path) = tempfile.mkstemp(prefix=basename, suffix=ext) - else: - path = basename + ext - fd = os.open(path, os.O_CREAT | os.O_WRONLY) - tempfiles.append(path) - try: - os.write(fd, contents) - finally: - os.close(fd) + fix = self.useFixture(createfile.CreateFileWithContent( + filename=basename, + contents=contents, + ext=ext, + encoding=encoding, + )) + tempfiles.append(fix.path) return tempfiles diff --git a/oslotest/createfile.py b/oslotest/createfile.py new file mode 100644 index 0000000..86fa8b2 --- /dev/null +++ b/oslotest/createfile.py @@ -0,0 +1,70 @@ +# 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) diff --git a/tests/unit/test_createfile.py b/tests/unit/test_createfile.py new file mode 100644 index 0000000..bed5a99 --- /dev/null +++ b/tests/unit/test_createfile.py @@ -0,0 +1,62 @@ +# -*- 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'))