behave-django

repository·main·Indexed 42 days ago

https://github.com/behave/behave-django

A bridge between the behave BDD framework and the Django web framework that enables human-readable acceptance tests. It provides a Django management command `python manage.py behave`, a `PageObject` class for headless web automation using BeautifulSoup, and specialized test runners including `BehaviorDrivenTestRunner`, `ExistingDatabaseTestRunner`, and `SimpleTestRunner`.

Tokens
10.9K
Snippets
48
Records
57
Agent score
51%

What's inside behave-django

  1. Overview of behave-django

    main

    behave-django is a BDD (Behavior-Driven Development) integration for the Django web framework. It allows you to run behave scenarios against a Django application, providing features such as:

    • Web browser automation ready: Integration suitable for end-to-end testing.
    • Database transactions per scenario: Ensures test isolation by wrapping scenarios in transactions.
    • Django Test Client: Access to Django's built-in test client for simulating requests.
    • Assertion Support: Use of unittest and Django's assertion library within steps.
    • Configuration: Full support for behave command line arguments and configuration files.
    • Fixture Loading: Ability to load Django fixtures for test data setup.
    • Page Objects: Support for the Page Object pattern to organize browser automation code.
  2. Headless vs. Selenium Page Objects

    main

    It is important to distinguish between the behave-django Page Object and Selenium-based Page Objects:

    Featurebehave-django (Headless)Selenium-based Page Objects
    DriverDjango Test ClientWeb Browser (e.g. Chrome)
    SpeedSignificantly fasterSignificantly slower
    MockingEasy/PossibleDifficult/Impossible
    FocusDjango application logicBrowser compatibility/UI rendering

    Use behave-django's headless implementation when you want to test your Django application code efficiently. Use alternative libraries (like page-object or selenium-page-factory) only if you specifically need to test browser-level interactions.

  3. Important note on ORM data and scenario lifecycle

    main
    If you are providing initial data via Python code using the Django ORM (instead of JSON/XML fixtures), you must place these calls in before_scenario(), even if the data is intended to be used across an entire feature. This is because Django's LiveServerTestCase resets the test database after every scenario.
  4. Understand database transaction isolation per scenario

    main

    By default, behave-django runs each scenario inside a database transaction, mimicking Django's TestCase implementation. This ensures that any database changes made during a scenario (such as creating users or records) are automatically rolled back after the scenario completes. You do not need to manually clean up the database between scenarios.

    @given('user "{username}" exists')
    def create_user(context, username):
        # This record will be rolled back after the scenario ends
        User.objects.create_user(username=username, password='correcthorsebatterystaple')
  5. Understand the test structure

    main

    The tests/ directory is organized into several parts:

    • tests/unit: Contains unit tests.
    • tests/acceptance: Contains feature tests.
    • test_project/ and test_app/: A minimal Django project (including manage.py) used for feature tests and as a usage example.

    Running tox executes both unit and feature tests and measures coverage.

    $ tox -e py-django52
  6. Measure test coverage using the coverage CLI

    main

    The simplest way to measure code coverage in a behave-django project is to use the coverage CLI instead of calling python manage.py directly.

    1. Install coverage with TOML support:
      pip install coverage[toml]
    2. Run your BDD tests through coverage:
      coverage run manage.py behave
    3. View the coverage report in your terminal:
      coverage report --show-missing
    $ coverage run manage.py behave
    $ coverage report --show-missing
  7. Prepare your development environment for behave-django

    main

    To contribute to behave-django, fork the repository and clone it locally. You must have tox installed to run linters, tests, and documentation builds. If you use uv, it is recommended to install tox with the tox-uv plugin for better performance and easier management of multiple Python versions.

    $ git clone git@github.com:your-username/behave-django.git
    $ pip install tox
    
    # If using uv:
    $ uv tool install tox --with tox-uv
    $ uv python install 3.14 --preview --default
  8. Configure remote browsers and Selenium Hub

    main

    When running tests where the browser is in a separate container (e.g., a Selenium Grid or Docker Compose service) from the Django test server, you must configure the test server to bind to a hostname that the browser container can resolve.

    1. Define a custom TestCase and TestRunner

    Subclass BehaviorDrivenTestCase to set the host and port. The host should be the resolvable hostname (e.g., the Docker Compose service name of your Django app) rather than localhost or 0.0.0.0.

    2. Run tests with the custom runner

    Use the --runner flag to specify your custom runner class.

    3. Connect to the remote WebDriver

    In your environment.py, initialize your browser (e.g., using Splinter) to connect to the remote Selenium hub.

    4. Update Django Settings

    Ensure the chosen host is included in your Django ALLOWED_HOSTS setting, or set ALLOWED_HOSTS = ['*'] in your test settings.

    # myproject/runner.py
    from behave_django.runner import BehaviorDrivenTestRunner
    from behave_django.testcase import BehaviorDrivenTestCase
    
    
    class RemoteBrowserTestCase(BehaviorDrivenTestCase):
        # Must be resolvable from the browser container (e.g., docker-compose service name)
        host = 'myapp'
        port = 8100
    
    
    class RemoteBrowserTestRunner(BehaviorDrivenTestRunner):
        testcase_class = RemoteBrowserTestCase
    $ python manage.py behave --runner myproject.runner.RemoteBrowserTestRunner
    # features/environment.py
    from splinter.browser import Browser
    
    def before_all(context):
        context.browser = Browser(
            driver_name='remote',
            browser='chrome',
            command_executor='http://selenium-hub:4444/wd/hub',
        )
  9. Set up behave-django for a Django project

    main

    To integrate behave-django into your Django project, follow these two steps:

    1. Add behave-django to the INSTALLED_APPS list in your Django settings file.
    2. Execute your tests using the behave management command provided by Django.

    This setup allows Behave to interact with your Django environment, including managing the test database.

    # In your Django settings.py
    INSTALLED_APPS = [
        ...
        'behave_django',
        ...
    ]
  10. Access Django's Test Client via context.test

    main

    In behave-django, the underlying Django TestCase instance is attached to the context object as context.test. You can use this to access the Django test client to perform HTTP requests (GET, POST, etc.) within your step definitions.

    To persist the result of a request for use in subsequent steps, save the response object to a custom attribute on the context (e.g., context.response).

    @when('I visit "{url}"')
    def visit(context, url):
        # Access the client via context.test and save the response
        context.response = context.test.client.get(url)
  11. Execute feature tests with python manage.py behave

    main

    Run your feature tests using the Django management command. This command automatically handles the creation and destruction of the test database for your default alias.

    python manage.py behave
    $ python manage.py behave
  12. Run tests and linters using Tox

    main

    Use tox to manage test environments.

    • Use tox list to see all available environments.
    • Use tox -e <env_name> to run a specific environment (e.g., tox -e py314-django60).
    • Use tox to run all linting and tests across all supported configurations.

    Important Test Tags:

    • @failing: Used for tests that are intentionally designed to fail.
    • @requires-live-http: Used for tests that cannot run with the --simple flag. Check tox.ini for specific environment details.
    $ tox list
    $ tox -e py314-django60
    $ tox