Skip to content

Intro

pytest is a popular testing framework for Python that provides a robust and flexible approach to testing. It is known for its simplicity, powerful features, and ease of use.

pytest-django is a plugin for pytest that integrates Django with the pytest testing framework. It extends pytest to handle Django-specific testing tasks.


Question

Can we use pytest instead of django unittest framework

Yes, you can definitely use pytest with Django instead of Django's default unit test framework. In fact, many developers prefer pytest due to its powerful features and flexibility. Here’s a step-by-step guide to help you get started:

  1. Install pytest and pytest-django:

    First, you need to install pytest and the pytest-django plugin, which provides Django-specific functionalities.

    pip install pytest pytest-django
    
  2. Configure pytest-django:

    Create a file named pytest.ini in your project root (the same directory as manage.py). This file will configure pytest to work with Django.

    [pytest]
    DJANGO_SETTINGS_MODULE = myproject.settings
    

    Replace myproject.settings with the path to your Django settings module.

  3. Create a conftest.py file (optional):

    You can use this file to define fixtures and hooks that pytest can use. For example, you might configure database settings or set up common test data.

    # conftest.py
    import pytest
    from django.urls import reverse
    
    @pytest.fixture
    def sample_url():
        return reverse('sample_view')
    
  4. Write your tests:

    You can start writing tests using pytest syntax. Here’s an example of a simple Django test using pytest:

    # test_models.py
    import pytest
    from django.urls import reverse
    from django.test import Client
    
    @pytest.mark.django_db
    def test_sample_view(sample_url):
        client = Client()
        response = client.get(sample_url)
        assert response.status_code == 200
    

    The @pytest.mark.django_db decorator is used to mark tests that require database access.

  5. Run your tests:

    You can run your tests using the pytest command in your terminal:

    pytest
    
  6. Use additional pytest features:

    You can take advantage of pytest’s features such as fixtures, parametrization, and more to write effective tests. For more details, refer to the pytest documentation and pytest-django documentation.

By following these steps, you can effectively use pytest with Django and take advantage of pytest's advanced testing capabilities.


Folder Structure

When using pytest with Django, your project structure can be flexible, but a common and recommended approach is to organize your tests in a way that aligns with Django's app structure. Below is an example of a typical folder structure for a Django project using pytest, with an emphasis on where you might place your test files:

myproject/
├── myproject/
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── myapp/
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── models.py
│   ├── tests/
│   │   ├── __init__.py
│   │   ├── test_models.py
│   │   ├── test_views.py
│   │   ├── test_forms.py
│   │   └── conftest.py
│   ├── views.py
│   ├── urls.py
│   └── migrations/
│       └── __init__.py
├── manage.py
└── pytest.ini
  • myproject/: The root directory of your Django project.

    • myproject/: This directory contains Django settings and configuration files.
    • manage.py: The command-line utility for managing your Django project.
    • pytest.ini: Configuration file for pytest.
    • myapp/: A Django application within your project.
  • tests/: Directory for test files.

    • __init__.py: This file makes the tests directory a package.
    • test_models.py: Contains tests for your Django models.
    • test_views.py: Contains tests for your views.
    • test_forms.py: Contains tests for your forms (if any).
    • conftest.py: Optional file for defining pytest fixtures and hooks specific to this app.
  1. Organizing Tests:

    • Models: Put tests related to Django models in test_models.py.
    • Views: Place tests related to Django views in test_views.py.
    • Forms: Put form-related tests in test_forms.py.
    • You can add more test files as needed, organizing them by functionality.
  2. Fixtures:

    • Define reusable fixtures in conftest.py for the specific app. This file can be used to set up any test data or configurations needed for your tests.
  3. pytest.ini Configuration:

    • The pytest.ini file at the root specifies the Django settings module and other configurations for pytest.

This structure helps keep tests organized and manageable, making it easier to maintain and scale as your project grows.


Advanced Folder Structure

If you have organized your Django apps inside a custom_apps directory, you'll need to ensure that Django can find these apps correctly and that pytest can run the tests.

Here’s a step-by-step guide to create a simple pytest setup to test if everything is configured correctly:

  1. Directory Structure

    Assuming your custom_apps directory is at the same level as manage.py, your project structure might look something like this:

    myproject/
    ├── myproject/
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── custom_apps/
    │   ├── app1/
    │   │   ├── __init__.py
    │   │   ├── models.py
    │   │   ├── views.py
    │   │   ├── tests/
    │   │   │   ├── __init__.py
    │   │   │   └── test_sample.py
    │   │   └── apps.py
    │   └── app2/
    │       ├── __init__.py
    │       ├── models.py
    │       ├── views.py
    │       ├── tests/
    │       │   ├── __init__.py
    │       │   └── test_sample.py
    │       └── apps.py
    ├── manage.py
    └── pytest.ini
    
  2. Update settings.py

    Ensure that your Django settings file (settings.py) is aware of the apps in custom_apps. You need to update the INSTALLED_APPS list to include the apps with their full path.

    # myproject/settings.py
    INSTALLED_APPS = [
        ...
        'custom_apps.app1',
        'custom_apps.app2',
    ]
    
  3. Create a Simple Test

    Let’s create a simple test case in one of your apps. We’ll use app1 for this example. In the tests directory of app1, create a file named test_sample.py.

    # custom_apps/app1/tests/test_sample.py
    
    import pytest
    
    def test_sample():
        assert 1 + 1 == 2
    
  4. Create pytest.ini Configuration

    Create or update the pytest.ini file in the root directory of your project to include the Django settings module.

    # pytest.ini
    
    [pytest]
    DJANGO_SETTINGS_MODULE = myproject.settings
    python_files = tests.py test_*.py *_test.py
    
  5. Run the Tests

    Navigate to the root directory of your project (where manage.py and pytest.ini are located) and run pytest:

    pytest
    
Summary

This setup ensures that pytest will discover and run the tests located in your custom_apps directory. If everything is configured correctly, you should see the output from pytest, indicating whether the tests passed or failed.

If you encounter any issues:

  • Ensure pytest-django is installed (pip install pytest-django).
  • Make sure the Django settings module is correctly specified in pytest.ini.
  • Verify that the apps are correctly listed in INSTALLED_APPS.

This simple setup should help you confirm that pytest is running correctly with your Django project.


Why pytest

While Django’s default testing framework is perfectly adequate for many use cases, pytest with pytest-django has become the preferred choice for many developers due to its advanced features, ease of use, and extensibility. It offers a more modern and flexible approach to testing, making it a popular choice in the Django community.


Reference