CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-graphene-django

Django integration for Graphene enabling GraphQL APIs in Django applications

Pending
Overview
Eval results
Files

testing.mddocs/

Testing Utilities

Test case classes and utility functions for GraphQL testing in Django applications with assertion helpers, query execution, and comprehensive testing patterns. Provides tools for unit testing GraphQL schemas, resolvers, and mutations.

Capabilities

GraphQLTestCase

Test case base class for GraphQL testing with built-in GraphQL execution and assertion helpers.

class GraphQLTestCase(django.test.TestCase):
    """
    Test case base class for GraphQL testing.
    
    Provides utility methods for executing GraphQL queries and mutations
    in Django test environment with assertion helpers and error handling.
    """
    
    GRAPHQL_SCHEMA = None           # GraphQL schema for testing
    GRAPHQL_URL = '/graphql/'       # GraphQL endpoint URL
    
    def query(self, query, op_name=None, input_data=None, variables=None, headers=None):
        """
        Execute GraphQL query in test environment.
        
        Parameters:
        - query: GraphQL query string
        - op_name: Operation name for named queries
        - input_data: Input data for mutations (deprecated, use variables)
        - variables: Query variables
        - headers: HTTP headers
        
        Returns:
        dict: GraphQL response data
        """
    
    def assertResponseNoErrors(self, resp, msg=None):
        """
        Assert GraphQL response has no errors.
        
        Parameters:
        - resp: GraphQL response
        - msg: Custom assertion message
        
        Raises:
        AssertionError: If response contains errors
        """
    
    def assertResponseHasErrors(self, resp, msg=None):
        """
        Assert GraphQL response has errors.
        
        Parameters:
        - resp: GraphQL response  
        - msg: Custom assertion message
        
        Raises:
        AssertionError: If response contains no errors
        """
    
    def setUp(self):
        """Set up test case with schema configuration."""
    
    def _client_query(self, query, op_name=None, input_data=None, variables=None, headers=None):
        """
        Internal method for client query execution.
        
        Parameters:
        - query: GraphQL query string
        - op_name: Operation name
        - input_data: Input data
        - variables: Query variables
        - headers: HTTP headers
        
        Returns:
        django.http.HttpResponse: HTTP response
        """

Utility Functions

Helper functions for GraphQL query execution and testing patterns outside of test case classes.

def graphql_query(query, variables=None, headers=None, client=None, graphql_url='/graphql/'):
    """
    Utility function for making GraphQL requests in tests.
    
    Parameters:
    - query: GraphQL query string
    - variables: Query variables dict
    - headers: HTTP headers dict
    - client: Django test client instance
    - graphql_url: GraphQL endpoint URL
    
    Returns:
    django.http.HttpResponse: HTTP response with GraphQL result
    """

def format_graphql_query(query, variables=None, operation_name=None):
    """
    Format GraphQL query with variables and operation name.
    
    Parameters:
    - query: GraphQL query string
    - variables: Query variables
    - operation_name: GraphQL operation name
    
    Returns:
    dict: Formatted query data for HTTP request
    """

def extract_graphql_errors(response):
    """
    Extract GraphQL errors from response.
    
    Parameters:
    - response: HTTP response with GraphQL data
    
    Returns:
    list: List of GraphQL error objects
    """

Usage Examples

Basic Query Testing

from graphene_django.utils.testing import GraphQLTestCase
from myapp.schema import schema

class UserQueryTest(GraphQLTestCase):
    GRAPHQL_SCHEMA = schema
    
    def setUp(self):
        self.user = User.objects.create(
            username='testuser',
            email='test@example.com'
        )
    
    def test_users_query(self):
        query = '''
            query {
                users {
                    id
                    username
                    email
                }
            }
        '''
        
        response = self.query(query)
        self.assertResponseNoErrors(response)
        
        users = response['data']['users']
        self.assertEqual(len(users), 1)
        self.assertEqual(users[0]['username'], 'testuser')
    
    def test_user_by_id_query(self):
        query = '''
            query GetUser($id: ID!) {
                user(id: $id) {
                    username
                    email
                }
            }
        '''
        
        variables = {'id': str(self.user.id)}
        response = self.query(query, variables=variables)
        self.assertResponseNoErrors(response)
        
        user_data = response['data']['user']
        self.assertEqual(user_data['username'], 'testuser')
        self.assertEqual(user_data['email'], 'test@example.com')

Mutation Testing

class UserMutationTest(GraphQLTestCase):
    GRAPHQL_SCHEMA = schema
    
    def test_create_user_mutation(self):
        mutation = '''
            mutation CreateUser($input: CreateUserInput!) {
                createUser(input: $input) {
                    user {
                        id
                        username
                        email
                    }
                    errors {
                        field
                        messages
                    }
                }
            }
        '''
        
        variables = {
            'input': {
                'username': 'newuser',
                'email': 'new@example.com',
                'password': 'securepassword123'
            }
        }
        
        response = self.query(mutation, variables=variables)
        self.assertResponseNoErrors(response)
        
        result = response['data']['createUser']
        self.assertEqual(len(result['errors']), 0)
        self.assertEqual(result['user']['username'], 'newuser')
        
        # Verify user was created in database
        user = User.objects.get(username='newuser')
        self.assertEqual(user.email, 'new@example.com')
    
    def test_create_user_validation_error(self):
        # Create existing user
        User.objects.create(username='existing', email='existing@example.com')
        
        mutation = '''
            mutation CreateUser($input: CreateUserInput!) {
                createUser(input: $input) {
                    user {
                        id
                    }
                    errors {
                        field
                        messages
                    }
                }
            }
        '''
        
        variables = {
            'input': {
                'username': 'existing',  # This should cause validation error
                'email': 'new@example.com'
            }
        }
        
        response = self.query(mutation, variables=variables)
        self.assertResponseNoErrors(response)  # No GraphQL errors
        
        result = response['data']['createUser']
        self.assertIsNone(result['user'])
        self.assertGreater(len(result['errors']), 0)
        self.assertEqual(result['errors'][0]['field'], 'username')

Authentication Testing

from django.contrib.auth import get_user_model
from django.test import override_settings

User = get_user_model()

class AuthenticatedGraphQLTest(GraphQLTestCase):
    GRAPHQL_SCHEMA = schema
    
    def setUp(self):
        self.user = User.objects.create_user(
            username='testuser',
            email='test@example.com',
            password='testpass123'
        )
    
    def test_authenticated_query(self):
        # Login user
        self.client.force_login(self.user)
        
        query = '''
            query {
                me {
                    id
                    username
                    email
                }
            }
        '''
        
        response = self.query(query)
        self.assertResponseNoErrors(response)
        
        me_data = response['data']['me']
        self.assertEqual(me_data['username'], 'testuser')
    
    def test_unauthenticated_query_error(self):
        query = '''
            query {
                me {
                    id
                    username
                }
            }
        '''
        
        response = self.query(query)
        self.assertResponseHasErrors(response)
        
        errors = response['errors']
        self.assertIn('authentication', errors[0]['message'].lower())
    
    def test_permission_required_mutation(self):
        # Create staff user
        staff_user = User.objects.create_user(
            username='staff',
            email='staff@example.com',
            password='staffpass',
            is_staff=True
        )
        
        mutation = '''
            mutation DeleteUser($id: ID!) {
                deleteUser(id: $id) {
                    success
                    errors {
                        field
                        messages
                    }
                }
            }
        '''
        
        # Test without permission
        self.client.force_login(self.user)
        response = self.query(mutation, variables={'id': str(self.user.id)})
        self.assertResponseHasErrors(response)
        
        # Test with permission
        self.client.force_login(staff_user)
        response = self.query(mutation, variables={'id': str(self.user.id)})
        self.assertResponseNoErrors(response)

Connection/Pagination Testing

class PaginationTest(GraphQLTestCase):
    GRAPHQL_SCHEMA = schema
    
    def setUp(self):
        # Create multiple users for pagination testing
        for i in range(10):
            User.objects.create(
                username=f'user{i}',
                email=f'user{i}@example.com'
            )
    
    def test_connection_pagination(self):
        query = '''
            query GetUsers($first: Int, $after: String) {
                users(first: $first, after: $after) {
                    edges {
                        node {
                            id
                            username
                        }
                        cursor
                    }
                    pageInfo {
                        hasNextPage
                        hasPreviousPage
                        startCursor
                        endCursor
                    }
                }
            }
        '''
        
        # First page
        response = self.query(query, variables={'first': 3})
        self.assertResponseNoErrors(response)
        
        connection = response['data']['users']
        self.assertEqual(len(connection['edges']), 3)
        self.assertTrue(connection['pageInfo']['hasNextPage'])
        self.assertFalse(connection['pageInfo']['hasPreviousPage'])
        
        # Second page
        end_cursor = connection['pageInfo']['endCursor']
        response = self.query(query, variables={'first': 3, 'after': end_cursor})
        self.assertResponseNoErrors(response)
        
        connection = response['data']['users']
        self.assertEqual(len(connection['edges']), 3)
        self.assertTrue(connection['pageInfo']['hasPreviousPage'])

Filtering Testing

class FilteringTest(GraphQLTestCase):
    GRAPHQL_SCHEMA = schema
    
    def setUp(self):
        self.active_user = User.objects.create(
            username='active',
            email='active@example.com',
            is_active=True
        )
        self.inactive_user = User.objects.create(
            username='inactive', 
            email='inactive@example.com',
            is_active=False
        )
    
    def test_filter_by_active_status(self):
        query = '''
            query GetUsers($isActive: Boolean) {
                users(isActive: $isActive) {
                    edges {
                        node {
                            username
                            isActive
                        }
                    }
                }
            }
        '''
        
        # Test active users
        response = self.query(query, variables={'isActive': True})
        self.assertResponseNoErrors(response)
        
        users = response['data']['users']['edges']
        self.assertEqual(len(users), 1)
        self.assertEqual(users[0]['node']['username'], 'active')
        
        # Test inactive users
        response = self.query(query, variables={'isActive': False})
        self.assertResponseNoErrors(response)
        
        users = response['data']['users']['edges']
        self.assertEqual(len(users), 1)
        self.assertEqual(users[0]['node']['username'], 'inactive')

Error Handling Testing

class ErrorHandlingTest(GraphQLTestCase):
    GRAPHQL_SCHEMA = schema
    
    def test_invalid_query_syntax(self):
        invalid_query = '''
            query {
                users {
                    id
                    nonexistentField
                }
            }
        '''
        
        response = self.query(invalid_query)
        self.assertResponseHasErrors(response)
        
        errors = response.get('errors', [])
        self.assertGreater(len(errors), 0)
    
    def test_resolver_exception(self):
        query = '''
            query {
                userThatThrowsError {
                    id
                }
            }
        '''
        
        response = self.query(query)
        self.assertResponseHasErrors(response)
        
        errors = response.get('errors', [])
        self.assertIn('error', errors[0]['message'].lower())
    
    def test_custom_error_formatting(self):
        # Override error formatting for sensitive information
        with override_settings(DEBUG=False):
            query = '''
                query {
                    sensitiveOperation {
                        data
                    }
                }
            '''
            
            response = self.query(query)
            self.assertResponseHasErrors(response)
            
            # In production, errors should be generic
            errors = response.get('errors', [])
            self.assertNotIn('database', errors[0]['message'].lower())

Custom Headers and Context Testing

class CustomContextTest(GraphQLTestCase):
    GRAPHQL_SCHEMA = schema
    
    def test_custom_headers(self):
        query = '''
            query {
                requestInfo {
                    headers
                    userAgent
                }
            }
        '''
        
        headers = {
            'HTTP_USER_AGENT': 'Test Client 1.0',
            'HTTP_X_CUSTOM_HEADER': 'custom-value'
        }
        
        response = self.query(query, headers=headers)
        self.assertResponseNoErrors(response)
        
        request_info = response['data']['requestInfo']
        self.assertEqual(request_info['userAgent'], 'Test Client 1.0')
    
    def test_graphql_context(self):
        self.client.force_login(self.user)
        
        query = '''
            query {
                contextInfo {
                    userId
                    isAuthenticated
                }
            }
        '''
        
        response = self.query(query)
        self.assertResponseNoErrors(response)
        
        context_info = response['data']['contextInfo']
        self.assertTrue(context_info['isAuthenticated'])
        self.assertEqual(int(context_info['userId']), self.user.id)

Install with Tessl CLI

npx tessl i tessl/pypi-graphene-django

docs

core-types.md

debug.md

fields.md

filtering.md

forms.md

index.md

rest-framework.md

testing.md

views.md

tile.json