Wednesday, August 22, 2012

pep 8 on pycharm

Pep 8 standard is a good convention to use when coding especially when working as a team.Standards and conventions make reading other peoples code easier.Getting yourself to start adhere to these  standards takes some time and effort, but by using the right tools it can take a shorter time.By the way, taking your time to learn these standards is quite worth the effort.

Pycharm is a wonderful python IDE which i would recommend to anybody doing development in python.Using pycharm you can set pep8 as an external tool, which you can invoke on any file you are currently working on to  check whether it violates any standards.This can be done this way.

Install pep8 package from the python package index

pip install pep8

go to: File > Settings > External Tools > Add new


if your using virtual env, use the path to pep8 installed in the virtualenv's bin directory.Otherwise point it to the location where pep8 is installed, use the whereis command to find it.
Now add an output filter as follows.

You can now access the command from the tools menu or conveniently right click anywhere within the file currently being edited and select the command.
The output should be quite helpful in identifying changes which need to be made.


Monday, August 6, 2012

django factory boy - better test management

Django factory boy is an excellent replacement for fixtures, most of the time you will encounter problems with maintenance of fixtures.For instance if you do migrations often, the set of fixtures will become invalid and has to be edited to fit the new schema, this can be extremely painful if you have a complex schema and lots of data.
Factory boy makes it easy to create objects when you need them for tests.For example..

lets say you have this set of models,
from django.db import models

class Owner(models.Model):
    name = models.CharField(max_length=200)
    phone = models.CharField(max_length=50)

    def __unicode__(self):
        return self.name

class Car(models.Model):
    name = models.CharField(max_length=200)
    owner = models.ForeignKey(Owner)

    def __unicode__(self):
        return self.name

Then your factories.py for these two will correspond to something like this
import factory
from models import Owner, Car

class OwnerFactory(factory.Factory):
    FACTORY_FOR = Owner
    name = 'bruce'
    phone = '+254728037573'

class CarFactory(factory.Factory):
    FACTORY_FOR = Car
    name = 'jeep'
    owner = factory.lazy_attribute(lambda a: OwnerFactory())

The tests for the factories themselves go something like this
from models import Car,Owner
from django.test.testcases import TestCase

class FactoryTestCase(TestCase):

    def test_car_factory(self):
        car = CarFactory()
        self.assertTrue(isinstance(car, Car))

    def test_owner_factory(self):
        owner = OwnerFactory()
        self.assertTrue(isinstance(owner, Owner))
Many to many fields are a bit tricky to emulate but this does the trick. For instance lets say you have this set of models.
from django.db import models

class Pizza(models.Model):
    name = models.CharField(max_length=120)
    toppings = models.ManyToManyField(Topping)

    def __unicode__(self):
        return self.name

class Topping(models.Model):
    name = models.CharField(max_length=200)

    def __unicode__(self):
        return self.name

Then your factories will go something like this.
from models import Pizza, Topping
import factory

class ToppingFactory(factory.Factory):
    FACTORY_FOR = Topping

    name = 'mushrooms'

class PizzaFactory(factory.Factory):
    FACTORY_FOR = Pizza

    name = 'mushroom delight'

    @classmethod
    def _prepare(cls, create, **kwargs):
        topping = ToppingFactory()
        pizza = super(PizzaFactory, cls)._prepare(create, **kwargs)
        pizza.toppings.add(topping)
        return pizza

So the key here is to override the _prepare method and assign the manytomanyfield objects here, since you have and instance of the object. In conclusion factories are a good alternative to fixtures when used in the right way.