Skip to main content
https://badge.fury.io/py/django-test-tools.svg https://codecov.io/gh/luiscberrocal/django-test-tools/branch/master/graph/badge.svg Updates Documentation Status

Simple tests tools to make testing faster and easier. Most of the tools are to do a quick scaffolding for tests.

The tools presume a naming convention:

  • Tests: Are named with the convention TestCaseModelName. For a model named Poll the test would be generated as the testing class would be TestCasePoll

  • Factories: Are named with the convention ModelName. For a model named Poll the test would be generated as the testing class would be PollFactory

  • Serializers: Are named with the convention TestCaseSerializer. For a model named Poll the test would be generated as the testing class would be PollSerializer

Compatibility matrix:

Python version

Django 1.11.x

Django 2.2.x

Django 3.0.x

3.7

x

x

x

3.6

x

x

x

Documentation

The full documentation is at https://django-test-tools.readthedocs.io.

Quickstart

Install Django Test Tools:

pip install django-test-tools

In your settings.py file add it to your INSTALLED_APPS

INSTALLED_APPS = (
    ...
    'django_test_tools.apps.DjangoTestToolsConfig',
    ...
)

Create an output folder in the root folder of you project, name it what ever you want, and add the settings variable TEST_OUTPUT_PATH pointing to it. Make sure to add this folder to your .gitignore file.

import environ

ROOT_DIR = (
    environ.Path(__file__) - 3
)  # (my_project/config/settings/base.py - 3 = alpha_clinic/)
APPS_DIR = ROOT_DIR.path("my_project")
TEST_OUTPUT_PATH = ROOT_DIR.path("output").root

Features

Factory Generator

To create Factory Boy style factories.

For a django project named polling_app with an app name poll the following command will generate the scaffolding for the tests for all the models in th app polls.

$  python manage.py generate_factories polling_app.polls

For the following models

class OperatingSystem(models.Model):
    name = models.CharField(max_length=20)
    version = models.CharField(max_length=5)
    licenses_available = models.IntegerField()
    cost = models.DecimalField(decimal_places=2, max_digits=7)

    class Meta:
        unique_together = ('name', 'version')


class Server(models.Model):
    PRODUCTION = 'PROD'
    DEVELOPMENT = 'DEV'
    USE_CHOICES = ((PRODUCTION, 'Prod'),
                   (DEVELOPMENT, 'Dev'))
    name = models.CharField(max_length=20, unique=True)
    notes = models.TextField()
    virtual = models.BooleanField()
    ip_address = models.GenericIPAddressField()
    created = models.DateTimeField()
    online_date = models.DateField()
    operating_system = models.ForeignKey(OperatingSystem, related_name='servers', on_delete=models.CASCADE)
    server_id = models.CharField(max_length=6)
    use = models.CharField(max_length=4, choices=USE_CHOICES, default=DEVELOPMENT)
    comments = models.TextField(null=True, blank=True)

running python manage.py generate_factories example.servers > ./output/factories.py will create the following factories

import string

from random import randint
from pytz import timezone

from django.conf import settings

from factory import Iterator
from factory import LazyAttribute
from factory import SubFactory
from factory import lazy_attribute
from factory.django import DjangoModelFactory, FileField
from factory.fuzzy import FuzzyText, FuzzyInteger
from faker import Factory as FakerFactory

from example.servers.models import OperatingSystem, Server

faker = FakerFactory.create()


class OperatingSystemFactory(DjangoModelFactory):
    class Meta:
        model = OperatingSystem

    name = LazyAttribute(lambda x: faker.text(max_nb_chars=20))
    version = LazyAttribute(lambda x: faker.text(max_nb_chars=5))
    licenses_available = LazyAttribute(lambda o: randint(1, 100))
    cost = LazyAttribute(lambda x: faker.pydecimal(left_digits=5, right_digits=2, positive=True))

class ServerFactory(DjangoModelFactory):
    class Meta:
        model = Server

    name = LazyAttribute(lambda x: faker.text(max_nb_chars=20))
    notes = LazyAttribute(lambda x: faker.paragraph(nb_sentences=3, variable_nb_sentences=True))
    virtual = Iterator([True, False])
    ip_address = LazyAttribute(lambda o: faker.ipv4(network=False))
    created = LazyAttribute(lambda x: faker.date_time_between(start_date="-1y", end_date="now",
                                                           tzinfo=timezone(settings.TIME_ZONE)))
    online_date = LazyAttribute(lambda x: faker.date_time_between(start_date="-1y", end_date="now",
                                                           tzinfo=timezone(settings.TIME_ZONE)))
    operating_system = SubFactory(OperatingSystemFactory)
    server_id = LazyAttribute(lambda x: FuzzyText(length=6, chars=string.digits).fuzz())
    use = Iterator(Server.CHOICES, getter=lambda x: x[0])
    comments = LazyAttribute(lambda x: faker.paragraph(nb_sentences=3, variable_nb_sentences=True))

Important the use attribute is created incorrectly. When you use choices you need to manually change it to USE_CHOICES.

use = Iterator(Server.USE_CHOICES, getter=lambda x: x[0])

Model Test Case Generator

$  python manage.py generate_model_test_cases project.app

Serializer Generator

$ python manage.py generate_serializers project.app -s ModelSerializer

Writing assertions

One of the most boring steps of writing tests is checking the content of static dictionaries. You now the content of the dictionary and you need to compare it with a result.

In the following code the assertions for the data dictionary will be generated in the fn file. IMPORTANT the name of the dictionary in this case data must be the same as the second argument of the method in order to generate the correct assertions.

fn = './output/_my_assertions.py'
data = [
        {'name': 'kilo', 'password': 9999,
         'groups': ['admin', 'users'],
         'config': {'server': 'all', 'bulding': 116}},
        {'name': 'pasto', 'password': 'nogo',
         'groups': ['users'],
         'config': {'server': 'database', 'bulding': None},
         'created_date': date(2016, 1, 3),
         'modified': '2016-10-01'}
    ]
    filename = write_assertions(data, 'data', filename=fn, type_only=True,excluded_keys=['config']))

The result of this script:

self.assertEqual(len(data), 2)
self.assertEqual(len(data[0]['groups']), 2)
self.assertEqual(data[0]['groups'][0], 'admin')
self.assertEqual(data[0]['groups'][1], 'users')
self.assertEqual(data[0]['name'], 'kilo')
self.assertEqual(data[0]['password'], 9999)
self.assertEqual(len(data[1]['groups']), 1)
self.assertEqual(data[1]['groups'][0], 'users')
self.assertEqual(data[1]['name'], 'pasto')
self.assertEqual(data[1]['password'], 'nogo')

Running Tests

Does the code actually work?

source <YOURVIRTUALENV>/bin/activate
(myenv) $ python runtests.py tests

Pushing code to Pypi

  1. Setup environment

source ./venv/bin/activate
  1. Updated version. Instead of patch you could also use major o minor depending on the level of the release.

$ make patch
  1. Check the .travis.yml to make sure the versions of Django are the latests. Check in https://www.djangoproject.com/download/ for the latest versions.

  2. Check setup.py for Django and Python versions.

  3. Close the git-flow release manually.

  4. Push to repo, Travis CI should deploy to pypi

make travis-push

Credits

Tools used in rendering this package:

History

0.1.0 (2017-04-26)

  • First release on PyPI.

Metadata

Release files for django-test-tools 2.2.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-test-tools 2.2.3
File Size Uploaded Provenance
django-test-tools-2.2.3.tar.gz 41.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for django-test-tools 2.2.3
File Interpreter ABI Platform
django_test_tools-2.2.3-py2.py3-none-any.whl Python 2, Python 3 none any Details

Total release size: 92.0 kB

Release files / django-test-tools-2.2.3.tar.gz

Download URL django-test-tools-2.2.3.tar.gz
Size 41.2 kB
Tags Source
SHA-256 checksum
How to use checksums
e63021395e9df5ca82cec9d05c1e14598b1cc21534d102421b89d579785cb8fc
BLAKE2b-256 checksum
How to use checksums
d91f6b26d9ecd7584b7d530b15256eb6a53abc1bc56914eb91f886f4ef505933
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.1 CPython/3.10.12

Release files / django_test_tools-2.2.3-py2.py3-none-any.whl

Download URL django_test_tools-2.2.3-py2.py3-none-any.whl
Size 50.8 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
166c73026491f636d88c8df104e1fccd47dd633e232aeac847c4a71fa893154b
BLAKE2b-256 checksum
How to use checksums
6911d5f86209afacc94b9a1939723d8241ac15b40c0299ea5b6cc77ac871f7fc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.1 CPython/3.10.12

Security for django-test-tools 2.2.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

2.2.3 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page