Index: third_party/google-endpoints/endpoints/test/test_util.py |
diff --git a/third_party/google-endpoints/endpoints/test/test_util.py b/third_party/google-endpoints/endpoints/test/test_util.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..131b224dd7ee9ea2f904ce8e3e411bc15dac9cc2 |
--- /dev/null |
+++ b/third_party/google-endpoints/endpoints/test/test_util.py |
@@ -0,0 +1,195 @@ |
+# Copyright 2016 Google Inc. All Rights Reserved. |
+# |
+# Licensed under the Apache License, Version 2.0 (the "License"); |
+# you may not use this file except in compliance with the License. |
+# You may obtain a copy of the License at |
+# |
+# http://www.apache.org/licenses/LICENSE-2.0 |
+# |
+# Unless required by applicable law or agreed to in writing, software |
+# distributed under the License is distributed on an "AS IS" BASIS, |
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+# See the License for the specific language governing permissions and |
+# limitations under the License. |
+ |
+"""Test utilities for API modules. |
+ |
+Classes: |
+ ModuleInterfaceTest: Test framework for developing public modules. |
+""" |
+ |
+# pylint: disable=g-bad-name |
+ |
+import __future__ |
+import json |
+import os |
+import types |
+ |
+ |
+def AssertDictEqual(expected, actual, testcase): |
+ """Utility method to dump diffs if the dictionaries aren't equal. |
+ |
+ Args: |
+ expected: dict, the expected results. |
+ actual: dict, the actual results. |
+ testcase: unittest.TestCase, the test case this assertion is used within. |
+ """ |
+ if expected != actual: |
+ testcase.assertMultiLineEqual( |
+ json.dumps(expected, indent=2, sort_keys=True), |
+ json.dumps(actual, indent=2, sort_keys=True)) |
+ |
+ |
+class ModuleInterfaceTest(object): |
+ r"""Test to ensure module interface is carefully constructed. |
+ |
+ A module interface is the set of public objects listed in the module __all__ |
+ attribute. Modules that will be used by the public should have this interface |
+ carefully declared. At all times, the __all__ attribute should have objects |
+ intended to be used by the public and other objects in the module should be |
+ considered unused. |
+ |
+ Protected attributes (those beginning with '_') and other imported modules |
+ should not be part of this set of variables. An exception is for variables |
+ that begin and end with '__' which are implicitly part of the interface |
+ (eg. __name__, __file__, __all__ itself, etc.). |
+ |
+ Modules that are imported in to the tested modules are an exception and may |
+ be left out of the __all__ definition. The test is done by checking the value |
+ of what would otherwise be a public name and not allowing it to be exported |
+ if it is an instance of a module. Modules that are explicitly exported are |
+ for the time being not permitted. |
+ |
+ To use this test class a module should define a new class that inherits first |
+ from ModuleInterfaceTest and then from unittest.TestCase. No other tests |
+ should be added to this test case, making the order of inheritance less |
+ important, but if setUp for some reason is overidden, it is important that |
+ ModuleInterfaceTest is first in the list so that its setUp method is |
+ invoked. |
+ |
+ Multiple inheretance is required so that ModuleInterfaceTest is not itself |
+ a test, and is not itself executed as one. |
+ |
+ The test class is expected to have the following class attributes defined: |
+ |
+ MODULE: A reference to the module that is being validated for interface |
+ correctness. |
+ |
+ Example: |
+ Module definition (hello.py): |
+ |
+ import sys |
+ |
+ __all__ = ['hello'] |
+ |
+ def _get_outputter(): |
+ return sys.stdout |
+ |
+ def hello(): |
+ _get_outputter().write('Hello\n') |
+ |
+ Test definition: |
+ |
+ import test_util |
+ import unittest |
+ |
+ import hello |
+ |
+ class ModuleInterfaceTest(module_testutil.ModuleInterfaceTest, |
+ unittest.TestCase): |
+ |
+ MODULE = hello |
+ |
+ |
+ class HelloTest(unittest.TestCase): |
+ ... Test 'hello' module ... |
+ |
+ |
+ def main(unused_argv): |
+ unittest.main() |
+ |
+ |
+ if __name__ == '__main__': |
+ app.run() |
+ """ |
+ |
+ def setUp(self): |
+ """Set up makes sure that MODULE and IMPORTED_MODULES is defined. |
+ |
+ This is a basic configuration test for the test itself so does not |
+ get it's own test case. |
+ """ |
+ if not hasattr(self, 'MODULE'): |
+ self.fail( |
+ "You must define 'MODULE' on ModuleInterfaceTest sub-class %s." % |
+ type(self).__name__) |
+ |
+ def testAllExist(self): |
+ """Test that all attributes defined in __all__ exist.""" |
+ missing_attributes = [] |
+ for attribute in self.MODULE.__all__: |
+ if not hasattr(self.MODULE, attribute): |
+ missing_attributes.append(attribute) |
+ if missing_attributes: |
+ self.fail('%s of __all__ are not defined in module.' % |
+ missing_attributes) |
+ |
+ def testAllExported(self): |
+ """Test that all public attributes not imported are in __all__.""" |
+ missing_attributes = [] |
+ for attribute in dir(self.MODULE): |
+ if not attribute.startswith('_'): |
+ if attribute not in self.MODULE.__all__: |
+ attribute_value = getattr(self.MODULE, attribute) |
+ if isinstance(attribute_value, types.ModuleType): |
+ continue |
+ # pylint: disable=protected-access |
+ if isinstance(attribute_value, __future__._Feature): |
+ continue |
+ missing_attributes.append(attribute) |
+ if missing_attributes: |
+ self.fail('%s are not modules and not defined in __all__.' % |
+ missing_attributes) |
+ |
+ def testNoExportedProtectedVariables(self): |
+ """Test that there are no protected variables listed in __all__.""" |
+ protected_variables = [] |
+ for attribute in self.MODULE.__all__: |
+ if attribute.startswith('_'): |
+ protected_variables.append(attribute) |
+ if protected_variables: |
+ self.fail('%s are protected variables and may not be exported.' % |
+ protected_variables) |
+ |
+ def testNoExportedModules(self): |
+ """Test that no modules exist in __all__.""" |
+ exported_modules = [] |
+ for attribute in self.MODULE.__all__: |
+ try: |
+ value = getattr(self.MODULE, attribute) |
+ except AttributeError: |
+ # This is a different error case tested for in testAllExist. |
+ pass |
+ else: |
+ if isinstance(value, types.ModuleType): |
+ exported_modules.append(attribute) |
+ if exported_modules: |
+ self.fail('%s are modules and may not be exported.' % exported_modules) |
+ |
+ |
+class DevServerTest(object): |
+ |
+ @staticmethod |
+ def setUpDevServerEnv(server_software_key='SERVER_SOFTWARE', |
+ server_software_value='Development/2.0.0'): |
+ original_env_value = os.environ.get(server_software_key) |
+ os.environ[server_software_key] = server_software_value |
+ return server_software_key, original_env_value |
+ |
+ @staticmethod |
+ def restoreEnv(server_software_key, server_software_value): |
+ if server_software_value is None: |
+ os.environ.pop(server_software_key, None) |
+ else: |
+ os.environ[server_software_key] = server_software_value |
+ |