Testing¶
Monkay provides several utilities to facilitate testing, especially when dealing with temporary overwrites, lazy imports, and checking imports and exports.
Temporary Overwrites¶
For testing purposes, Monkay provides three context manager methods that allow you to temporarily overwrite settings, extensions, or instances in a thread-safe manner. These methods help you control the environment during tests without affecting the global state.
Available Context Managers:¶
with_settings(settings)
: Temporarily overwrites the settings for the scope of the context.with_extensions(extensions_dict, *, apply_extensions=False)
: Temporarily overwrites the extensions for the scope. Theapply_extensions
flag controls whether extensions are applied during the overwrite.with_instance(instance, *, apply_extensions=False, use_extensions_overwrite=True)
: Temporarily overwrites the instance for the scope. You can also apply extensions and control the overwrite behavior using the respective flags.
These context managers provide a flexible way to test different configurations of settings, extensions, and instances without permanently modifying them.
Example:¶
from monkay import Monkay
monkay = Monkay(globals())
# Overwrite settings temporarily
with monkay.with_settings({"setting_name": "new_value"}):
assert monkay.settings.setting_name == "new_value"
# Overwrite extensions temporarily
with monkay.with_extensions({"extension_name": "new_extension"}, apply_extensions=True):
assert "extension_name" in monkay.extensions
# Overwrite instance temporarily
with monkay.with_instance(new_instance, apply_extensions=False):
assert monkay.instance is new_instance
These context managers are especially useful for writing isolated and repeatable tests, where you may want to modify the environment without affecting the global state.
Check Imports and Exports¶
Monkay provides a debugging method called find_missing()
to help you verify that all imports and exports are correctly defined and available. This method can be particularly useful for testing and debugging, but it is expensive and should only be used in error cases or for debugging purposes.
find_missing
Method¶
The find_missing()
method checks if all exports are correctly defined in the __all__
variable of a module and whether all required imports are available.
Parameters:¶
all_var
: If provided, the method checks that all keys are in the given__all__
variable. If set toTrue
, it checks the__all__
variable of the module.search_pathes
: A list of module paths to search for imports. The method will check if each import path is available and correctly imported.ignore_deprecated_import_errors
: If set toTrue
, it suppresses errors for deprecated imports that fail.require_search_path_all_var
: IfTrue
(default), it ensures that the search path modules have an__all__
variable. IfFalse
, missing__all__
errors for search paths are ignored.
The method returns a dictionary with the following structure:
- Key: Import name or import path
- Value: Set of errors related to the import
Possible Errors:¶
not_in_all_var
: The import is not listed in the provided__all__
variable.missing_attr
: The attribute defined in__all__
does not exist or raises anAttributeError
.missing_all_var
: The search path or main module does not have an__all__
variable. This error can be suppressed by settingrequire_search_path_all_var=False
.import
: The import of the module or function raised anImportError
.shadowed
: The key is defined as a lazy import but is also defined in the main module, meaning the lazy import is not used.search_path_extra
: The search path is not included in the lazy imports.search_path_import
: The import of the search path failed.
Example:¶
Using Monkay for tests is straightforward and convenient, as shown in the example below:
import edgy
def test_edgy_lazy_imports():
# Check for missing imports in the specified modules
missing = edgy.monkay.find_missing(
all_var=edgy.__all__,
search_pathes=["edgy.core.files", "edgy.core.db.fields", "edgy.core.connection"]
)
# Remove false positives if any
if missing.get("AutoNowMixin") == {"AutoNowMixin"}:
del missing["AutoNowMixin"]
# Assert that no imports are missing
assert not missing
In this example:
- The find_missing()
method is used to check for any missing imports in the edgy
module and its submodules.
- If there are any false positives (e.g., an import was marked as missing but is actually valid), they are removed from the result.
- The test asserts that there are no missing imports.
This ensures that no lazy imports are broken and that all expected imports are available.
Ignore Import Errors for Deprecated Lazy Imports¶
When you have deprecated lazy imports, you can suppress import errors for these deprecated attributes by setting ignore_deprecated_import_errors=True
. This is particularly useful when migrating from an old import path to a new one, while still allowing the application to run without breaking.
Example:¶
missing = edgy.monkay.find_missing(
all_var=edgy.__all__,
search_pathes=["edgy.core.files", "edgy.core.db.fields", "edgy.core.connection"],
ignore_deprecated_import_errors=True
)
This will suppress errors for deprecated imports, allowing the system to continue functioning even if some of the lazy imports have been deprecated or removed.
Summary of Key Features for Testing¶
- Temporary Overwrites: Use context managers (
with_settings
,with_extensions
,with_instance
) to temporarily modify settings, extensions, or instances in a thread-safe manner during tests. - Check Imports and Exports: Use
find_missing()
to verify that all imports and exports are correctly defined and available, helping to identify issues with missing attributes or failed imports. - Ignore Deprecated Import Errors: Optionally suppress errors for deprecated lazy imports to allow smoother transitions between old and new import paths.
These testing utilities provide an effective way to validate your application's environment and ensure that all components are correctly loaded and available during testing. Let me know if you need further refinements or if you'd like to move on to another section!