Simple tests tools to make testing faster and easier.
Project description
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
Setup environment
source ./venv/bin/activate
Updated version. Instead of patch you could also use major o minor depending on the level of the release.
$ make patch
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.
Check setup.py for Django and Python versions.
Close the git-flow release manually.
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file django-test-tools-2.2.3.tar.gz
.
File metadata
- Download URL: django-test-tools-2.2.3.tar.gz
- Upload date:
- Size: 41.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.10.12
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | e63021395e9df5ca82cec9d05c1e14598b1cc21534d102421b89d579785cb8fc |
|
MD5 | 15874e0ab01c846f5edf6f9aefc3b704 |
|
BLAKE2b-256 | d91f6b26d9ecd7584b7d530b15256eb6a53abc1bc56914eb91f886f4ef505933 |
File details
Details for the file django_test_tools-2.2.3-py2.py3-none-any.whl
.
File metadata
- Download URL: django_test_tools-2.2.3-py2.py3-none-any.whl
- Upload date:
- Size: 50.8 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.10.12
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 166c73026491f636d88c8df104e1fccd47dd633e232aeac847c4a71fa893154b |
|
MD5 | 697a98d0c06fd3083e88e9200ad61393 |
|
BLAKE2b-256 | 6911d5f86209afacc94b9a1939723d8241ac15b40c0299ea5b6cc77ac871f7fc |