Using APIViewTestCases and ViewTestCases in plugins #6943

Open
opened 2025-12-29 19:47:03 +01:00 by adam · 1 comment
Owner

Originally created by @miaow2 on GitHub (Sep 7, 2022).

NetBox version

v3.3.0

Feature type

Change to existing functionality

Proposed functionality

Hi, NetBox team!
I am writing a plugin for NetBox and want to use APIViewTestCases and ViewTestCases in tests. But they don't work because test cases don't know that plugins namespaces are extended by plugins: and plugins-api:. GraphQLTestCase does not work because function dynamic_import (from utilities/utils.py) can't import plugins graphql types.

I've made several changes and test cases started working in plugins. NetBox core tests also working. Check changes below.

In API and views test cases checks if app_label is in settings.PLUGINS

utilities/testing/api.py

class APITestCase(ModelTestCase):

    def _get_view_namespace(self):
-        return f'{self.view_namespace or self.model._meta.app_label}-api'
+        app_label = self.view_namespace or self.model._meta.app_label
+       if app_label in settings.PLUGINS:
+            app_label = f'plugins-api:{app_label}'
+        return f'{app_label}-api'

utilities/testing/api.py

+from django.conf import settings

class ModelViewTestCase(ModelTestCase):

    def _get_base_url(self):
-        return '{}:{}_{{}}'.format(
-            self.model._meta.app_label,
-            self.model._meta.model_name
-        )
+        app_label = self.model._meta.app_label
+        if app_label in settings.PLUGINS:
+            app_label = f'plugins:{app_label}'
+        return f'{app_label}:{self.model._meta.model_name}_{{}}'

In GraphQLTestCase I'm using import_object (from extras/plugins/utils.py) instead of dynamic_import for plugins.
utilities/testing/api.py

+from extras.plugins.utils import import_object

def get_graphql_type_for_model(model):
    """
    Return the GraphQL type class for the given model.
    """
    app_name, model_name = model._meta.label.split('.')
    # Object types for Django's auth models are in the users app
    if app_name == 'auth':
        app_name = 'users'
-    class_name = f'{app_name}.graphql.types.{model_name}Type'
-    try:
-        return dynamic_import(class_name)
-    except AttributeError:
-        raise GraphQLTypeNotFound(f"Could not find GraphQL type for {app_name}.{model_name}")
+    if app_name in settings.PLUGINS:
+        class_name = f'{app_name}.graphql.{model_name}Type'
+        graphql_type = import_object(class_name)
+        if graphql_type is None:
+            raise GraphQLTypeNotFound(f"Could not find GraphQL type for {app_name}.{model_name}")
+    else:
+        class_name = f'{app_name}.graphql.types.{model_name}Type'
+        try:
+            graphql_type = dynamic_import(class_name)
+        except AttributeError:
+            raise GraphQLTypeNotFound(f"Could not find GraphQL type for {app_name}.{model_name}")

+    return graphql_type

Use case

It would be great to use NetBox abstractions in plugin testing, it really simplifies the work.
I can create a pull request if this solution is right for you. If not, feel free to close this issue. Early I've opened discussion.

Database changes

There are no database changes.

External dependencies

There are no external dependencies.

Originally created by @miaow2 on GitHub (Sep 7, 2022). ### NetBox version v3.3.0 ### Feature type Change to existing functionality ### Proposed functionality Hi, NetBox team! I am writing a plugin for NetBox and want to use **APIViewTestCases** and **ViewTestCases** in tests. But they don't work because test cases don't know that plugins namespaces are extended by `plugins:` and `plugins-api:`. **GraphQLTestCase** does not work because function **dynamic_import** (from `utilities/utils.py`) can't import plugins graphql types. I've made several changes and test cases started working in plugins. NetBox core tests also working. Check changes below. In API and views test cases checks if `app_label` is in `settings.PLUGINS` [utilities/testing/api.py](https://github.com/netbox-community/netbox/blob/develop/netbox/utilities/testing/api.py#L50) ```diff class APITestCase(ModelTestCase): def _get_view_namespace(self): - return f'{self.view_namespace or self.model._meta.app_label}-api' + app_label = self.view_namespace or self.model._meta.app_label + if app_label in settings.PLUGINS: + app_label = f'plugins-api:{app_label}' + return f'{app_label}-api' ``` [utilities/testing/api.py](https://github.com/netbox-community/netbox/blob/develop/netbox/utilities/testing/views.py#L26) ```diff +from django.conf import settings class ModelViewTestCase(ModelTestCase): def _get_base_url(self): - return '{}:{}_{{}}'.format( - self.model._meta.app_label, - self.model._meta.model_name - ) + app_label = self.model._meta.app_label + if app_label in settings.PLUGINS: + app_label = f'plugins:{app_label}' + return f'{app_label}:{self.model._meta.model_name}_{{}}' ``` In **GraphQLTestCase** I'm using `import_object` (from `extras/plugins/utils.py`) instead of `dynamic_import` for plugins. [utilities/testing/api.py](https://github.com/netbox-community/netbox/blob/develop/netbox/utilities/api.py#L31) ```diff +from extras.plugins.utils import import_object def get_graphql_type_for_model(model): """ Return the GraphQL type class for the given model. """ app_name, model_name = model._meta.label.split('.') # Object types for Django's auth models are in the users app if app_name == 'auth': app_name = 'users' - class_name = f'{app_name}.graphql.types.{model_name}Type' - try: - return dynamic_import(class_name) - except AttributeError: - raise GraphQLTypeNotFound(f"Could not find GraphQL type for {app_name}.{model_name}") + if app_name in settings.PLUGINS: + class_name = f'{app_name}.graphql.{model_name}Type' + graphql_type = import_object(class_name) + if graphql_type is None: + raise GraphQLTypeNotFound(f"Could not find GraphQL type for {app_name}.{model_name}") + else: + class_name = f'{app_name}.graphql.types.{model_name}Type' + try: + graphql_type = dynamic_import(class_name) + except AttributeError: + raise GraphQLTypeNotFound(f"Could not find GraphQL type for {app_name}.{model_name}") + return graphql_type ``` ### Use case It would be great to use NetBox abstractions in plugin testing, it really simplifies the work. I can create a pull request if this solution is right for you. If not, feel free to close this issue. Early I've opened [discussion](https://github.com/netbox-community/netbox/discussions/10128). ### Database changes There are no database changes. ### External dependencies There are no external dependencies.
Author
Owner

@peteeckel commented on GitHub (Nov 14, 2023):

As it's been a while - I wholeheartedly support this issue.

I've been (semi-legally :-)) using inherited versions of the classes in question since the beginning and found lots of errors that way - actually a long time ago I raised this a while ago, but lost track of it.

@peteeckel commented on GitHub (Nov 14, 2023): As it's been a while - I wholeheartedly support this issue. I've been (semi-legally :-)) using inherited versions of the classes in question since the beginning and found lots of errors that way - actually a long time ago I raised this a while ago, but lost track of it.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#6943