Regression testing releases with Depicted (Dpxdt), Travis, & Saucelabs

Depicted is a release testing tool that compares before and after screenshots of your webpage, highlighting differences between the two.

Depicted supplements your release testing by allowing you to approve any visual changes a new release may cause.

I wrote a script during my time at Sprintly that would take a TravisCI build ID, pull related screenshots from our Saucelabs selenium tests, and upload them to a Depicted API server for comparison.

Before a new release would be deployed, we would manually run our Depicted release script and check and approve any changes.

This script was integrated as a Django management command for ease of use. Check out the full script below with comments.

Django, Redis & AWS ElastiCache primary/replica cluster

AWS’s ElastiCache service is a convenient way to launch a Redis cluster. If you’re using Django, both django-redis-cache and django-redis packages support an ElastiCache Redis instance. If you are launching ElastiCache Redis with any amount of replicas, some additional master-slave configuration is needed in your Django settings.

Here is an example of an ElastiCache Redis cluster with a primary instance and two replicas:

The following is an example of the correct settings for this cluster if you’re using django-redis-cache backend:

CACHES = {
    'default': {
        'BACKEND': 'redis_cache.RedisCache',
        'LOCATION': [
            "test-001.730tfw.0001.use1.cache.amazonaws.com:6379",
            "test-002.730tfw.0001.use1.cache.amazonaws.com:6379",
            "test-003.730tfw.0001.use1.cache.amazonaws.com:6379"
        ],
        'OPTIONS': {
            'DB': 0,
            'MASTER_CACHE': "test-001.730tfw.0001.use1.cache.amazonaws.com:6379"
        },
    }
}

https://django-redis-cache.readthedocs.io/en/latest/advanced_configuration.html#master-slave-setup

django-simple-redis-admin: Manage redis within the django admin

It’s been a while since I talked about anything i’ve been coding. A few months ago I released Django Simple Redis Admin, which allows you to manage redis cache keys within the Django admin. Something that annoys me with other django admin packages is the requirement to add database tables for their packages. django-simple-redis-admin gets around this by making a django model on the fly. No need for tables, just plug and play. Hopefully in the future i’ll be adding some filters and speeding things up. Check out django-simple-redis-admin on my GitHub page.

Ultramemcache: python-ultramemcached and django-ultramemached-cache

A few months ago I came across a package on GitHub called Ultramemcache, which was described as “Ultra fast memcache client written in highly optimized C++ with Python bindings.”

Using Ulramemcache, I modified the common python-memcached library to use Ultramemcache, making sure it could be used as a drop in replacement. Check out python-ultramemcached on my GitHub page.

I also put together a django cache backend using Ultramemcache. This currently does not require my python-ultramemcached library. Check out django-ultramemcached-cache on my GitHub page.

Django AuthenticationForm and non field errors

Here’s a quick tip for the built in Django AuthenticationForm in django.contrib.auth.forms: use the non_field_errors method when trying to display the incorrect user/pass error. The error is raised in the general clean method and is not bound to any field, so using form.errors doesn’t give you the error message itself.

{{ form.non_field_errors }}

Django forms: Adding a blank option to a required choice field

Recently I came across a problem where I had a django form choicefield that needed to be required, but also needed a blank choice in case the user didn’t see the field and incorrectly submitted the first value. I saw a stack overflow post recommending to make a clean method to check that the first choice isn’t selected. That post is here:

http://stackoverflow.com/questions/5289491/blank-option-in-required-choicefield

… but a better way to do this is to simply leave the value of the blank choice as an empty string, which will invalidate the form without any extra clean method, like below:


CHOICES_WITH_BLANK = (
    ('', '--------'),
    ('1', 'choice one'),
    ('2', 'choice two'),
)

class ChoiceForm(forms.Form):
     choice_field = forms.ChoiceField(choices=CHOICES_WITH_BLANK)

Django forms: passing variables to a modelchoicefield

So I came across the problem of needing to filter my Django ModelChoiceField queryset by a variable in my view. Specifically I needed to pass the current selected state to the ModelChoiceField queryset. The best way I found to do this is to initialize the form with my state var in the initial:

state = 'OH'
form = LocationForm(initial={'state':state})

After that, instead of creating the field the traditional way, you can append the field to the self.fields dictionary within the init, enabling you to pass the initial state variable into the queryset of the field. Here is my form:

class LocationForm(forms.Form):

    def __init__(self, *args, **kwargs):
        super(LocationForm, self).__init__(*args, **kwargs)
        self.fields.insert(len(self.fields)-1, 'location',
                           forms.ModelChoiceField(queryset=Location.objects.filter(state=self.initial['state'])))

    first_name = forms.CharField(50, label="First Name")
    last_name = forms.CharField(50, label="Last Name")
    address = forms.CharField(60, label="Street Address")
    city = forms.CharField(40, label="City")
    state = USStateField()
    zip = USZipCodeField()

Self.fields is a Django SortedDict, and it’s insert method takes the index to insert to, the key, and the value.