.. _testing: Testing ======= Overview -------- When it comes to testing, DSG follows the same conventions as `Django `_ and `DRF `_. It use the `unittest `_ library, a built-in Python module for testing. This allows for the creation of robust and comprehensive unit tests, ensuring the reliability and stability of the codebase. To enable unit test of your gRPC services, DSG provides a **mock gRPC server** that allows you to test your services as if they were being handled by a real gRPC server, **replacing the networking calls by function calls**. The following sections will guide you through the process of writing and running tests for DSG. Writing Tests ------------- Let's imagine a dummy service for a model Post .. code-block:: python # quickstrart/services.py from django_filters.rest_framework import DjangoFilterBackend from django_socio_grpc.generics import AsyncModelService from quickstart.models import Post from quickstart.serializer import PostProtoSerializer # AsyncModelService implements basic crud functionnalities class PostService(AsyncModelService): queryset = Post.objects.all() serializer_class = PostProtoSerializer filter_backends = [DjangoFilterBackend] filterset_fields = ["headline"] The following is a basic structure for your testing class: .. code-block:: python # quickstart/tests.py from django.test import TestCase from .post.services.post_service import PostService from .post.grpc import post_pb2 from .post.grpc.post_pb2_grpc import ( PostControllerStub, add_PostControllerServicer_to_server, ) from .grpc_test_utils.fake_grpc import FakeFullAIOGRPC class TestPost(TestCase): def setup(self): self.fake_grpc = FakeFullAIOGRPC( add_PostControllerServicer_to_server, PostService.as_servicer(), ) Now, let's dissect the ``TestPost`` class: - We recommend using ``TestCase`` from ``django.test`` for testing your service. - The ``setup`` method should instantiate a ``FakeFullAIOGRPC``. - ``FakeFullAIOGRPC`` is initialized with two parameters: - ``add_PostControllerServicer_to_server``: This function is **automatically generated by gRPC**. It's responsible for **adding a servicer to a gRPC server**. In this case, it's used to add the ``PostService`` servicer to the server. - ``Servicer``: This is the actual **service that handles the RPCs**. In this context, ``PostService`` is the servicer. It contains the logic for handling the client's requests. - For a deeper understanding of services and the process of initiating a real server, consult the `gRPC Python Basics documentation `_. - When you create an instance of ``FakeFullAIOGRPC``, it sets up a **mock gRPC server with your servicer**. This allows you to make calls to your servicer methods **as if they were being handled by a real gRPC server**. .. warning:: The ``fake_grpc.py`` file provides two classes: ``FakeAIOGRPC`` and ``FakeFullAIOGRPC``, both of which inherit from the ``fakeRPC`` base class. However, it's important to note that both ``FakeGRPC`` and ``FakeAIOGRPC`` are now deprecated. For asynchronous contexts, we strongly recommend using ``FakeFullAIOGRC``, as it is specifically designed and optimized for such use cases. Testing common functionnalities: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Here are some important test files in the DSG project: - `Actions `_: Contains tests for the action functionality. - `Basic async service `_: Test the basic asynchronous service. - `Async exception `_: Contains tests for handling exceptions in asynchronous services. - `Basic mixin `_: Test the basic mixins used in the project. - `Filtering `_: Contains tests for the filtering functionality. - `Pagination `_: Test the pagination functionality. - `Permissions `_: Contains tests for the permissions functionality. - `Placeholders `_: Test the placeholder functionality. - `Auth `_: Contains tests for the authentication functionality. - `Auth without session middleware `_: Test the authentication functionality without using session middleware. - `Async stream `_: Test the asynchronous streaming functionality. - `Local middleware `_: Test the locale middleware. - `Legacy django middleware `_: Test the legacy Django middleware. - `Proto generation `_: Test the protobuf generation functionality. - `Protobuf registration `_: Test the registration of protobufs. - `App handler registration `_: Test the registration of app handlers. Running Tests ------------- To run tests on your application, it is advised to install ``pytest`` and ``pytest-django``. The installation instructions can be found in the `pytest-django tutorial `_. Verify your installation by checking the ``pytest`` version: .. code-block:: bash pytest --version Create a test file named ``quickstart/tests.py``. Follow the instructions provided earlier in this document for guidance on how to structure your first test. Run your tests with the following command: .. code-block:: bash pytest For more details on ``pytest`` and ``unittest``, refer to the `pytest documentation `_ and `unittest documentation `_ respectively.